diff options
author | Jeff Law <law@redhat.com> | 2017-09-04 08:00:29 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2017-09-04 08:00:29 -0600 |
commit | 8713d0f1c46f81107ea61781e2f4dc918d0fb67d (patch) | |
tree | 48e17398703864eb4a21643c5d2da00328515093 | |
parent | 8d2b48ae9f3e1e70dfe2aaf32abb9e74594b8875 (diff) | |
download | gcc-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
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr64910-2.c | 85 | ||||
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 12 |
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), |