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 --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;
}
--
2.51.0