https://gcc.gnu.org/g:20897922c9b4b63333615ec01d92fcc5a5a771ea
commit r17-4022-g20897922c9b4b63333615ec01d92fcc5a5a771ea Author: Richard Biener <[email protected]> Date: Wed Sep 2 15:19:36 2026 +0200 Make nowrap_type_p honor -fwrapv-pointer nowrap_type_p guards several transforms in IVOPTs and niter analysis but it incorrectly considers POINTER_TYPE_P as always not wrapping. * 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. Diff: --- 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(-) 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 000000000000..957d1d83de3d --- /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 000000000000..c5f0039ea3b3 --- /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 0c1ebd1c7d51..fa070bb007c7 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; }
