aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2021-01-22 23:56:32 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2021-01-26 22:51:30 +0100
commit95827edfcb2daa42fa18ce555f2c30910fdc2493 (patch)
tree662ef5ac7953c7f2c493ba60991d4eb792584ef9
parenta5a61b2e345bac65ef1c256daeb7842539ab1262 (diff)
downloadsparse-95827edfcb2daa42fa18ce555f2c30910fdc2493.tar.gz
cmps: canonicalize SEL(x > 0, a, -a) --> SEL(x >= 0, a, -a)
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@gmail.com>
-rw-r--r--simplify.c14
-rw-r--r--validation/optim/canonical-abs.c1
2 files changed, 14 insertions, 1 deletions
diff --git a/simplify.c b/simplify.c
index 10cdf50d..584078dd 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 0809a52d..1bd6d89a 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