diff mbox

Add (1 << A) & 1) folding (PR middle-end/64309)

Message ID 20141216151513.GG16332@redhat.com
State New
Headers show

Commit Message

Marek Polacek Dec. 16, 2014, 3:15 p.m. UTC
On Tue, Dec 16, 2014 at 03:08:23PM +0100, Richard Biener wrote:
> You can use
> 
> (for cmp (ne eq)
>      icmp (eq ne)
>  (simplify
>   (cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop)
>   (icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
> 
> to combine both patterns.  Btw, shoudln't it be (bit_and (...) 

Ah, we can have multiple operators to iterate (and yes, it's
documented, my bad).

> integer_each_onep)?  I'm always unsure about the complex integer case
> (maybe try a runtime testcase and see what happens - eventually we
> just don't support bit operations on them...)

Correct - we don't allow complex operands for neither shift, nor bit and.
So I left the integer_onep in there.  Thanks.

2014-12-16  Marek Polacek  <polacek@redhat.com>

	PR middle-end/64309
	* match.pd: Add ((1 << A) & 1) != 0 -> A == 0 and
	((1 << A) & 1) == 0 -> A != 0.

	* gcc.dg/pr64309.c: New test.


	Marek

Comments

Richard Biener Dec. 16, 2014, 6:15 p.m. UTC | #1
On Tue, 16 Dec 2014, Marek Polacek wrote:

> On Tue, Dec 16, 2014 at 03:08:23PM +0100, Richard Biener wrote:
> > You can use
> > 
> > (for cmp (ne eq)
> >      icmp (eq ne)
> >  (simplify
> >   (cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop)
> >   (icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
> > 
> > to combine both patterns.  Btw, shoudln't it be (bit_and (...) 
> 
> Ah, we can have multiple operators to iterate (and yes, it's
> documented, my bad).
> 
> > integer_each_onep)?  I'm always unsure about the complex integer case
> > (maybe try a runtime testcase and see what happens - eventually we
> > just don't support bit operations on them...)
> 
> Correct - we don't allow complex operands for neither shift, nor bit and.
> So I left the integer_onep in there.  Thanks.

Ok.

Thanks,
Richard.

> 2014-12-16  Marek Polacek  <polacek@redhat.com>
> 
> 	PR middle-end/64309
> 	* match.pd: Add ((1 << A) & 1) != 0 -> A == 0 and
> 	((1 << A) & 1) == 0 -> A != 0.
> 
> 	* gcc.dg/pr64309.c: New test.
> 
> diff --git gcc/match.pd gcc/match.pd
> index 083d65f..dbca99e 100644
> --- gcc/match.pd
> +++ gcc/match.pd
> @@ -599,6 +599,13 @@ along with GCC; see the file COPYING3.  If not see
>  			    build_int_cst (TREE_TYPE (@1),
>  					   element_precision (type)), @1); }))
>  
> +/* ((1 << A) & 1) != 0 -> A == 0
> +   ((1 << A) & 1) == 0 -> A != 0 */
> +(for cmp (ne eq)
> +     icmp (eq ne)
> + (simplify
> +  (cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop)
> +  (icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
>  
>  /* Simplifications of conversions.  */
>  
> diff --git gcc/testsuite/gcc.dg/pr64309.c gcc/testsuite/gcc.dg/pr64309.c
> index e69de29..710a762 100644
> --- gcc/testsuite/gcc.dg/pr64309.c
> +++ gcc/testsuite/gcc.dg/pr64309.c
> @@ -0,0 +1,66 @@
> +/* PR middle-end/64309 */
> +/* { dg-do run } */
> +/* { dg-options "-fdump-tree-original" } */
> +
> +int
> +fn1 (int n)
> +{
> +  return ((1 << n) & 1) != 0;
> +}
> +
> +int
> +fn2 (int n)
> +{
> +  return (1 & (1 << n)) != 0;
> +}
> +
> +int
> +fn3 (int n)
> +{
> +  return ((1 << n) & 1) == 0;
> +}
> +
> +int
> +fn4 (int n)
> +{
> +  return (1 & (1 << n)) == 0;
> +}
> +
> +int
> +main (void)
> +{
> +  if (fn1 (0) != 1
> +      || fn1 (1) != 0
> +      || fn1 (2) != 0
> +      || fn1 (3) != 0
> +      || fn1 (4) != 0
> +      || fn1 (5) != 0)
> +    __builtin_abort ();
> +
> +  if (fn2 (0) != 1
> +      || fn2 (1) != 0
> +      || fn2 (2) != 0
> +      || fn2 (3) != 0
> +      || fn2 (4) != 0
> +      || fn2 (5) != 0)
> +    __builtin_abort ();
> +
> +  if (fn3 (0) != 0
> +      || fn3 (1) != 1
> +      || fn3 (2) != 1
> +      || fn3 (3) != 1
> +      || fn3 (4) != 1
> +      || fn3 (5) != 1)
> +    __builtin_abort ();
> +
> +  if (fn4 (0) != 0
> +      || fn4 (1) != 1
> +      || fn4 (2) != 1
> +      || fn4 (3) != 1
> +      || fn4 (4) != 1
> +      || fn4 (5) != 1)
> +    __builtin_abort ();
> +}
> +
> +/* { dg-final { scan-tree-dump-not "(<<|>>)" "original" } } */
> +/* { dg-final { cleanup-tree-dump "original" } } */
> 
> 	Marek
> 
>
diff mbox

Patch

diff --git gcc/match.pd gcc/match.pd
index 083d65f..dbca99e 100644
--- gcc/match.pd
+++ gcc/match.pd
@@ -599,6 +599,13 @@  along with GCC; see the file COPYING3.  If not see
 			    build_int_cst (TREE_TYPE (@1),
 					   element_precision (type)), @1); }))
 
+/* ((1 << A) & 1) != 0 -> A == 0
+   ((1 << A) & 1) == 0 -> A != 0 */
+(for cmp (ne eq)
+     icmp (eq ne)
+ (simplify
+  (cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop)
+  (icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
 
 /* Simplifications of conversions.  */
 
diff --git gcc/testsuite/gcc.dg/pr64309.c gcc/testsuite/gcc.dg/pr64309.c
index e69de29..710a762 100644
--- gcc/testsuite/gcc.dg/pr64309.c
+++ gcc/testsuite/gcc.dg/pr64309.c
@@ -0,0 +1,66 @@ 
+/* PR middle-end/64309 */
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-original" } */
+
+int
+fn1 (int n)
+{
+  return ((1 << n) & 1) != 0;
+}
+
+int
+fn2 (int n)
+{
+  return (1 & (1 << n)) != 0;
+}
+
+int
+fn3 (int n)
+{
+  return ((1 << n) & 1) == 0;
+}
+
+int
+fn4 (int n)
+{
+  return (1 & (1 << n)) == 0;
+}
+
+int
+main (void)
+{
+  if (fn1 (0) != 1
+      || fn1 (1) != 0
+      || fn1 (2) != 0
+      || fn1 (3) != 0
+      || fn1 (4) != 0
+      || fn1 (5) != 0)
+    __builtin_abort ();
+
+  if (fn2 (0) != 1
+      || fn2 (1) != 0
+      || fn2 (2) != 0
+      || fn2 (3) != 0
+      || fn2 (4) != 0
+      || fn2 (5) != 0)
+    __builtin_abort ();
+
+  if (fn3 (0) != 0
+      || fn3 (1) != 1
+      || fn3 (2) != 1
+      || fn3 (3) != 1
+      || fn3 (4) != 1
+      || fn3 (5) != 1)
+    __builtin_abort ();
+
+  if (fn4 (0) != 0
+      || fn4 (1) != 1
+      || fn4 (2) != 1
+      || fn4 (3) != 1
+      || fn4 (4) != 1
+      || fn4 (5) != 1)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "(<<|>>)" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */