mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
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:
30
gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c
Normal file
30
gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c
Normal 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;
|
||||
}
|
||||
36
gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c
Normal file
36
gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c
Normal 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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user