diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c new file mode 100644 index 00000000000..1dd8dbcf1d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-options "-Os" } */ + +short a, f, i; +static const int *e; +short *g; +long h; +int main() +{ + { + unsigned j = i; + a = 1; + for (; a; a++) { + { + long b = j, d = h; + int c = 0; + while (d--) + *(char *)b++ = c; + } + if (e) + break; + } + j && (*g)--; + const int **k = &e; + *k = 0; + } + if (f != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c new file mode 100644 index 00000000000..0ee21854552 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-options "-Os" } */ + +int b, c, d; +char e; +short f; +const unsigned short **g; +char h(char k) { + if (k) + return '0'; + return 0; +} +int l() { + b = 0; + return 1; +} +static short m(unsigned k) { + const unsigned short *n[65]; + g = &n[4]; + k || l(); + long a = k; + char i = 0; + unsigned long j = k; + while (j--) + *(char *)a++ = i; + c = h(d); + f = k; + return 0; +} +int main() { + long o = (e < 0) << 5; + m(o); + if (f != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc index a28470b66ea..39fd4402d25 100644 --- a/gcc/tree-loop-distribution.cc +++ b/gcc/tree-loop-distribution.cc @@ -1574,6 +1574,7 @@ find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_st basic_block bb_ld = NULL; basic_block bb_st = NULL; + edge exit = single_exit (loop); if (single_ld) { @@ -1589,6 +1590,14 @@ find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_st bb_ld = gimple_bb (DR_STMT (single_ld)); if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_ld)) return false; + + /* The data reference must also be executed before possibly exiting + the loop as otherwise we'd for example unconditionally execute + memset (ptr, 0, n) which even with n == 0 implies ptr is non-NULL. */ + if (bb_ld != loop->header + && (!exit + || !dominated_by_p (CDI_DOMINATORS, exit->src, bb_ld))) + return false; } if (single_st) @@ -1604,6 +1613,12 @@ find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_st bb_st = gimple_bb (DR_STMT (single_st)); if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_st)) return false; + + /* And before exiting the loop. */ + if (bb_st != loop->header + && (!exit + || !dominated_by_p (CDI_DOMINATORS, exit->src, bb_st))) + return false; } if (single_ld && single_st)