On 16/08/18 23:12, Luc Van Oostenryck wrote: > Doing a LSR(X, N) will drop the N right bits. > So any simplification that can be made when using an AND clearing > the right N bits can also be used on LSR (as if its first operand > would first be implicitly be ANDed with such a mask). > > So, in order to not duplicate complex simplifications involving > ANDs & ORs masks, merge these both function in a single one, > using the mask corresponding to the operation. > > Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> > --- > simplify.c | 56 ++++++++++++++++++++++-------------------------------- > 1 file changed, 23 insertions(+), 33 deletions(-) > > diff --git a/simplify.c b/simplify.c > index ef98b205a..ce48b3a91 100644 > --- a/simplify.c > +++ b/simplify.c > @@ -546,6 +546,24 @@ undef: > return NULL; > } > > +static int simplify_mask_or_and(struct instruction *insn, unsigned long long mask, > + pseudo_t src, pseudo_t other) > +{ > + unsigned long long omask, nmask; > + pseudo_t src2 = src->def->src2; > + > + if (!constant(src2)) > + return 0; > + omask = src2->value; > + nmask = omask & mask; > + if (nmask != 0) > + return 0; > + // replace OP(((A & M') | B), C) Huh?, should that be OP(((A & M') | B), C) & M ? and ... > + // by OP(B, C) OP(B, C) & M ? confused. ATB, Ramsay Jones > + // when (M' & M) == 0 > + return replace_pseudo(insn, &insn->src1, other); > +} > + > static long long check_shift_count(struct instruction *insn, unsigned long long uval) > { > unsigned int size = insn->size; > @@ -575,18 +593,6 @@ static long long check_shift_count(struct instruction *insn, unsigned long long > return sval; > } > > -static int simplify_or_lsr(struct instruction *insn, pseudo_t src, pseudo_t other, unsigned shift) > -{ > - // src->def->opcode == OP_AND > - pseudo_t src2 = src->def->src2; > - > - if (!constant(src2)) > - return 0; > - if (((unsigned long long) src2->value) >> shift) > - return 0; > - return replace_pseudo(insn, &insn->src1, other); > -} > - > static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long value) > { > struct instruction *def; > @@ -660,15 +666,13 @@ static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long v > case OP_LSR: > goto case_shift_shift; > case OP_OR: > - // replace ((A & M) | B) >> S > - // by (B >> S) > - // when (M >> S) == 0 > + mask = bits_mask(size - value) << value; > src = def->src1; > if (def_opcode(src) == OP_AND) > - return simplify_or_lsr(insn, src, def->src2, value); > + return simplify_mask_or_and(insn, mask, src, def->src2); > src = def->src2; > if (def_opcode(src) == OP_AND) > - return simplify_or_lsr(insn, src, def->src1, value); > + return simplify_mask_or_and(insn, mask, src, def->src1); > break; > case OP_SHL: > // replace (A << S) >> S > @@ -824,17 +828,6 @@ static int simplify_seteq_setne(struct instruction *insn, long long value) > return 0; > } > > -static int simplify_and_or_mask(struct instruction *insn, pseudo_t and, pseudo_t other, unsigned long long mask) > -{ > - struct instruction *def = and->def; > - > - if (!constant(def->src2)) > - return 0; > - if (def->src2->value & mask) > - return 0; > - return replace_pseudo(insn, &insn->src1, other); > -} > - > static int simplify_constant_mask(struct instruction *insn, unsigned long long mask) > { > pseudo_t old = insn->src1; > @@ -849,15 +842,12 @@ static int simplify_constant_mask(struct instruction *insn, unsigned long long m > osize = 1; > goto oldsize; > case OP_OR: > - // Let's handle ((A & M') | B ) & M > - // or (B | (A & M')) & M > - // when M' & M == 0 > src1 = def->src1; > src2 = def->src2; > if (def_opcode(src1) == OP_AND) > - return simplify_and_or_mask(insn, src1, src2, mask); > + return simplify_mask_or_and(insn, mask, src1, src2); > if (def_opcode(src2) == OP_AND) > - return simplify_and_or_mask(insn, src2, src1, mask); > + return simplify_mask_or_and(insn, mask, src2, src1); > break; > case OP_ZEXT: > osize = def->orig_type->bit_size; >