On 23/08/18 23:24, Luc Van Oostenryck wrote: > The simplication of AND(SHIFT(a | b, S), M) can be done by combining s/simplication/simplification/ > the mask M with the effective mask corresponding to SHIFT(_, S). > > This intruction pattern is generated when accessing bitfields, s/intruction/instruction/ ATB, Ramsay Jones > for example, code like: > struct u { > unsigned int :2; > unsigned int f:3; > }; > int bfu(struct u s, int a) > { > s.f = a; > return s.f; > } > > is now simplified into the minimal: > bfu: > and.32 %r11 <- %arg2, $7 > ret.32 %r11 > > The simplification is done by introducing a small helper, > simplify_mask_shift(), doing the pattern matching and then calling > simplify_mask_shift_or() with the mask M. > > Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> > --- > simplify.c | 18 ++++++++++++++++++ > validation/optim/and-or-bfu.c | 1 - > validation/optim/bitfield-store-loadu.c | 1 - > 3 files changed, 18 insertions(+), 2 deletions(-) > > diff --git a/simplify.c b/simplify.c > index e398d727e..78688c7c3 100644 > --- a/simplify.c > +++ b/simplify.c > @@ -686,6 +686,21 @@ static int simplify_mask_shift_or(struct instruction *sh, struct instruction *or > return simplify_mask_or(sh, smask & mask, or); > } > > +static int simplify_mask_shift(struct instruction *sh, unsigned long long mask) > +{ > + struct instruction *inner; > + > + if (!constant(sh->src2) || sh->tainted) > + return 0; > + switch (DEF_OPCODE(inner, sh->src1)) { > + case OP_OR: > + if (!multi_users(sh->target)) > + return simplify_mask_shift_or(sh, inner, mask); > + break; > + } > + return 0; > +} > + > static long long check_shift_count(struct instruction *insn, unsigned long long uval) > { > unsigned int size = insn->size; > @@ -986,6 +1001,9 @@ static int simplify_constant_mask(struct instruction *insn, unsigned long long m > goto oldsize; > case OP_OR: > return simplify_mask_or(insn, mask, def); > + case OP_LSR: > + case OP_SHL: > + return simplify_mask_shift(def, mask); > case OP_ZEXT: > osize = def->orig_type->bit_size; > /* fall through */ > diff --git a/validation/optim/and-or-bfu.c b/validation/optim/and-or-bfu.c > index c9dcfc33e..b6a080bd1 100644 > --- a/validation/optim/and-or-bfu.c > +++ b/validation/optim/and-or-bfu.c > @@ -12,7 +12,6 @@ int bfu(struct u s, int a) > /* > * check-name: and-or-bfu > * check-command: test-linearize -Wno-decl $file > - * check-known-to-fail > * > * check-output-ignore > * check-output-pattern(1): and\\. > diff --git a/validation/optim/bitfield-store-loadu.c b/validation/optim/bitfield-store-loadu.c > index 4c289504c..7fa1593d9 100644 > --- a/validation/optim/bitfield-store-loadu.c > +++ b/validation/optim/bitfield-store-loadu.c > @@ -12,7 +12,6 @@ int foo(struct s s, int a) > /* > * check-name: bitfield-store-load unsigned > * check-command: test-linearize -Wno-decl $file > - * check-known-to-fail > * > * check-output-ignore > * check-output-excludes: shl\\. >