aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-06 21:50:31 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-22 15:58:07 +0100
commit7f03e99c7e74d9971460e42a2230de66ae6ffdcf (patch)
treefd49d57421f49f0b22b804d7ffc8f901a6a55f46
parenta49663abcf7f1a0139b403fa23856ca998ffee28 (diff)
downloadsparse-7f03e99c7e74d9971460e42a2230de66ae6ffdcf.tar.gz
not: simplify ((x cmp y) {&,|,^} (x !cmp y)) --> {0,1,1}
Simplify bitwise operations on a compare and its complement into 0 (for &) or 1 for (| and ^). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--simplify.c24
-rw-r--r--validation/optim/cse-not02.c1
2 files changed, 21 insertions, 4 deletions
diff --git a/simplify.c b/simplify.c
index b41c1557..9938a597 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1632,7 +1632,7 @@ static int simplify_compare(struct instruction *insn)
static int simplify_and_one_side(struct instruction *insn, pseudo_t *p1, pseudo_t *p2)
{
- struct instruction *def;
+ struct instruction *def, *defr = NULL;
pseudo_t src1 = *p1;
switch (DEF_OPCODE(def, src1)) {
@@ -1640,6 +1640,12 @@ static int simplify_and_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
if (def->src == *p2)
return replace_with_value(insn, 0);
break;
+ case OP_BINCMP ... OP_BINCMP_END:
+ if (DEF_OPCODE(defr, *p2) == opcode_negate(def->opcode)) {
+ if (def->src1 == defr->src1 && def->src2 == defr->src2)
+ return replace_with_value(insn, 0);
+ }
+ break;
}
return 0;
}
@@ -1652,7 +1658,7 @@ static int simplify_and(struct instruction *insn)
static int simplify_ior_one_side(struct instruction *insn, pseudo_t *p1, pseudo_t *p2)
{
- struct instruction *def;
+ struct instruction *def, *defr = NULL;
pseudo_t src1 = *p1;
switch (DEF_OPCODE(def, src1)) {
@@ -1660,6 +1666,12 @@ static int simplify_ior_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
if (def->src == *p2)
return replace_with_value(insn, bits_mask(insn->size));
break;
+ case OP_BINCMP ... OP_BINCMP_END:
+ if (DEF_OPCODE(defr, *p2) == opcode_negate(def->opcode)) {
+ if (def->src1 == defr->src1 && def->src2 == defr->src2)
+ return replace_with_value(insn, 1);
+ }
+ break;
}
return 0;
}
@@ -1672,7 +1684,7 @@ static int simplify_ior(struct instruction *insn)
static int simplify_xor_one_side(struct instruction *insn, pseudo_t *p1, pseudo_t *p2)
{
- struct instruction *def;
+ struct instruction *def, *defr = NULL;
pseudo_t src1 = *p1;
switch (DEF_OPCODE(def, src1)) {
@@ -1680,6 +1692,12 @@ static int simplify_xor_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
if (def->src == *p2)
return replace_with_value(insn, bits_mask(insn->size));
break;
+ case OP_BINCMP ... OP_BINCMP_END:
+ if (DEF_OPCODE(defr, *p2) == opcode_negate(def->opcode)) {
+ if (def->src1 == defr->src1 && def->src2 == defr->src2)
+ return replace_with_value(insn, 1);
+ }
+ break;
}
return 0;
}
diff --git a/validation/optim/cse-not02.c b/validation/optim/cse-not02.c
index aa54a375..70addebc 100644
--- a/validation/optim/cse-not02.c
+++ b/validation/optim/cse-not02.c
@@ -5,7 +5,6 @@ int xor(int a, int b) { return ((a == b) ^ (a != b)) == 1; }
/*
* check-name: cse-not02
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-returns: 1