tree-optimization/111583 - loop distribution issue

The following conservatively fixes loop distribution to only
recognize memset/memcpy and friends when at least one element
is going to be processed.  This avoids having an unconditional
builtin call in the IL that might imply the source and destination
pointers are non-NULL when originally pointers were not always
dereferenced.

With -Os loop header copying is less likely to ensure this.

	PR tree-optimization/111583
	* tree-loop-distribution.cc (find_single_drs): Ensure the
	load/store are always executed.

	* gcc.dg/tree-ssa/pr111583-1.c: New testcase.
	* gcc.dg/tree-ssa/pr111583-2.c: Likewise.
This commit is contained in:
Richard Biener
2023-09-29 11:08:18 +02:00
parent 59cda1f952
commit 962ca7149d
3 changed files with 81 additions and 0 deletions

View File

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

View File

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

View File

@@ -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)