aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--simplify.c83
-rw-r--r--validation/optim/set-uimm0.c14
-rw-r--r--validation/optim/simplify-neg-add-cte.c11
-rw-r--r--validation/optim/simplify-neg-not.c9
-rw-r--r--validation/optim/simplify-neg-sub.c9
-rw-r--r--validation/optim/simplify-not-add-cte.c11
-rw-r--r--validation/optim/simplify-not-neg.c9
-rw-r--r--validation/optim/simplify-not-sub-cte.c11
-rw-r--r--validation/optim/simplify-not-xor-cte.c11
9 files changed, 163 insertions, 5 deletions
diff --git a/simplify.c b/simplify.c
index 6caf6cbc..7588e420 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1173,6 +1173,36 @@ 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;
}
return 0;
}
@@ -1451,21 +1481,64 @@ static int simplify_constant_unop(struct instruction *insn)
static int simplify_unop(struct instruction *insn)
{
+ struct instruction *def;
+ pseudo_t src = insn->src;
+
if (dead_insn(insn, &insn->src1, NULL, NULL))
return REPEAT_CSE;
- if (constant(insn->src1))
+ if (constant(src))
return simplify_constant_unop(insn);
switch (insn->opcode) {
- struct instruction *def;
-
case OP_NOT:
- if (DEF_OPCODE(def, insn->src) == OP_NOT)
+ switch (DEF_OPCODE(def, src)) {
+ case OP_ADD:
+ if (!constant(def->src2))
+ break;
+ insn->opcode = OP_SUB; // ~(x + C) --> ~C - x
+ src = eval_unop(OP_NOT, insn->size, def->src2);
+ use_pseudo(insn, def->src1, &insn->src2);
+ return replace_pseudo(insn, &insn->src1, src);
+ case OP_NEG:
+ insn->opcode = OP_SUB; // ~(-x) --> x - 1
+ insn->src2 = value_pseudo(1);
+ return replace_pseudo(insn, &insn->src1, def->src);
+ case OP_NOT: // ~(~x) --> x
return replace_with_pseudo(insn, def->src);
+ case OP_SUB:
+ if (!constant(def->src1))
+ break;
+ insn->opcode = OP_ADD; // ~(C - x) --> x + ~C
+ insn->src2 = eval_unop(OP_NOT, insn->size, def->src1);
+ return replace_pseudo(insn, &insn->src1, def->src2);
+ case OP_XOR:
+ if (!constant(def->src2))
+ break;
+ insn->opcode = OP_XOR; // ~(x ^ C) --> x ^ ~C
+ insn->src2 = eval_unop(OP_NOT, insn->size, def->src2);
+ return replace_pseudo(insn, &insn->src1, def->src1);
+ }
break;
case OP_NEG:
- if (DEF_OPCODE(def, insn->src) == OP_NEG)
+ switch (DEF_OPCODE(def, src)) {
+ case OP_ADD:
+ if (!constant(def->src2))
+ break;
+ insn->opcode = OP_SUB; // -(x + C) --> (-C - x)
+ src = eval_unop(OP_NEG, insn->size, def->src2);
+ use_pseudo(insn, def->src1, &insn->src2);
+ return replace_pseudo(insn, &insn->src1, src);
+ case OP_NEG: // -(-x) --> x
return replace_with_pseudo(insn, def->src);
+ case OP_NOT:
+ insn->opcode = OP_ADD; // -(~x) --> x + 1
+ insn->src2 = value_pseudo(1);
+ return replace_pseudo(insn, &insn->src1, def->src);
+ case OP_SUB:
+ insn->opcode = OP_SUB; // -(x - y) --> y - x
+ use_pseudo(insn, def->src1, &insn->src2);
+ return replace_pseudo(insn, &insn->src1, def->src2);
+ }
break;
default:
return 0;
diff --git a/validation/optim/set-uimm0.c b/validation/optim/set-uimm0.c
new file mode 100644
index 00000000..ded8fc82
--- /dev/null
+++ b/validation/optim/set-uimm0.c
@@ -0,0 +1,14 @@
+static _Bool setlt0(unsigned int a) { return (a < 0u) == 0; }
+static _Bool setge0(unsigned int a) { return (a >= 0u) == 1; }
+static _Bool setle0(unsigned int a) { return (a <= 0u) == (a == 0); }
+static _Bool setgt0(unsigned int a) { return (a > 0u) == (a != 0); }
+static _Bool setlt1(unsigned int a) { return (a < 1u) == (a == 0); }
+static _Bool setge1(unsigned int a) { return (a >= 1u) == (a != 0); }
+
+/*
+ * check-name: set-uimm0
+ * check-command: test-linearize $file
+ *
+ * check-output-ignore
+ * check-output-pattern(6): ret\\.1 *\\$1
+ */
diff --git a/validation/optim/simplify-neg-add-cte.c b/validation/optim/simplify-neg-add-cte.c
new file mode 100644
index 00000000..a02c474f
--- /dev/null
+++ b/validation/optim/simplify-neg-add-cte.c
@@ -0,0 +1,11 @@
+#define C 3
+
+int foo(int x) { return -(x + C) == (-3 - x); }
+
+/*
+ * check-name: simplify-neg-add-cte
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ */
diff --git a/validation/optim/simplify-neg-not.c b/validation/optim/simplify-neg-not.c
new file mode 100644
index 00000000..e92352cf
--- /dev/null
+++ b/validation/optim/simplify-neg-not.c
@@ -0,0 +1,9 @@
+int foo(int x) { return -(~x) == x + 1; }
+
+/*
+ * check-name: simplify-neg-not
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ */
diff --git a/validation/optim/simplify-neg-sub.c b/validation/optim/simplify-neg-sub.c
new file mode 100644
index 00000000..9a824f09
--- /dev/null
+++ b/validation/optim/simplify-neg-sub.c
@@ -0,0 +1,9 @@
+int foo(int x, int y) { return -(x - y) == (y - x); }
+
+/*
+ * check-name: simplify-neg-sub
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ */
diff --git a/validation/optim/simplify-not-add-cte.c b/validation/optim/simplify-not-add-cte.c
new file mode 100644
index 00000000..6594012b
--- /dev/null
+++ b/validation/optim/simplify-not-add-cte.c
@@ -0,0 +1,11 @@
+#define C 3
+
+int foo(int x) { return ~(x + C) == (~C - x); }
+
+/*
+ * check-name: simplify-not-add-cte
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ */
diff --git a/validation/optim/simplify-not-neg.c b/validation/optim/simplify-not-neg.c
new file mode 100644
index 00000000..3fd8400d
--- /dev/null
+++ b/validation/optim/simplify-not-neg.c
@@ -0,0 +1,9 @@
+int foo(int x) { return ~(-x) == (x - 1); }
+
+/*
+ * check-name: simplify-not-neg
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ */
diff --git a/validation/optim/simplify-not-sub-cte.c b/validation/optim/simplify-not-sub-cte.c
new file mode 100644
index 00000000..1ea73ece
--- /dev/null
+++ b/validation/optim/simplify-not-sub-cte.c
@@ -0,0 +1,11 @@
+#define C 3
+
+int foo(int x) { return ~(C - x) == (x + ~C); }
+
+/*
+ * check-name: simplify-not-sub-cte
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ */
diff --git a/validation/optim/simplify-not-xor-cte.c b/validation/optim/simplify-not-xor-cte.c
new file mode 100644
index 00000000..c3c803b3
--- /dev/null
+++ b/validation/optim/simplify-not-xor-cte.c
@@ -0,0 +1,11 @@
+#define C 3
+
+int foo(int x) { return ~(x ^ C) == (x ^ ~C); }
+
+/*
+ * check-name: simplify-not-xor-cte
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ */