diff mbox

Fix range test optimization (PR tree-optimization/63302)

Message ID 20141016220152.GM10376@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Oct. 16, 2014, 10:01 p.m. UTC
Hi!

This patch fixes PR63302 by using proper predicate to test if
an INTEGER_CST is a not power of 2.
While the issue has been originally reported for PA, the testcase
shows the same issue on x86_64 (just with __int128 instead of long long).

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

2014-10-16  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/63302
	* tree-ssa-reassoc.c (optimize_range_tests_xor,
	optimize_range_tests_diff): Use !integer_pow2p () instead of
	tree_log2 () < 0.

	* gcc.c-torture/execute/pr63302.c: New test.


	Jakub

Comments

Richard Biener Oct. 17, 2014, 8:02 a.m. UTC | #1
On Fri, 17 Oct 2014, Jakub Jelinek wrote:

> Hi!
> 
> This patch fixes PR63302 by using proper predicate to test if
> an INTEGER_CST is a not power of 2.
> While the issue has been originally reported for PA, the testcase
> shows the same issue on x86_64 (just with __int128 instead of long long).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux on both
> 4.9 branch and trunk, ok for trunk/4.9?

Ok.

Thanks,
Richard.

> 2014-10-16  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/63302
> 	* tree-ssa-reassoc.c (optimize_range_tests_xor,
> 	optimize_range_tests_diff): Use !integer_pow2p () instead of
> 	tree_log2 () < 0.
> 
> 	* gcc.c-torture/execute/pr63302.c: New test.
> 
> --- gcc/tree-ssa-reassoc.c.jj	2014-04-22 15:05:46.000000000 +0200
> +++ gcc/tree-ssa-reassoc.c	2014-10-15 13:33:12.501190909 +0200
> @@ -2198,7 +2198,7 @@ optimize_range_tests_xor (enum tree_code
>    lowxor = fold_binary (BIT_XOR_EXPR, type, lowi, lowj);
>    if (lowxor == NULL_TREE || TREE_CODE (lowxor) != INTEGER_CST)
>      return false;
> -  if (tree_log2 (lowxor) < 0)
> +  if (!integer_pow2p (lowxor))
>      return false;
>    highxor = fold_binary (BIT_XOR_EXPR, type, highi, highj);
>    if (!tree_int_cst_equal (lowxor, highxor))
> @@ -2245,7 +2245,7 @@ optimize_range_tests_diff (enum tree_cod
>    tem1 = fold_binary (MINUS_EXPR, type, lowj, lowi);
>    if (tem1 == NULL_TREE || TREE_CODE (tem1) != INTEGER_CST)
>      return false;
> -  if (tree_log2 (tem1) < 0)
> +  if (!integer_pow2p (tem1))
>      return false;
>  
>    mask = fold_build1 (BIT_NOT_EXPR, type, tem1);
> --- gcc/testsuite/gcc.c-torture/execute/pr63302.c.jj	2014-10-15 13:33:57.075343573 +0200
> +++ gcc/testsuite/gcc.c-torture/execute/pr63302.c	2014-10-15 13:33:44.000000000 +0200
> @@ -0,0 +1,60 @@
> +/* PR tree-optimization/63302 */
> +
> +#ifdef __SIZEOF_INT128__
> +#if __SIZEOF_INT128__ * __CHAR_BIT__ == 128
> +#define USE_INT128
> +#endif
> +#endif
> +#if __SIZEOF_LONG_LONG__ * __CHAR_BIT__ == 64
> +#define USE_LLONG
> +#endif
> +
> +#ifdef USE_INT128
> +__attribute__((noinline, noclone)) int
> +foo (__int128 x)
> +{
> +  __int128 v = x & (((__int128) -1 << 63) | 0x7ff);
> + 
> +  return v == 0 || v == ((__int128) -1 << 63);
> +}
> +#endif
> +
> +#ifdef USE_LLONG
> +__attribute__((noinline, noclone)) int
> +bar (long long x)
> +{
> +  long long v = x & (((long long) -1 << 31) | 0x7ff);
> + 
> +  return v == 0 || v == ((long long) -1 << 31);
> +}
> +#endif
> +
> +int
> +main ()
> +{
> +#ifdef USE_INT128
> +  if (foo (0) != 1
> +      || foo (1) != 0
> +      || foo (0x800) != 1
> +      || foo (0x801) != 0
> +      || foo ((__int128) 1 << 63) != 0
> +      || foo ((__int128) -1 << 63) != 1
> +      || foo (((__int128) -1 << 63) | 1) != 0
> +      || foo (((__int128) -1 << 63) | 0x800) != 1
> +      || foo (((__int128) -1 << 63) | 0x801) != 0)
> +    __builtin_abort ();
> +#endif
> +#ifdef USE_LLONG
> +  if (bar (0) != 1
> +      || bar (1) != 0
> +      || bar (0x800) != 1
> +      || bar (0x801) != 0
> +      || bar (1LL << 31) != 0
> +      || bar (-1LL << 31) != 1
> +      || bar ((-1LL << 31) | 1) != 0
> +      || bar ((-1LL << 31) | 0x800) != 1
> +      || bar ((-1LL << 31) | 0x801) != 0)
> +    __builtin_abort ();
> +#endif
> +  return 0;
> +}
> 
> 	Jakub
> 
>
diff mbox

Patch

--- gcc/tree-ssa-reassoc.c.jj	2014-04-22 15:05:46.000000000 +0200
+++ gcc/tree-ssa-reassoc.c	2014-10-15 13:33:12.501190909 +0200
@@ -2198,7 +2198,7 @@  optimize_range_tests_xor (enum tree_code
   lowxor = fold_binary (BIT_XOR_EXPR, type, lowi, lowj);
   if (lowxor == NULL_TREE || TREE_CODE (lowxor) != INTEGER_CST)
     return false;
-  if (tree_log2 (lowxor) < 0)
+  if (!integer_pow2p (lowxor))
     return false;
   highxor = fold_binary (BIT_XOR_EXPR, type, highi, highj);
   if (!tree_int_cst_equal (lowxor, highxor))
@@ -2245,7 +2245,7 @@  optimize_range_tests_diff (enum tree_cod
   tem1 = fold_binary (MINUS_EXPR, type, lowj, lowi);
   if (tem1 == NULL_TREE || TREE_CODE (tem1) != INTEGER_CST)
     return false;
-  if (tree_log2 (tem1) < 0)
+  if (!integer_pow2p (tem1))
     return false;
 
   mask = fold_build1 (BIT_NOT_EXPR, type, tem1);
--- gcc/testsuite/gcc.c-torture/execute/pr63302.c.jj	2014-10-15 13:33:57.075343573 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr63302.c	2014-10-15 13:33:44.000000000 +0200
@@ -0,0 +1,60 @@ 
+/* PR tree-optimization/63302 */
+
+#ifdef __SIZEOF_INT128__
+#if __SIZEOF_INT128__ * __CHAR_BIT__ == 128
+#define USE_INT128
+#endif
+#endif
+#if __SIZEOF_LONG_LONG__ * __CHAR_BIT__ == 64
+#define USE_LLONG
+#endif
+
+#ifdef USE_INT128
+__attribute__((noinline, noclone)) int
+foo (__int128 x)
+{
+  __int128 v = x & (((__int128) -1 << 63) | 0x7ff);
+ 
+  return v == 0 || v == ((__int128) -1 << 63);
+}
+#endif
+
+#ifdef USE_LLONG
+__attribute__((noinline, noclone)) int
+bar (long long x)
+{
+  long long v = x & (((long long) -1 << 31) | 0x7ff);
+ 
+  return v == 0 || v == ((long long) -1 << 31);
+}
+#endif
+
+int
+main ()
+{
+#ifdef USE_INT128
+  if (foo (0) != 1
+      || foo (1) != 0
+      || foo (0x800) != 1
+      || foo (0x801) != 0
+      || foo ((__int128) 1 << 63) != 0
+      || foo ((__int128) -1 << 63) != 1
+      || foo (((__int128) -1 << 63) | 1) != 0
+      || foo (((__int128) -1 << 63) | 0x800) != 1
+      || foo (((__int128) -1 << 63) | 0x801) != 0)
+    __builtin_abort ();
+#endif
+#ifdef USE_LLONG
+  if (bar (0) != 1
+      || bar (1) != 0
+      || bar (0x800) != 1
+      || bar (0x801) != 0
+      || bar (1LL << 31) != 0
+      || bar (-1LL << 31) != 1
+      || bar ((-1LL << 31) | 1) != 0
+      || bar ((-1LL << 31) | 0x800) != 1
+      || bar ((-1LL << 31) | 0x801) != 0)
+    __builtin_abort ();
+#endif
+  return 0;
+}