diff mbox series

match.pd: Optimize ~(X >> Y) to ~X >> Y if ~X can be simplified [PR96688]

Message ID 20210114090938.GV1034503@tucnak
State New
Headers show
Series match.pd: Optimize ~(X >> Y) to ~X >> Y if ~X can be simplified [PR96688] | expand

Commit Message

Jakub Jelinek Jan. 14, 2021, 9:09 a.m. UTC
Hi!

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.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-01-13  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.


	Jakub

Comments

Richard Biener Jan. 14, 2021, 10:10 a.m. UTC | #1
On Thu, 14 Jan 2021, Jakub Jelinek wrote:

> Hi!
> 
> 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.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

> 2021-01-13  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.
> 
> --- gcc/match.pd.jj	2021-01-13 15:27:13.843788907 +0100
> +++ gcc/match.pd	2021-01-13 18:01:09.706568135 +0100
> @@ -1109,6 +1109,18 @@ (define_operator_list COND_TERNARY
>  	&& 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 */
> --- gcc/testsuite/gcc.dg/tree-ssa/pr96688.c.jj	2021-01-13 19:12:26.396363212 +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr96688.c	2021-01-13 19:13:32.146628538 +0100
> @@ -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);
> +}
> --- gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c.jj	2020-01-12 11:54:37.609395365 +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c	2021-01-14 10:04:03.100243196 +0100
> @@ -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-*-* } } } */
> --- gcc/testsuite/gcc.target/i386/pr66821.c.jj	2020-01-12 11:54:37.969389933 +0100
> +++ gcc/testsuite/gcc.target/i386/pr66821.c	2021-01-14 10:04:41.210807013 +0100
> @@ -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" } } */
> 
> 	Jakub
> 
>
diff mbox series

Patch

--- gcc/match.pd.jj	2021-01-13 15:27:13.843788907 +0100
+++ gcc/match.pd	2021-01-13 18:01:09.706568135 +0100
@@ -1109,6 +1109,18 @@  (define_operator_list COND_TERNARY
 	&& 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 */
--- gcc/testsuite/gcc.dg/tree-ssa/pr96688.c.jj	2021-01-13 19:12:26.396363212 +0100
+++ gcc/testsuite/gcc.dg/tree-ssa/pr96688.c	2021-01-13 19:13:32.146628538 +0100
@@ -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);
+}
--- gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c.jj	2020-01-12 11:54:37.609395365 +0100
+++ gcc/testsuite/gcc.dg/tree-ssa/reassoc-37.c	2021-01-14 10:04:03.100243196 +0100
@@ -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-*-* } } } */
--- gcc/testsuite/gcc.target/i386/pr66821.c.jj	2020-01-12 11:54:37.969389933 +0100
+++ gcc/testsuite/gcc.target/i386/pr66821.c	2021-01-14 10:04:41.210807013 +0100
@@ -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" } } */