diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-01-14 12:50:33 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-01-14 12:50:33 +0100 |
commit | 8f8762a2e8659c1db802ba001869085c1915498f (patch) | |
tree | ca73185066382b0e83e9d96cb388dd6cad1af760 /gcc | |
parent | e45c41988bfd655b1df7cff8fcf111dc6fb732e3 (diff) | |
download | gcc-8f8762a2e8659c1db802ba001869085c1915498f.zip gcc-8f8762a2e8659c1db802ba001869085c1915498f.tar.gz gcc-8f8762a2e8659c1db802ba001869085c1915498f.tar.bz2 |
match.pd: Optimize ~(X >> Y) to ~X >> Y if ~X can be simplified [PR96688]
This patch optimizes two GIMPLE operations into just one.
As mentioned in the PR, there is some risk this might create more expensive
constants, but sometimes it will make them on the other side less expensive,
it really depends on the exact value.
And if it is an important issue, we should do it in md or during expansion.
2021-01-14 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/96688
* match.pd (~(X >> Y) -> ~X >> Y): New simplification if
~X can be simplified.
* gcc.dg/tree-ssa/pr96688.c: New test.
* gcc.dg/tree-ssa/reassoc-37.c: Adjust scan-tree-dump regex.
* gcc.target/i386/pr66821.c: Likewise.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/match.pd | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr96688.c | 24 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr66821.c | 2 |
4 files changed, 38 insertions, 2 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 6f7b41f..f08ab67 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1119,6 +1119,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && wi::to_wide (@1) != wi::min_value (TYPE_PRECISION (type), SIGNED)) (minus (plus @1 { build_minus_one_cst (type); }) @0)))) + +/* ~(X >> Y) -> ~X >> Y if ~X can be simplified. */ +(simplify + (bit_not (rshift:s @0 @1)) + (if (!TYPE_UNSIGNED (TREE_TYPE (@0))) + (rshift (bit_not! @0) @1) + /* For logical right shifts, this is possible only if @0 doesn't + have MSB set and the logical right shift is changed into + arithmetic shift. */ + (if (!wi::neg_p (tree_nonzero_bits (@0))) + (with { tree stype = signed_type_for (TREE_TYPE (@0)); } + (convert (rshift (bit_not! (convert:stype @0)) @1)))))) #endif /* x + (x & 1) -> (x + 1) & ~1 */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96688.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96688.c new file mode 100644 index 0000000..acaa0f6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96688.c @@ -0,0 +1,24 @@ +/* PR tree-optimization/96688 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times " = -124 >> " 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " >> " 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " = ~" 1 "optimized" } } */ + +int +foo (int x) +{ + return ~(123 >> x); +} + +unsigned +bar (int x) +{ + return ~(123U >> x); +} + +unsigned +baz (int x) +{ + return ~(~123U >> x); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c index 624b2a8..948fa3b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c @@ -12,5 +12,5 @@ foo (int x) } /* Check if the tests have been folded into a bit test. */ -/* { dg-final { scan-tree-dump "(8784908|0x0*860c0c)" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "(8784908|-8784909|0x0*860c0c)" "optimized" { target i?86-*-* x86_64-*-* } } } */ /* { dg-final { scan-tree-dump "(<<|>>)" "optimized" { target i?86-*-* x86_64-*-* } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66821.c b/gcc/testsuite/gcc.target/i386/pr66821.c index a04e862..4195e75 100644 --- a/gcc/testsuite/gcc.target/i386/pr66821.c +++ b/gcc/testsuite/gcc.target/i386/pr66821.c @@ -11,5 +11,5 @@ foo (int x) } /* Check if the tests have been folded into a bit test. */ -/* { dg-final { scan-tree-dump "(8784908|0x0*860c0c)" "optimized" } } */ +/* { dg-final { scan-tree-dump "(8784908|-8784909|0x0*860c0c)" "optimized" } } */ /* { dg-final { scan-tree-dump "(<<|>>)" "optimized" } } */ |