tree-optimization/114998 - use-after-free with loop distribution
When loop distribution releases a PHI node of the original IL it can end up clobbering memory that's re-used when it upon releasing its RDG resets all stmt UIDs back to -1, even those that got released. The fix is to avoid resetting UIDs based on stmts in the RDG but instead reset only those still present in the loop. PR tree-optimization/114998 * tree-loop-distribution.cc (free_rdg): Take loop argument. Reset UIDs of stmts still in the IL rather than all stmts referenced from the RDG. (loop_distribution::build_rdg): Pass loop to free_rdg. (loop_distribution::distribute_loop): Likewise. (loop_distribution::transform_reduction_loop): Likewise. * gcc.dg/torture/pr114998.c: New testcase. (cherry picked from commit 34d15a4d630a0d54eddb99bdab086c506e10dac5)
This commit is contained in:
parent
81c627d47c
commit
1e9ae50d4d
2 changed files with 53 additions and 6 deletions
35
gcc/testsuite/gcc.dg/torture/pr114998.c
Normal file
35
gcc/testsuite/gcc.dg/torture/pr114998.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-fno-tree-dce -ftree-loop-distribution" } */
|
||||
|
||||
short a, d;
|
||||
int b, c, f, g, h, i, j[2], o;
|
||||
__attribute__((const)) int s(char r);
|
||||
int main() {
|
||||
int l, m, k, n;
|
||||
if (b) {
|
||||
char p;
|
||||
for (; p >= 0; p--) {
|
||||
int e[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
|
||||
1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1,
|
||||
0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0};
|
||||
if (j[p]) {
|
||||
int q[1];
|
||||
i = o;
|
||||
o = q[h];
|
||||
if (g)
|
||||
n = d;
|
||||
m = 4;
|
||||
for (; m; m--) {
|
||||
if (l)
|
||||
k |= c;
|
||||
if (a)
|
||||
break;
|
||||
}
|
||||
}
|
||||
s(n);
|
||||
f |= b;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -778,7 +778,7 @@ loop_distribution::stmts_from_loop (class loop *loop, vec<gimple *> *stmts)
|
|||
/* Free the reduced dependence graph RDG. */
|
||||
|
||||
static void
|
||||
free_rdg (struct graph *rdg)
|
||||
free_rdg (struct graph *rdg, loop_p loop)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -792,13 +792,25 @@ free_rdg (struct graph *rdg)
|
|||
|
||||
if (v->data)
|
||||
{
|
||||
gimple_set_uid (RDGV_STMT (v), -1);
|
||||
(RDGV_DATAREFS (v)).release ();
|
||||
free (v->data);
|
||||
}
|
||||
}
|
||||
|
||||
free_graph (rdg);
|
||||
|
||||
/* Reset UIDs of stmts still in the loop. */
|
||||
basic_block *bbs = get_loop_body (loop);
|
||||
for (unsigned i = 0; i < loop->num_nodes; ++i)
|
||||
{
|
||||
basic_block bb = bbs[i];
|
||||
gimple_stmt_iterator gsi;
|
||||
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
gimple_set_uid (gsi_stmt (gsi), -1);
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
gimple_set_uid (gsi_stmt (gsi), -1);
|
||||
}
|
||||
free (bbs);
|
||||
}
|
||||
|
||||
struct graph *
|
||||
|
@ -812,7 +824,7 @@ loop_distribution::build_rdg (class loop *loop, control_dependences *cd)
|
|||
rdg = new_graph (stmts.length ());
|
||||
if (!create_rdg_vertices (rdg, stmts, loop))
|
||||
{
|
||||
free_rdg (rdg);
|
||||
free_rdg (rdg, loop);
|
||||
return NULL;
|
||||
}
|
||||
stmts.release ();
|
||||
|
@ -3062,7 +3074,7 @@ loop_distribution::distribute_loop (class loop *loop,
|
|||
"Loop %d not distributed: too many memory references.\n",
|
||||
loop->num);
|
||||
|
||||
free_rdg (rdg);
|
||||
free_rdg (rdg, loop);
|
||||
loop_nest.release ();
|
||||
free_data_refs (datarefs_vec);
|
||||
delete ddrs_table;
|
||||
|
@ -3259,7 +3271,7 @@ loop_distribution::distribute_loop (class loop *loop,
|
|||
FOR_EACH_VEC_ELT (partitions, i, partition)
|
||||
partition_free (partition);
|
||||
|
||||
free_rdg (rdg);
|
||||
free_rdg (rdg, loop);
|
||||
return nbp - *nb_calls;
|
||||
}
|
||||
|
||||
|
@ -3665,7 +3677,7 @@ loop_distribution::transform_reduction_loop (loop_p loop)
|
|||
auto_bitmap partition_stmts;
|
||||
bitmap_set_range (partition_stmts, 0, rdg->n_vertices);
|
||||
find_single_drs (loop, rdg, partition_stmts, &store_dr, &load_dr);
|
||||
free_rdg (rdg);
|
||||
free_rdg (rdg, loop);
|
||||
|
||||
/* Bail out if there is no single load. */
|
||||
if (load_dr == NULL)
|
||||
|
|
Loading…
Add table
Reference in a new issue