On 21/08/18 22:41, Luc Van Oostenryck wrote: > In simplify_mask_or(), two calls to simplify_mask_or_and() are > made: one for each operand of the OR instruction. > These two calls are guarded by a test checking the presence of > the AND instruction. If it is the case for the first operand, > the second operand is never considered for simplification, > even if no simplications has been made. s/simplications/simplifications/ > > Fix this by testing the return value of simplify_and_or_mask() > and let's do the second call if no simplifications could be > done in the first one. > > For example, code like: > int foo(int x, int y, int a) > { > return ((a & 0xf000) | (x & y)) & 0x0fff; > } > > was expectedly simplified into: > foo: > and.32 %r5 <- %arg1, %arg2 > and.32 %r7 <- %r5, $0xfff > ret.32 %r7 > > while the same code with the operands of the OR swaped was not: s/swaped/swapped/ ATB, Ramsay Jones > int foo(int x, int y, int a) > { > return ((x & y) | (a & 0xf000)) & 0x0fff; > } > > resulted in the non-optimized: > foo: > and.32 %r3 <- %arg1, %arg2 > and.32 %r5 <- %arg3, $0xf000 > or.32 %r6 <- %r3, %r5 > and.32 %r7 <- %r6, $0xfff > ret.32 %r7 > > but now the simplification can also be done: > foo: > and.32 %r3 <- %arg1, %arg2 > and.32 %r7 <- %r3, $0xfff > ret.32 %r7 > > Note: it would be simpler to unconditionally do both calls > but this is unsafe because some of the concerned > instructions, needed in the second call, could have > been simplified away in the first one. > > Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> > --- > simplify.c | 7 +++++-- > validation/optim/and-or-bfx.c | 1 - > validation/optim/and-or-lsrx.c | 1 - > validation/optim/and-or-maskx.c | 1 - > 4 files changed, 5 insertions(+), 5 deletions(-) > > diff --git a/simplify.c b/simplify.c > index 969fd15bb..2431a90cb 100644 > --- a/simplify.c > +++ b/simplify.c > @@ -589,11 +589,14 @@ static int simplify_mask_or(struct instruction *insn, unsigned long long mask, s > { > pseudo_t src1 = or->src1; > pseudo_t src2 = or->src2; > + int rc; > > if (def_opcode(src1) == OP_AND) > - return simplify_mask_or_and(insn, mask, src1, src2); > + if ((rc = simplify_mask_or_and(insn, mask, src1, src2))) > + return rc; > if (def_opcode(src2) == OP_AND) > - return simplify_mask_or_and(insn, mask, src2, src1); > + if ((rc = simplify_mask_or_and(insn, mask, src2, src1))) > + return rc; > return 0; > } > > diff --git a/validation/optim/and-or-bfx.c b/validation/optim/and-or-bfx.c > index ed04e2d31..57a54cf5e 100644 > --- a/validation/optim/and-or-bfx.c > +++ b/validation/optim/and-or-bfx.c > @@ -11,7 +11,6 @@ void foo(struct s *p, int a, int b) > /* > * check-name: and-or-bfx > * check-command: test-linearize -Wno-decl $file > - * check-known-to-fail > * > * check-output-ignore > * check-output-pattern(2): and\\. > diff --git a/validation/optim/and-or-lsrx.c b/validation/optim/and-or-lsrx.c > index 0b7d8f445..31adca92e 100644 > --- a/validation/optim/and-or-lsrx.c > +++ b/validation/optim/and-or-lsrx.c > @@ -6,7 +6,6 @@ unsigned int foo(unsigned int x, unsigned int y, unsigned int a) > /* > * check-name: and-or-lsrx > * check-command: test-linearize -Wno-decl $file > - * check-known-to-fail > * > * check-output-ignore > * check-output-pattern(1): and\\. > diff --git a/validation/optim/and-or-maskx.c b/validation/optim/and-or-maskx.c > index 497c1a60e..21d44e8d0 100644 > --- a/validation/optim/and-or-maskx.c > +++ b/validation/optim/and-or-maskx.c > @@ -6,7 +6,6 @@ int foo(int x, int y, int a) > /* > * check-name: and-or-maskx > * check-command: test-linearize -Wno-decl $file > - * check-known-to-fail > * > * check-output-ignore > * check-output-pattern(2): and\\. >