aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2016-12-17 10:29:56 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-08 09:55:12 +0200
commitfd79461f2abe11be0aca467b77982b5c9517c9b0 (patch)
tree9bf44f7e271da6a88062879bb11054bf309a7404
parent0fa902bbcf33024cc02d0582eb8b17f97d0e6048 (diff)
downloadsparse-dev-fd79461f2abe11be0aca467b77982b5c9517c9b0.tar.gz
simplify (x & M) >> S to (x >> S) & (M >> S)
This is especially usefull when simplifying code accessing bitfields. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--simplify.c14
-rw-r--r--validation/optim/and-lsr.c1
2 files changed, 14 insertions, 1 deletions
diff --git a/simplify.c b/simplify.c
index ab715aad..455b1a04 100644
--- a/simplify.c
+++ b/simplify.c
@@ -590,6 +590,7 @@ static int simplify_or_lsr(struct instruction *insn, pseudo_t src, pseudo_t othe
static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long value)
{
struct instruction *def;
+ unsigned long long mask;
unsigned long long nval;
unsigned int size;
pseudo_t src2;
@@ -643,6 +644,19 @@ 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:
+ // replace (A & M) >> S
+ // by (A >> S) & (M >> S)
+ if (!constant(def->src2))
+ break;
+ if (nbr_users(pseudo) > 1)
+ break;
+ mask = def->src2->value;
+ def->opcode = OP_LSR;
+ def->src2 = insn->src2;
+ insn->opcode = OP_AND;
+ insn->src2 = value_pseudo(mask >> value);
+ return REPEAT_CSE;
case OP_LSR:
goto case_shift_shift;
case OP_OR:
diff --git a/validation/optim/and-lsr.c b/validation/optim/and-lsr.c
index df6b72f3..439eb822 100644
--- a/validation/optim/and-lsr.c
+++ b/validation/optim/and-lsr.c
@@ -8,7 +8,6 @@ unsigned int foo(unsigned int x)
/*
* check-name: and-lsr
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-contains: and\\..*\\$15