aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/simplify.c
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-08-07 11:14:37 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-08 09:55:12 +0200
commit0fa902bbcf33024cc02d0582eb8b17f97d0e6048 (patch)
treeba3b113a69c286c9785464310ba396ce0976815b /simplify.c
parented1e163b88d6cc2e3435474caf9c1bc5c3764096 (diff)
downloadsparse-dev-0fa902bbcf33024cc02d0582eb8b17f97d0e6048.tar.gz
simplify (x << S) >> S into x & (-1 >> S)
This transformation is especially usefull when simplifying code accessing bitfields or for other masking manipulations. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'simplify.c')
-rw-r--r--simplify.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/simplify.c b/simplify.c
index e0434425..ab715aad 100644
--- a/simplify.c
+++ b/simplify.c
@@ -656,6 +656,17 @@ static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long v
if (def_opcode(src) == OP_AND)
return simplify_or_lsr(insn, src, def->src1, value);
break;
+ case OP_SHL:
+ // replace (A << S) >> S
+ // by A & (Mask(size) >> S)
+ if (!constant(def->src2))
+ break;
+ if (def->src2->value != value)
+ break;
+ size = insn->size - value;
+ insn->opcode = OP_AND;
+ insn->src2 = value_pseudo((1ULL << size) - 1);
+ return replace_pseudo(insn, &insn->src1, def->src1);
}
break;
case OP_SHL: