When computing the absolute value using an expression like: (a > 0) ? a : -a it's irrelevant to use '>' or '>=', both will give the same result since 0 is its own negation. Canonicalize these equivalent expressions, such that OP_GE is always used. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- simplify.c | 14 ++++++++++++++ validation/optim/canonical-abs.c | 1 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/simplify.c b/simplify.c index 10cdf50dcbf1..584078ddca89 100644 --- a/simplify.c +++ b/simplify.c @@ -454,6 +454,13 @@ static inline pseudo_t is_same_op(pseudo_t src, int op, unsigned osize) return def->src; } +static bool is_negate_of(pseudo_t p, pseudo_t ref) +{ + struct instruction *def; + + return (DEF_OPCODE(def, p) == OP_NEG) && (def->src == ref); +} + /// // replace the operand of an instruction // @insn: the instruction @@ -2308,6 +2315,13 @@ static int simplify_select(struct instruction *insn) // SEL(x {<,<=} y, a, b) --> SEL(x {>=,>} y, b, a) def->opcode = opcode_negate(def->opcode); return switch_pseudo(insn, &insn->src2, insn, &insn->src3); + case OP_SET_GT: + if (one_use(cond) && is_zero(def->src2)) { + if (is_negate_of(src2, src1)) + // SEL(x > 0, a, -a) --> SEL(x >= 0, a, -a) + return replace_opcode(def, OP_SET_GE); + } + break; case OP_SEL: if (constant(def->src2) && constant(def->src3)) { // Is the def of the conditional another select? diff --git a/validation/optim/canonical-abs.c b/validation/optim/canonical-abs.c index 0809a52d445b..1bd6d89a3ad5 100644 --- a/validation/optim/canonical-abs.c +++ b/validation/optim/canonical-abs.c @@ -5,7 +5,6 @@ _Bool abs2(int a) { return (a < 0 ? -a : a) == (a <= 0 ? -a : a); } /* * check-name: canonical-abs1 * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-returns: 1 -- 2.30.0