diff mbox series

Make nowrap_type_p honor -fwrapv-pointer

Message ID o5n3rp11-qqps-oo65-p4ns-o7722r6r1o21@fhfr.qr
State New
Headers show
Series Make nowrap_type_p honor -fwrapv-pointer | expand

Commit Message

Richard Biener Sept. 2, 2026, 2:01 p.m. UTC
nowrap_type_p guards several transforms in IVOPTs and niter
analysis but it incorrectly considers POINTER_TYPE_P as always
not wrapping.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

	* tree-ssa-loop-niter.cc (nowrap_type_p): Honor
	-fwrapv-pointer.

	* gcc.dg/torture/pr113703-3.c: New test.
	* gcc.dg/torture/pr113703-4.c: Likewise.
---
 gcc/testsuite/gcc.dg/torture/pr113703-3.c | 34 +++++++++++++++++++++++
 gcc/testsuite/gcc.dg/torture/pr113703-4.c | 32 +++++++++++++++++++++
 gcc/tree-ssa-loop-niter.cc                |  5 +---
 3 files changed, 67 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr113703-3.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr113703-4.c
diff mbox series

Patch

diff --git a/gcc/testsuite/gcc.dg/torture/pr113703-3.c b/gcc/testsuite/gcc.dg/torture/pr113703-3.c
new file mode 100644
index 00000000000..957d1d83de3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr113703-3.c
@@ -0,0 +1,34 @@ 
+/* { dg-do run } */
+/* { dg-additional-options "-fwrapv-pointer -fno-tree-vectorize -fno-tree-loop-distribute-patterns" } */
+
+#include <stdint.h>
+
+uintptr_t sum = 0;
+
+__attribute__((noipa)) void
+f (char *p, unsigned int i, unsigned int n)
+{
+  p -= i;
+  do
+    {
+      sum += (uintptr_t)p;
+      p -= 1;
+      i++;
+    }
+  while (i < n);
+}
+
+int
+main ()
+{
+  /* I is 2 and N is 8, so the loop iterates 6 times and P walks past the
+     start of the address space, which is well defined here.  Its values
+     are therefore not ordered like those of I and the counter cannot be
+     eliminated in favour of it, but IVOPTs used to do it nevertheless and
+     the loop exited at the first test.  */
+  f ((char *)4, 2, 8);
+  /* SUM is 2 + 1 + 0 - 1 - 2 - 3.  */
+  if (sum != (uintptr_t)-3)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr113703-4.c b/gcc/testsuite/gcc.dg/torture/pr113703-4.c
new file mode 100644
index 00000000000..c5f0039ea3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr113703-4.c
@@ -0,0 +1,32 @@ 
+/* { dg-do run } */
+/* { dg-additional-options "-fwrapv-pointer -fno-tree-vectorize -fno-tree-loop-distribute-patterns" } */
+
+#include <stdint.h>
+
+uintptr_t sum = 0;
+
+__attribute__((noipa)) void
+f (char *p, unsigned int i, unsigned int n)
+{
+  p += i;
+  do
+    {
+      sum += (uintptr_t)p;
+      p += 1;
+      i++;
+    }
+  while (i < n);
+}
+
+int
+main ()
+{
+  /* Mirror image of gcc.dg/torture/ivopts-lt-3.c with an increasing pointer:
+     the loop iterates 6 times and P walks past the end of the address space
+     instead of its start.  */
+  f ((char *)-4, 2, 8);
+  /* SUM is -2 - 1 + 0 + 1 + 2 + 3.  */
+  if (sum != 3)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index 0c1ebd1c7d5..fa070bb007c 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -5347,13 +5347,10 @@  n_of_executions_at_most (gimple *stmt,
 bool
 nowrap_type_p (tree type)
 {
-  if (ANY_INTEGRAL_TYPE_P (type)
+  if ((ANY_INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
       && TYPE_OVERFLOW_UNDEFINED (type))
     return true;
 
-  if (POINTER_TYPE_P (type))
-    return true;
-
   return false;
 }