diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-10-26 07:07:06 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-08 02:12:01 +0100 |
commit | 452ea1741e587b3bfd495e6ac35b47e7659abc70 (patch) | |
tree | fcdebb14de57c4ba308f9e489fbf3a76e85b0daa | |
parent | bbcc6abac7af8ac614489b676064d4c3050fd882 (diff) | |
download | sparse-452ea1741e587b3bfd495e6ac35b47e7659abc70.tar.gz |
cmp: move some code in a separate function: simplify_compare_constant()
simplify_constant_rightside() contains a few simplification
regarding unsigned compares but much more can be done for
unsigned and signed ones.
So, move the current simplification in a separate function.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | simplify.c | 74 |
1 files changed, 43 insertions, 31 deletions
@@ -1057,6 +1057,43 @@ static int simplify_seteq_setne(struct instruction *insn, long long value) return 0; } +static int simplify_compare_constant(struct instruction *insn, long long value) +{ + switch (insn->opcode) { + case OP_SET_B: + if (!value) { // (x < 0) --> 0 + return replace_with_pseudo(insn, value_pseudo(0)); + } else if (value == 1) { // (x < 1) --> (x == 0) + insn->src2 = value_pseudo(0); + insn->opcode = OP_SET_EQ; + return REPEAT_CSE; + } + break; + case OP_SET_AE: + if (!value) { // (x >= 0) --> 1 + return replace_with_pseudo(insn, value_pseudo(1)); + } else if (value == 1) { // (x >= 1) --> (x != 0) + insn->src2 = value_pseudo(0); + insn->opcode = OP_SET_NE; + return REPEAT_CSE; + } + break; + case OP_SET_BE: + if (!value) { // (x <= 0) --> (x == 0) + insn->opcode = OP_SET_EQ; + return REPEAT_CSE; + } + break; + case OP_SET_A: + if (!value) { // (x > 0) --> (x != 0) + insn->opcode = OP_SET_NE; + return REPEAT_CSE; + } + break; + } + return 0; +} + static int simplify_constant_mask(struct instruction *insn, unsigned long long mask) { pseudo_t old = insn->src1; @@ -1169,37 +1206,12 @@ static int simplify_constant_rightside(struct instruction *insn) case OP_SET_NE: case OP_SET_EQ: - return simplify_seteq_setne(insn, value); - case OP_SET_B: - if (!value) { // (x < 0) --> 0 - return replace_with_pseudo(insn, value_pseudo(0)); - } else if (value == 1) { // (x < 1) --> (x == 0) - insn->src2 = value_pseudo(0); - insn->opcode = OP_SET_EQ; - return REPEAT_CSE; - } - break; - case OP_SET_AE: - if (!value) { // (x >= 0) --> 1 - return replace_with_pseudo(insn, value_pseudo(1)); - } else if (value == 1) { // (x >= 1) --> (x != 0) - insn->src2 = value_pseudo(0); - insn->opcode = OP_SET_NE; - return REPEAT_CSE; - } - break; - case OP_SET_BE: - if (!value) { // (x <= 0) --> (x == 0) - insn->opcode = OP_SET_EQ; - return REPEAT_CSE; - } - break; - case OP_SET_A: - if (!value) { // (x > 0) --> (x != 0) - insn->opcode = OP_SET_NE; - return REPEAT_CSE; - } - break; + if ((changed = simplify_seteq_setne(insn, value))) + return changed; + /* fallthrough */ + case OP_SET_LT: case OP_SET_LE: case OP_SET_GE: case OP_SET_GT: + case OP_SET_B: case OP_SET_BE: case OP_SET_AE: case OP_SET_A: + return simplify_compare_constant(insn, value); } return 0; } |