diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2016-12-17 10:29:56 +0100 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-08-08 09:55:12 +0200 |
| commit | fd79461f2abe11be0aca467b77982b5c9517c9b0 (patch) | |
| tree | 9bf44f7e271da6a88062879bb11054bf309a7404 | |
| parent | 0fa902bbcf33024cc02d0582eb8b17f97d0e6048 (diff) | |
| download | sparse-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.c | 14 | ||||
| -rw-r--r-- | validation/optim/and-lsr.c | 1 |
2 files changed, 14 insertions, 1 deletions
@@ -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 |
