aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-09-02 09:44:09 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2024-09-02 09:44:09 +0200
commit25d51fb7d098a9ac8880ccb2121d889815680177 (patch)
treeefd9e9c0a7b409e1fbcdc200a2fe0ec7b4282ce4 /gcc
parent9aaedfc4146c5e4b8412913a6ca4092a2731c35c (diff)
downloadgcc-25d51fb7d098a9ac8880ccb2121d889815680177.zip
gcc-25d51fb7d098a9ac8880ccb2121d889815680177.tar.gz
gcc-25d51fb7d098a9ac8880ccb2121d889815680177.tar.bz2
ranger: Fix up range computation for CLZ [PR116486]
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-range-op.cc6
-rw-r--r--gcc/testsuite/gcc.dg/bitint-109.c25
2 files changed, 29 insertions, 2 deletions
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index d1c5271..68a7df8 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -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
index 0000000..84c4314
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-109.c
@@ -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 ();
+}