aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-07 01:09:07 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-07 12:08:31 +0100
commit7ccaa8a6e88a02e05cb37adc2658071947e9331c (patch)
treec7d272aee4287fe23fdf22da603e6fa2b124eb8e
parente58ddb5678f2fb1843c6871399509eacf9cc1371 (diff)
downloadsparse-7ccaa8a6e88a02e05cb37adc2658071947e9331c.tar.gz
select: simplify SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z) and its dual
If the condition of a select is also a select but with constant operands, some simplification can be done: * if the second operand is 0, the original condition can be used, * idem if the first operand is 0s but the operand must be swapped. Originally-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--simplify.c20
-rw-r--r--validation/optim/select-select-true-false0.c1
-rw-r--r--validation/optim/select-select-true-false1.c1
3 files changed, 20 insertions, 2 deletions
diff --git a/simplify.c b/simplify.c
index f2aaa52d..6b44d447 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1748,6 +1748,7 @@ 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;
@@ -1782,6 +1783,25 @@ static int simplify_select(struct instruction *insn)
kill_use(&insn->src3);
return replace_with_value(insn, 0);
}
+
+ switch (DEF_OPCODE(def, cond)) {
+ 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, 0, C), y, z) --> SEL(x, z, y)
+ if (!def->src3->value) {
+ 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);
+ }
+ }
+ break;
+ }
return 0;
}
diff --git a/validation/optim/select-select-true-false0.c b/validation/optim/select-select-true-false0.c
index 46bd7667..4066c2da 100644
--- a/validation/optim/select-select-true-false0.c
+++ b/validation/optim/select-select-true-false0.c
@@ -4,7 +4,6 @@ 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-known-to-fail
*
* 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
index 00ffdcd1..32c0364d 100644
--- a/validation/optim/select-select-true-false1.c
+++ b/validation/optim/select-select-true-false1.c
@@ -7,7 +7,6 @@ int foo(int p)
/*
* check-name: select-select-true-false1
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-returns: 1