aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-18 18:42:17 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-22 09:26:18 +0200
commitcb4bed63e19e64d62364337cca20285f782ac6fd (patch)
treeb78904af07a4813721c4e259fcaf67e2f2e03d3b
parent729be196bb860270de32ec076873c6d327f592a0 (diff)
downloadsparse-dev-cb4bed63e19e64d62364337cca20285f782ac6fd.tar.gz
simplify ((x & M) << S) when (M << S) == 0
The instructions SHL(AND(x, M), S) can be simplified to 0 if (M << S) == 0. For example code like: unsigned foo(unsigned x) { return (x & 0xfff00000) << 12; } is now simplified into: foo: ret.32 $0 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--simplify.c11
-rw-r--r--validation/optim/shl-and0.c1
2 files changed, 11 insertions, 1 deletions
diff --git a/simplify.c b/simplify.c
index b9aa88b1..54ee9421 100644
--- a/simplify.c
+++ b/simplify.c
@@ -720,6 +720,17 @@ static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long v
if (value >= size)
goto zero;
switch(DEF_OPCODE(def, pseudo)) {
+ case OP_AND:
+ // simplify (A & M) << S
+ if (!constant(def->src2))
+ break;
+ mask = bits_mask(insn->size) >> value;
+ omask = def->src2->value;
+ nmask = omask & mask;
+ if (nmask == 0)
+ return replace_with_pseudo(insn, value_pseudo(0));
+ // do not simplify into ((A << S) & (M << S))
+ break;
case OP_LSR:
// replace ((x >> S) << S)
// by (x & (-1 << S))
diff --git a/validation/optim/shl-and0.c b/validation/optim/shl-and0.c
index 289859ae..894bd882 100644
--- a/validation/optim/shl-and0.c
+++ b/validation/optim/shl-and0.c
@@ -7,7 +7,6 @@ unsigned shl_and0(unsigned x)
/*
* check-name: shl-and0
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-contains: ret\\..*\\$0$