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@xxxxxxxxxxxxxxxxxxxx> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- simplify.c | 20 ++++++++++++++++++++ validation/optim/select-select-true-false0.c | 1 - validation/optim/select-select-true-false1.c | 1 - 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/simplify.c b/simplify.c index f2aaa52de84b..6b44d447c0a9 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 46bd7667400d..4066c2dad6fc 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 00ffdcd1bc9b..32c0364de2ba 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 -- 2.29.2