aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2017-09-04 08:00:29 -0600
committerJeff Law <law@gcc.gnu.org>2017-09-04 08:00:29 -0600
commit8713d0f1c46f81107ea61781e2f4dc918d0fb67d (patch)
tree48e17398703864eb4a21643c5d2da00328515093 /gcc
parent8d2b48ae9f3e1e70dfe2aaf32abb9e74594b8875 (diff)
downloadgcc-8713d0f1c46f81107ea61781e2f4dc918d0fb67d.zip
gcc-8713d0f1c46f81107ea61781e2f4dc918d0fb67d.tar.gz
gcc-8713d0f1c46f81107ea61781e2f4dc918d0fb67d.tar.bz2
re PR tree-optimization/64910 (tree reassociation results in poor code)
2017-09-03 Jeff Law <law@redhat.com> PR tree-optimization/64910 * tree-ssa-reassoc.c (reassociate_bb): For bitwise binary ops, swap the first and last operand if the last is a constant. PR tree-optimization/64910 * gcc.dg/tree-ssa/pr64910-2.c: New test. From-SVN: r251659
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr64910-2.c85
-rw-r--r--gcc/tree-ssa-reassoc.c12
4 files changed, 108 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0bc8b4b..5170417 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-09-04 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/64910
+ * tree-ssa-reassoc.c (reassociate_bb): For bitwise binary ops,
+ swap the first and last operand if the last is a constant.
+
2017-09-04 Marek Polacek <polacek@redhat.com>
PR sanitizer/82072
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 45cee1f..8920c76 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-09-04 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/64910
+ * gcc.dg/tree-ssa/pr64910-2.c: New test.
+
2017-09-04 Marek Polacek <polacek@redhat.com>
PR sanitizer/82072
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr64910-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr64910-2.c
new file mode 100644
index 0000000..2e3d679
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr64910-2.c
@@ -0,0 +1,85 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-reassoc1" } */
+
+/* We want to make sure that we reassociate in a way that has the
+ constant last. With the constant last, it's more likely to result
+ in a bitfield test on targets with such capabilities. */
+
+extern void boo ();
+
+int b2b_uc (unsigned char u, unsigned char w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+
+int b2b_us (unsigned short u, unsigned short w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+
+int b2b_ui (unsigned int u, unsigned int w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+int b2b_ul (unsigned long u, unsigned long w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+int b2b_ull (unsigned long long u, unsigned long long w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+
+int b2b_sc (signed char u, signed char w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+
+int b2b_ss (signed short u, signed short w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+
+int b2b_si (signed int u, signed int w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+int b2b_sl (signed long u, signed long w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+int b2b_sll (signed long long u, signed long long w)
+{
+ if ((u & w) & 0x20)
+ boo ();
+}
+
+/* The AND of U & W should go into a temporary, when is then ANDed
+ with the constant.
+
+ First verify that we have the right number of ANDs between U and W. */
+/* { dg-final { scan-tree-dump-times "\[uw\]_\[0-9\]+.D. \& \[uw\]_\[0-9\]+.D.;" 10 "reassoc1"} } */
+
+/* Then verify that we have the right number of ANDS between a temporary
+ and the constant. */
+/* { dg-final { scan-tree-dump-times "_\[0-9]+ \& 32;" 10 "reassoc1"} } */
+
+/* Each function has one AND. It will have either a second AND or TEST. So
+ we can count the number of AND and TEST instructions. They must be 2X
+ the number of test functions in this file. */
+/* { dg-final { scan-assembler-times "and|test" 20 { target { i?86-*-* x86_64-*-*} } } } */
+
+/* Similarly on the m68k. The code for the long long tests is suboptimal,
+ which catch via the second pattern and xfail. */
+/* { dg-final { scan-assembler-times "and|btst" 20 { target { m68k-*-* } } } } */
+/* { dg-final { scan-assembler-not "or" { target { m68k-*-* } xfail { *-*-* } } } } */
+
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 561acea..7604819 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -5762,6 +5762,18 @@ reassociate_bb (basic_block bb)
fprintf (dump_file,
"Width = %d was chosen for reassociation\n", width);
+
+ /* For binary bit operations, if the last operand in
+ OPS is a constant, move it to the front. This
+ helps ensure that we generate (X & Y) & C rather
+ than (X & C) & Y. The former will often match
+ a canonical bit test when we get to RTL. */
+ if ((rhs_code == BIT_AND_EXPR
+ || rhs_code == BIT_IOR_EXPR
+ || rhs_code == BIT_XOR_EXPR)
+ && TREE_CODE (ops.last ()->op) == INTEGER_CST)
+ std::swap (*ops[0], *ops[ops_num - 1]);
+
if (width > 1
&& ops.length () > 3)
rewrite_expr_tree_parallel (as_a <gassign *> (stmt),