diff mbox series

fold-const: Fix up CLZ handling in tree_call_nonnegative_warnv_p [PR115337]

Message ID Zl8X2dd4h35HO0BV@tucnak
State New
Headers show
Series fold-const: Fix up CLZ handling in tree_call_nonnegative_warnv_p [PR115337] | expand

Commit Message

Jakub Jelinek June 4, 2024, 1:34 p.m. UTC
Hi!

The function currently incorrectly assumes all the __builtin_clz* and .CLZ
calls have non-negative result.  That is the case of the former which is UB
on zero and has [0, prec-1] return value otherwise, and is the case of the
single argument .CLZ as well (again, UB on zero), but for two argument
.CLZ is the case only if the second argument is also nonnegative (or if we
know the argument can't be zero, but let's do that just in the ranger IMHO).

The following patch does that.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and 14?
For 13 and earlier, we can't use the testcase and the fold-const.cc change
would need to differentiate between __builtin_clz* vs. .CLZ and in the
latter case look at CLZ_DEFINED_VALUE_AT_ZERO.

2024-06-04  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/115337
	* fold-const.cc (tree_call_nonnegative_warnv_p) <CASE_CFN_CLZ>:
	If arg1 is non-NULL, RECURSE on it, otherwise return true.

	* gcc.dg/bitint-106.c: New test.


	Jakub

Comments

Richard Biener June 4, 2024, 1:45 p.m. UTC | #1
On Tue, 4 Jun 2024, Jakub Jelinek wrote:

> Hi!
> 
> The function currently incorrectly assumes all the __builtin_clz* and .CLZ
> calls have non-negative result.  That is the case of the former which is UB
> on zero and has [0, prec-1] return value otherwise, and is the case of the
> single argument .CLZ as well (again, UB on zero), but for two argument
> .CLZ is the case only if the second argument is also nonnegative (or if we
> know the argument can't be zero, but let's do that just in the ranger IMHO).
> 
> The following patch does that.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and 14?

OK.

Thanks,
Richard.

> For 13 and earlier, we can't use the testcase and the fold-const.cc change
> would need to differentiate between __builtin_clz* vs. .CLZ and in the
> latter case look at CLZ_DEFINED_VALUE_AT_ZERO.
> 
> 2024-06-04  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/115337
> 	* fold-const.cc (tree_call_nonnegative_warnv_p) <CASE_CFN_CLZ>:
> 	If arg1 is non-NULL, RECURSE on it, otherwise return true.
> 
> 	* gcc.dg/bitint-106.c: New test.
> 
> --- gcc/fold-const.cc.jj	2024-04-04 10:47:46.363287718 +0200
> +++ gcc/fold-const.cc	2024-06-04 10:56:57.575425348 +0200
> @@ -15241,7 +15241,6 @@ tree_call_nonnegative_warnv_p (tree type
>      CASE_CFN_FFS:
>      CASE_CFN_PARITY:
>      CASE_CFN_POPCOUNT:
> -    CASE_CFN_CLZ:
>      CASE_CFN_CLRSB:
>      case CFN_BUILT_IN_BSWAP16:
>      case CFN_BUILT_IN_BSWAP32:
> @@ -15250,6 +15249,11 @@ tree_call_nonnegative_warnv_p (tree type
>        /* Always true.  */
>        return true;
>  
> +    CASE_CFN_CLZ:
> +      if (arg1)
> +	return RECURSE (arg1);
> +      return true;
> +
>      CASE_CFN_SQRT:
>      CASE_CFN_SQRT_FN:
>        /* sqrt(-0.0) is -0.0.  */
> --- gcc/testsuite/gcc.dg/bitint-106.c.jj	2024-06-04 12:00:59.017079094 +0200
> +++ gcc/testsuite/gcc.dg/bitint-106.c	2024-06-04 12:00:41.975306632 +0200
> @@ -0,0 +1,29 @@
> +/* PR tree-optimization/115337 */
> +/* { dg-do run { target bitint } } */
> +/* { dg-options "-O2" } */
> +
> +#if __BITINT_MAXWIDTH__ >= 129
> +#define N 128
> +#else
> +#define N 63
> +#endif
> +
> +_BitInt (N) g;
> +int c;
> +
> +void
> +foo (unsigned _BitInt (N + 1) z, _BitInt (N) *ret)
> +{
> +  c = __builtin_stdc_first_leading_one (z << N);
> +  _BitInt (N) y = *(_BitInt (N) *) __builtin_memset (&g, c, 5);
> +  *ret = y;
> +}
> +
> +int
> +main ()
> +{
> +  _BitInt (N) x;
> +  foo (0, &x);
> +  if (c || g || x)
> +    __builtin_abort ();
> +}
> 
> 	Jakub
> 
>
diff mbox series

Patch

--- gcc/fold-const.cc.jj	2024-04-04 10:47:46.363287718 +0200
+++ gcc/fold-const.cc	2024-06-04 10:56:57.575425348 +0200
@@ -15241,7 +15241,6 @@  tree_call_nonnegative_warnv_p (tree type
     CASE_CFN_FFS:
     CASE_CFN_PARITY:
     CASE_CFN_POPCOUNT:
-    CASE_CFN_CLZ:
     CASE_CFN_CLRSB:
     case CFN_BUILT_IN_BSWAP16:
     case CFN_BUILT_IN_BSWAP32:
@@ -15250,6 +15249,11 @@  tree_call_nonnegative_warnv_p (tree type
       /* Always true.  */
       return true;
 
+    CASE_CFN_CLZ:
+      if (arg1)
+	return RECURSE (arg1);
+      return true;
+
     CASE_CFN_SQRT:
     CASE_CFN_SQRT_FN:
       /* sqrt(-0.0) is -0.0.  */
--- gcc/testsuite/gcc.dg/bitint-106.c.jj	2024-06-04 12:00:59.017079094 +0200
+++ gcc/testsuite/gcc.dg/bitint-106.c	2024-06-04 12:00:41.975306632 +0200
@@ -0,0 +1,29 @@ 
+/* PR tree-optimization/115337 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#if __BITINT_MAXWIDTH__ >= 129
+#define N 128
+#else
+#define N 63
+#endif
+
+_BitInt (N) g;
+int c;
+
+void
+foo (unsigned _BitInt (N + 1) z, _BitInt (N) *ret)
+{
+  c = __builtin_stdc_first_leading_one (z << N);
+  _BitInt (N) y = *(_BitInt (N) *) __builtin_memset (&g, c, 5);
+  *ret = y;
+}
+
+int
+main ()
+{
+  _BitInt (N) x;
+  foo (0, &x);
+  if (c || g || x)
+    __builtin_abort ();
+}