aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-08 00:48:06 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-22 09:25:34 +0200
commit8b8a5e5501bb130900f0007126d283119512b286 (patch)
tree38048aaa11a59654a4ecce5e8bb93558ad3bb50a
parent6faa3df7a00349041436b6b17a3891425f0b8928 (diff)
downloadsparse-dev-8b8a5e5501bb130900f0007126d283119512b286.tar.gz
allow simplification of OP(((x & y) | (a & M')), K)
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 simplifications have been made. 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 swapped was not: 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@gmail.com>
-rw-r--r--simplify.c7
-rw-r--r--validation/optim/and-or-bfx.c1
-rw-r--r--validation/optim/and-or-lsrx.c1
-rw-r--r--validation/optim/and-or-maskx.c1
4 files changed, 5 insertions, 5 deletions
diff --git a/simplify.c b/simplify.c
index 0ccd7c9f..dd569007 100644
--- a/simplify.c
+++ b/simplify.c
@@ -620,11 +620,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 ed04e2d3..57a54cf5 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 0b7d8f44..31adca92 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 497c1a60..21d44e8d 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\\.