diff options
| -rw-r--r-- | opcode.c | 20 | ||||
| -rw-r--r-- | opcode.h | 1 | ||||
| -rw-r--r-- | simplify.c | 20 | ||||
| -rw-r--r-- | validation/optim/canonical-cmp.c | 124 |
4 files changed, 151 insertions, 14 deletions
@@ -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 , }, }; @@ -4,6 +4,7 @@ extern const struct opcode_table { int negate:8; + int swap:8; } opcode_table[]; #endif @@ -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 + */ |
