]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ranger: Fix up range computation for CLZ [PR116486]
authorJakub Jelinek <jakub@redhat.com>
Mon, 2 Sep 2024 07:44:09 +0000 (09:44 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 2 Sep 2024 07:44:09 +0000 (09:44 +0200)
The initial CLZ gimple-range-op.cc implementation handled just the
case where second argument to .CLZ is equal to prec, but in
r15-1014 I've added also handling of the -1 case.  As the following
testcase shows, incorrectly though for the case where the first argument
has [0,0] range.  If the second argument is prec, then the result should
be [prec,prec] and that was handled correctly, but when the second argument
is -1, the result should be [-1,-1] but instead it was incorrectly computed
as [prec-1,prec-1] (when second argument is prec, mini is 0 and maxi is
prec, while when second argument is -1, mini is -1 and maxi is prec-1).

Fixed thusly (the actual handling is then similar to the CTZ [0,0] case).

2024-09-02  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/116486
* gimple-range-op.cc (cfn_clz::fold_range): If lh is [0,0]
and mini is -1, return [-1,-1] range rather than [prec-1,prec-1].

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

gcc/gimple-range-op.cc
gcc/testsuite/gcc.dg/bitint-109.c [new file with mode: 0644]

index d1c527191f4adc1e41228bf1f54087db7bcd13a4..68a7df8d01bca9c5fce25ec4c5d56c24af002bba 100644 (file)
@@ -972,8 +972,10 @@ cfn_clz::fold_range (irange &r, tree type, const irange &lh,
     {
       // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec,
       // return [prec, prec] or [-1, -1], otherwise ignore the range.
-      if (maxi == prec || mini == -1)
-       mini = maxi;
+      if (maxi == prec)
+       mini = prec;
+      else if (mini == -1)
+       maxi = -1;
     }
   else if (mini >= 0)
     mini = newmini;
diff --git a/gcc/testsuite/gcc.dg/bitint-109.c b/gcc/testsuite/gcc.dg/bitint-109.c
new file mode 100644 (file)
index 0000000..84c4314
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR middle-end/116486 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2 -fno-tree-ccp" } */
+
+unsigned u;
+
+#if __BITINT_MAXWIDTH__ >= 129
+#define N 0x100000000000000000000000000000000uwb
+#else
+#define N 0xffffffffffffffffuwb
+#endif
+
+int
+foo (void)
+{
+  return __builtin_stdc_first_leading_one (u / N);
+}
+
+int
+main ()
+{
+  int x = foo ();
+  if (x)
+    __builtin_abort ();
+}