aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-10-26 07:07:06 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-08 02:12:01 +0100
commit452ea1741e587b3bfd495e6ac35b47e7659abc70 (patch)
treefcdebb14de57c4ba308f9e489fbf3a76e85b0daa
parentbbcc6abac7af8ac614489b676064d4c3050fd882 (diff)
downloadsparse-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.c74
1 files changed, 43 insertions, 31 deletions
diff --git a/simplify.c b/simplify.c
index f2aaa52d..3338b72e 100644
--- a/simplify.c
+++ b/simplify.c
@@ -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;
}