Loop splitting is fine when the control variable is of integer type, but when it is a pointer type the upper bound of the new loop is calculated incorrectly. The calculation should be guard_init + (end-beg), but instead we do guard_init - (end-beg).
Fixed thusly. Bootstrapped, regtested. OK? Andrew. 2017-03-08 Andrew Haley <a...@redhat.com> PR tree-optimization/79894 * tree-ssa-loop-split.c (compute_new_first_bound): When calculating the new upper bound, (END-BEG) should be added, not subtracted. Index: gcc/tree-ssa-loop-split.c =================================================================== --- gcc/tree-ssa-loop-split.c (revision 245948) +++ gcc/tree-ssa-loop-split.c (working copy) @@ -436,7 +436,6 @@ if (POINTER_TYPE_P (TREE_TYPE (guard_init))) { enddiff = gimple_convert (stmts, sizetype, enddiff); - enddiff = gimple_build (stmts, NEGATE_EXPR, sizetype, enddiff); newbound = gimple_build (stmts, POINTER_PLUS_EXPR, TREE_TYPE (guard_init), guard_init, enddiff); 2017-03-08 Andrew Haley <a...@redhat.com> PR tree-optimization/79894 * gcc.dg/tree-ssa/pr79943.c: New test. Index: gcc/testsuite/gcc.dg/tree-ssa/pr79943.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/pr79943.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/pr79943.c (revision 0) @@ -0,0 +1,40 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fsplit-loops -fdump-tree-lsplit-details" } */ +/* { dg-require-effective-target int32plus } */ + +#ifdef __cplusplus +extern "C" void abort (void); +#else +extern void abort (void); +#endif + +typedef struct { + int n; +} region_t; + +void set (region_t *region) __attribute__((noinline)); +void doit (region_t *beg, region_t *end, region_t *limit) + __attribute__((noinline)); + +region_t regions[10]; + +void +set (region_t *region) { + region->n = 1; +} + +void +doit (region_t *beg, region_t *end, region_t *limit) { + for (region_t *cur = beg; cur < end; cur++) { + if (cur < limit) { + set(cur); + } + } +} + +int +main (void) { + doit(®ions[0], ®ions[2], ®ions[10]); + if (regions[1].n != 1) + abort(); +}