aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-09 23:50:41 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-09 23:51:02 +0100
commit55d44f307c12fe0241d0a12e1dfe0320a54510af (patch)
treedad6270b05823b876b78ec29e39e961a12a6c6f6
parent94dbf5cc3a0789876c8c5acd937fca6c7f89900d (diff)
parentb5bbdc9c3835b62c1e67bbd1b69017bb07f57823 (diff)
downloadsparse-55d44f307c12fe0241d0a12e1dfe0320a54510af.tar.gz
Merge branch 'optim-sel' into next
* simplify SEL(SEL(...), ...) * simplify SEL(x == y, x, y) and friends * simplify SEL(x, x, x) and SEL(x, 0, x)
-rw-r--r--simplify.c59
-rw-r--r--validation/optim/call-inlined.c11
-rw-r--r--validation/optim/eqne-select.c12
-rw-r--r--validation/optim/select-constant-cond.c10
-rw-r--r--validation/optim/select-same-args.c9
-rw-r--r--validation/optim/select-select-true-false0.c10
-rw-r--r--validation/optim/select-select-true-false1.c13
-rw-r--r--validation/optim/select-select-true-true.c9
-rw-r--r--validation/optim/select-self-zero.c10
9 files changed, 122 insertions, 21 deletions
diff --git a/simplify.c b/simplify.c
index f2aaa52d..6713e8af 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1748,18 +1748,17 @@ static int simplify_cast(struct instruction *insn)
static int simplify_select(struct instruction *insn)
{
pseudo_t cond, src1, src2;
+ struct instruction *def;
cond = insn->src1;
src1 = insn->src2;
src2 = insn->src3;
- if (constant(cond) || src1 == src2) {
- pseudo_t *kill, take;
- kill_use(&insn->src1);
- take = cond->value ? src1 : src2;
- kill = cond->value ? &insn->src3 : &insn->src2;
- kill_use(kill);
- return replace_with_pseudo(insn, take);
- }
+
+ if (constant(cond))
+ return replace_with_pseudo(insn, cond->value ? src1 : src2);
+ if (src1 == src2)
+ return replace_with_pseudo(insn, src1);
+
if (constant(src1) && constant(src2)) {
long long val1 = src1->value;
long long val2 = src2->value;
@@ -1777,10 +1776,46 @@ static int simplify_select(struct instruction *insn)
return REPEAT_CSE;
}
}
- if (cond == src2 && is_zero(src1)) {
- kill_use(&insn->src1);
- kill_use(&insn->src3);
- return replace_with_value(insn, 0);
+ if (cond == src2 && is_zero(src1)) // SEL(x, 0, x) --> 0
+ return replace_with_pseudo(insn, src1);
+ if (cond == src1 && is_zero(src2)) // SEL(x, x, 0) --> x
+ return replace_with_pseudo(insn, cond);
+
+ switch (DEF_OPCODE(def, cond)) {
+ case OP_SET_EQ:
+ if (src1 == def->src1 && src2 == def->src2)
+ return replace_with_pseudo(insn, src2); // SEL(x==y,x,y) --> y
+ if (src2 == def->src1 && src1 == def->src2)
+ return replace_with_pseudo(insn, src2); // SEL(y==x,x,y) --> y
+ break;
+ case OP_SET_NE:
+ if (src1 == def->src1 && src2 == def->src2)
+ return replace_with_pseudo(insn, src1); // SEL(x!=y,x,y) --> x
+ if (src2 == def->src1 && src1 == def->src2)
+ return replace_with_pseudo(insn, src1); // SEL(y!=x,x,y) --> x
+ break;
+ case OP_SEL:
+ if (constant(def->src2) && constant(def->src3)) {
+ // Is the def of the conditional another select?
+ // And if that one results in a "zero or not", use the
+ // original conditional instead.
+ // SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z)
+ // SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond
+ // SEL(SEL(x, 0, C), y, z) --> SEL(x, z, y)
+ // SEL(SEL(x, C1, C2), y, z) --> y
+ if (!def->src3->value) {
+ if ((src1 == def->src2) && (src2 == def->src3))
+ return replace_with_pseudo(insn, cond);
+ return replace_pseudo(insn, &insn->cond, def->cond);
+ }
+ if (!def->src2->value) {
+ switch_pseudo(insn, &insn->src2, insn, &insn->src3);
+ return replace_pseudo(insn, &insn->cond, def->cond);
+ }
+ // both values must be non-zero
+ return replace_with_pseudo(insn, src1);
+ }
+ break;
}
return 0;
}
diff --git a/validation/optim/call-inlined.c b/validation/optim/call-inlined.c
index f21b3294..7f5f4e89 100644
--- a/validation/optim/call-inlined.c
+++ b/validation/optim/call-inlined.c
@@ -18,13 +18,6 @@ int foo(int a, int b, int p)
* check-name: call-inlined
* check-command: test-linearize -Wno-decl $file
*
- * check-output-start
-foo:
-.L0:
- <entry-point>
- select.32 %r10 <- %arg3, %arg3, $0
- ret.32 %r10
-
-
- * check-output-end
+ * check-output-ignore
+ * check-output-returns: %arg3
*/
diff --git a/validation/optim/eqne-select.c b/validation/optim/eqne-select.c
new file mode 100644
index 00000000..9dfd88b5
--- /dev/null
+++ b/validation/optim/eqne-select.c
@@ -0,0 +1,12 @@
+int sel_eq01(int a, int b) { return ((a == b) ? a : b) == b; }
+int sel_eq10(int a, int b) { return ((a == b) ? b : a) == a; }
+int sel_ne01(int a, int b) { return ((a != b) ? a : b) == a; }
+int sel_ne10(int a, int b) { return ((a != b) ? b : a) == b; }
+
+/*
+ * check-name: eqne-select
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-constant-cond.c b/validation/optim/select-constant-cond.c
new file mode 100644
index 00000000..a9337e2c
--- /dev/null
+++ b/validation/optim/select-constant-cond.c
@@ -0,0 +1,10 @@
+int t(int p, int a, int b) { return ((p == p) ? a : b) == a; }
+int f(int p, int a, int b) { return ((p != p) ? a : b) == b; }
+
+/*
+ * check-name: select-constant-cond
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-same-args.c b/validation/optim/select-same-args.c
new file mode 100644
index 00000000..403af471
--- /dev/null
+++ b/validation/optim/select-same-args.c
@@ -0,0 +1,9 @@
+int foo(int p, int a) { return (p ? a : a) == a; }
+
+/*
+ * check-name: select-same-args
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-select-true-false0.c b/validation/optim/select-select-true-false0.c
new file mode 100644
index 00000000..4066c2da
--- /dev/null
+++ b/validation/optim/select-select-true-false0.c
@@ -0,0 +1,10 @@
+int fw(int p, int a, int b) { return ((p ? 42 : 0) ? a : b) == ( p ? a : b); }
+int bw(int p, int a, int b) { return ((p ? 0 : 42) ? a : b) == ( p ? b : a); }
+
+/*
+ * check-name: select-select-true-false0
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-select-true-false1.c b/validation/optim/select-select-true-false1.c
new file mode 100644
index 00000000..32c0364d
--- /dev/null
+++ b/validation/optim/select-select-true-false1.c
@@ -0,0 +1,13 @@
+int foo(int p)
+{
+ int t = (p ? 42 : 0);
+ return (t ? 42 : 0) == ( p ? 42 : 0);
+}
+
+/*
+ * check-name: select-select-true-false1
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-select-true-true.c b/validation/optim/select-select-true-true.c
new file mode 100644
index 00000000..c0c26fdd
--- /dev/null
+++ b/validation/optim/select-select-true-true.c
@@ -0,0 +1,9 @@
+int foo(int p, int a, int b) { return ((p ? 42 : 43) ? a : b) == a ; }
+
+/*
+ * check-name: select-select-true-true
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-self-zero.c b/validation/optim/select-self-zero.c
new file mode 100644
index 00000000..73b3a3dc
--- /dev/null
+++ b/validation/optim/select-self-zero.c
@@ -0,0 +1,10 @@
+int sel_self0x(int x) { return (x ? 0 : x) == 0; }
+int sel_selfx0(int x) { return (x ? x : 0) == x; }
+
+/*
+ * check-name: select-self-zero
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */