aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--opcode.c20
-rw-r--r--opcode.h1
-rw-r--r--simplify.c20
-rw-r--r--validation/optim/canonical-cmp.c124
4 files changed, 151 insertions, 14 deletions
diff --git a/opcode.c b/opcode.c
index 0aed1ca1..102bef68 100644
--- a/opcode.c
+++ b/opcode.c
@@ -23,14 +23,14 @@
#include "linearize.h"
const struct opcode_table opcode_table[OP_LAST] = {
- [OP_SET_EQ] = { .negate = OP_SET_NE, },
- [OP_SET_NE] = { .negate = OP_SET_EQ, },
- [OP_SET_LT] = { .negate = OP_SET_GE, },
- [OP_SET_LE] = { .negate = OP_SET_GT, },
- [OP_SET_GE] = { .negate = OP_SET_LT, },
- [OP_SET_GT] = { .negate = OP_SET_LE, },
- [OP_SET_B ] = { .negate = OP_SET_AE, },
- [OP_SET_BE] = { .negate = OP_SET_A , },
- [OP_SET_AE] = { .negate = OP_SET_B , },
- [OP_SET_A ] = { .negate = OP_SET_BE, },
+ [OP_SET_EQ] = { .negate = OP_SET_NE, .swap = OP_SET_EQ, },
+ [OP_SET_NE] = { .negate = OP_SET_EQ, .swap = OP_SET_NE, },
+ [OP_SET_LT] = { .negate = OP_SET_GE, .swap = OP_SET_GT, },
+ [OP_SET_LE] = { .negate = OP_SET_GT, .swap = OP_SET_GE, },
+ [OP_SET_GE] = { .negate = OP_SET_LT, .swap = OP_SET_LE, },
+ [OP_SET_GT] = { .negate = OP_SET_LE, .swap = OP_SET_LT, },
+ [OP_SET_B ] = { .negate = OP_SET_AE, .swap = OP_SET_A , },
+ [OP_SET_BE] = { .negate = OP_SET_A , .swap = OP_SET_AE, },
+ [OP_SET_AE] = { .negate = OP_SET_B , .swap = OP_SET_BE, },
+ [OP_SET_A ] = { .negate = OP_SET_BE, .swap = OP_SET_B , },
};
diff --git a/opcode.h b/opcode.h
index 3a89de05..4a9b102f 100644
--- a/opcode.h
+++ b/opcode.h
@@ -4,6 +4,7 @@
extern const struct opcode_table {
int negate:8;
+ int swap:8;
} opcode_table[];
#endif
diff --git a/simplify.c b/simplify.c
index 044371bc..6ceb096b 100644
--- a/simplify.c
+++ b/simplify.c
@@ -750,6 +750,16 @@ static int canonicalize_commutative(struct instruction *insn)
return repeat_phase |= REPEAT_CSE;
}
+static int canonicalize_compare(struct instruction *insn)
+{
+ if (canonical_order(insn->src1, insn->src2))
+ return 0;
+
+ switch_pseudo(insn, &insn->src1, insn, &insn->src2);
+ insn->opcode = opcode_table[insn->opcode].swap;
+ return repeat_phase |= REPEAT_CSE;
+}
+
static inline int simple_pseudo(pseudo_t pseudo)
{
return pseudo->type == PSEUDO_VAL || pseudo->type == PSEUDO_SYM;
@@ -1158,15 +1168,17 @@ int simplify_instruction(struct instruction *insn)
canonicalize_commutative(insn);
return simplify_binop(insn);
+ case OP_SET_LE: case OP_SET_GE:
+ case OP_SET_LT: case OP_SET_GT:
+ case OP_SET_B: case OP_SET_A:
+ case OP_SET_BE: case OP_SET_AE:
+ canonicalize_compare(insn);
+ /* fall through */
case OP_SUB:
case OP_DIVU: case OP_DIVS:
case OP_MODU: case OP_MODS:
case OP_SHL:
case OP_LSR: case OP_ASR:
- case OP_SET_LE: case OP_SET_GE:
- case OP_SET_LT: case OP_SET_GT:
- case OP_SET_B: case OP_SET_A:
- case OP_SET_BE: case OP_SET_AE:
return simplify_binop(insn);
case OP_NOT: case OP_NEG:
diff --git a/validation/optim/canonical-cmp.c b/validation/optim/canonical-cmp.c
new file mode 100644
index 00000000..19b41631
--- /dev/null
+++ b/validation/optim/canonical-cmp.c
@@ -0,0 +1,124 @@
+typedef signed int sint;
+typedef unsigned int uint;
+
+sint seq(sint p, sint a) { return (123 == p) ? a : 0; }
+sint sne(sint p, sint a) { return (123 != p) ? a : 0; }
+
+sint slt(sint p, sint a) { return (123 > p) ? a : 0; }
+sint sle(sint p, sint a) { return (123 >= p) ? a : 0; }
+sint sge(sint p, sint a) { return (123 <= p) ? a : 0; }
+sint sgt(sint p, sint a) { return (123 < p) ? a : 0; }
+
+uint ueq(uint p, uint a) { return (123 == p) ? a : 0; }
+uint une(uint p, uint a) { return (123 != p) ? a : 0; }
+
+uint ubt(uint p, uint a) { return (123 > p) ? a : 0; }
+uint ube(uint p, uint a) { return (123 >= p) ? a : 0; }
+uint uae(uint p, uint a) { return (123 <= p) ? a : 0; }
+uint uat(uint p, uint a) { return (123 < p) ? a : 0; }
+
+/*
+ * check-name: canonical-cmp
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-exclude: \$123,
+ *
+ * check-output-start
+seq:
+.L0:
+ <entry-point>
+ seteq.32 %r4 <- %arg1, $123
+ select.32 %r5 <- %r4, %arg2, $0
+ ret.32 %r5
+
+
+sne:
+.L2:
+ <entry-point>
+ setne.32 %r11 <- %arg1, $123
+ select.32 %r12 <- %r11, %arg2, $0
+ ret.32 %r12
+
+
+slt:
+.L4:
+ <entry-point>
+ setlt.32 %r18 <- %arg1, $123
+ select.32 %r19 <- %r18, %arg2, $0
+ ret.32 %r19
+
+
+sle:
+.L6:
+ <entry-point>
+ setle.32 %r25 <- %arg1, $123
+ select.32 %r26 <- %r25, %arg2, $0
+ ret.32 %r26
+
+
+sge:
+.L8:
+ <entry-point>
+ setge.32 %r32 <- %arg1, $123
+ select.32 %r33 <- %r32, %arg2, $0
+ ret.32 %r33
+
+
+sgt:
+.L10:
+ <entry-point>
+ setgt.32 %r39 <- %arg1, $123
+ select.32 %r40 <- %r39, %arg2, $0
+ ret.32 %r40
+
+
+ueq:
+.L12:
+ <entry-point>
+ seteq.32 %r45 <- %arg1, $123
+ select.32 %r46 <- %r45, %arg2, $0
+ ret.32 %r46
+
+
+une:
+.L14:
+ <entry-point>
+ setne.32 %r50 <- %arg1, $123
+ select.32 %r51 <- %r50, %arg2, $0
+ ret.32 %r51
+
+
+ubt:
+.L16:
+ <entry-point>
+ setb.32 %r55 <- %arg1, $123
+ select.32 %r56 <- %r55, %arg2, $0
+ ret.32 %r56
+
+
+ube:
+.L18:
+ <entry-point>
+ setbe.32 %r60 <- %arg1, $123
+ select.32 %r61 <- %r60, %arg2, $0
+ ret.32 %r61
+
+
+uae:
+.L20:
+ <entry-point>
+ setae.32 %r65 <- %arg1, $123
+ select.32 %r66 <- %r65, %arg2, $0
+ ret.32 %r66
+
+
+uat:
+.L22:
+ <entry-point>
+ seta.32 %r70 <- %arg1, $123
+ select.32 %r71 <- %r70, %arg2, $0
+ ret.32 %r71
+
+
+ * check-output-end
+ */