Commit b71b7a8e by Richard Biener Committed by Richard Biener

re PR tree-optimization/71132 (gcc ICE at -O3 on valid code on x86_64-linux-gnu with “seg fault”)

2016-05-17  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/71132
	* tree-loop-distribution.c (create_rdg_cd_edges): Pass in loop.
	Only add control dependences for blocks in the loop.
	(build_rdg): Adjust.
	(generate_code_for_partition): Return whether loop should
	be destroyed and delay that.
	(distribute_loop): Likewise.
	(pass_loop_distribution::execute): Record loops to be destroyed
	and perform delayed destroying of loops.

	* gcc.dg/torture/pr71132.c: New testcase.

From-SVN: r236320
parent 3c51ad46
2016-05-17 Richard Biener <rguenther@suse.de>
PR tree-optimization/71132
* tree-loop-distribution.c (create_rdg_cd_edges): Pass in loop.
Only add control dependences for blocks in the loop.
(build_rdg): Adjust.
(generate_code_for_partition): Return whether loop should
be destroyed and delay that.
(distribute_loop): Likewise.
(pass_loop_distribution::execute): Record loops to be destroyed
and perform delayed destroying of loops.
2016-05-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com> 2016-05-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/70809 PR target/70809
......
2016-05-17 Richard Biener <rguenther@suse.de>
PR tree-optimization/71132
* gcc.dg/torture/pr71132.c: New testcase.
2016-05-17 Christophe Lyon <christophe.lyon@linaro.org> 2016-05-17 Christophe Lyon <christophe.lyon@linaro.org>
* g++.dg/inherit/think1.C: Fix dg-do and dg-skip order. * g++.dg/inherit/think1.C: Fix dg-do and dg-skip order.
......
/* { dg-do compile } */
typedef unsigned size_t;
struct {
unsigned char buf[sizeof(long)];
} a;
size_t b;
int main()
{
size_t c, i;
unsigned char *d;
for (; c < sizeof(long);)
{
d = a.buf;
b = 0;
for (; b < i; b++)
*d++ = '\0';
for (; c < b; c++)
*d++ = 'a';
c = 0;
for (; i < sizeof(long); i++)
;
}
}
...@@ -312,7 +312,7 @@ create_rdg_flow_edges (struct graph *rdg) ...@@ -312,7 +312,7 @@ create_rdg_flow_edges (struct graph *rdg)
/* Creates the edges of the reduced dependence graph RDG. */ /* Creates the edges of the reduced dependence graph RDG. */
static void static void
create_rdg_cd_edges (struct graph *rdg, control_dependences *cd) create_rdg_cd_edges (struct graph *rdg, control_dependences *cd, loop_p loop)
{ {
int i; int i;
...@@ -324,6 +324,7 @@ create_rdg_cd_edges (struct graph *rdg, control_dependences *cd) ...@@ -324,6 +324,7 @@ create_rdg_cd_edges (struct graph *rdg, control_dependences *cd)
edge_iterator ei; edge_iterator ei;
edge e; edge e;
FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds) FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
if (flow_bb_inside_loop_p (loop, e->src))
create_edge_for_control_dependence (rdg, e->src, i, cd); create_edge_for_control_dependence (rdg, e->src, i, cd);
} }
else else
...@@ -455,7 +456,7 @@ build_rdg (vec<loop_p> loop_nest, control_dependences *cd) ...@@ -455,7 +456,7 @@ build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
create_rdg_flow_edges (rdg); create_rdg_flow_edges (rdg);
if (cd) if (cd)
create_rdg_cd_edges (rdg, cd); create_rdg_cd_edges (rdg, cd, loop_nest[0]);
datarefs.release (); datarefs.release ();
...@@ -917,9 +918,9 @@ destroy_loop (struct loop *loop) ...@@ -917,9 +918,9 @@ destroy_loop (struct loop *loop)
recompute_dominator (CDI_DOMINATORS, dest)); recompute_dominator (CDI_DOMINATORS, dest));
} }
/* Generates code for PARTITION. */ /* Generates code for PARTITION. Return whether LOOP needs to be destroyed. */
static void static bool
generate_code_for_partition (struct loop *loop, generate_code_for_partition (struct loop *loop,
partition *partition, bool copy_p) partition *partition, bool copy_p)
{ {
...@@ -930,7 +931,7 @@ generate_code_for_partition (struct loop *loop, ...@@ -930,7 +931,7 @@ generate_code_for_partition (struct loop *loop,
gcc_assert (!partition_reduction_p (partition) gcc_assert (!partition_reduction_p (partition)
|| !copy_p); || !copy_p);
generate_loops_for_partition (loop, partition, copy_p); generate_loops_for_partition (loop, partition, copy_p);
return; return false;
case PKIND_MEMSET: case PKIND_MEMSET:
generate_memset_builtin (loop, partition); generate_memset_builtin (loop, partition);
...@@ -947,7 +948,8 @@ generate_code_for_partition (struct loop *loop, ...@@ -947,7 +948,8 @@ generate_code_for_partition (struct loop *loop,
/* Common tail for partitions we turn into a call. If this was the last /* Common tail for partitions we turn into a call. If this was the last
partition for which we generate code, we have to destroy the loop. */ partition for which we generate code, we have to destroy the loop. */
if (!copy_p) if (!copy_p)
destroy_loop (loop); return true;
return false;
} }
...@@ -1397,11 +1399,12 @@ pgcmp (const void *v1_, const void *v2_) ...@@ -1397,11 +1399,12 @@ pgcmp (const void *v1_, const void *v2_)
/* Distributes the code from LOOP in such a way that producer /* Distributes the code from LOOP in such a way that producer
statements are placed before consumer statements. Tries to separate statements are placed before consumer statements. Tries to separate
only the statements from STMTS into separate loops. only the statements from STMTS into separate loops.
Returns the number of distributed loops. */ Returns the number of distributed loops. Set *DESTROY_P to whether
LOOP needs to be destroyed. */
static int static int
distribute_loop (struct loop *loop, vec<gimple *> stmts, distribute_loop (struct loop *loop, vec<gimple *> stmts,
control_dependences *cd, int *nb_calls) control_dependences *cd, int *nb_calls, bool *destroy_p)
{ {
struct graph *rdg; struct graph *rdg;
partition *partition; partition *partition;
...@@ -1644,11 +1647,12 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts, ...@@ -1644,11 +1647,12 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
dump_rdg_partitions (dump_file, partitions); dump_rdg_partitions (dump_file, partitions);
*destroy_p = false;
FOR_EACH_VEC_ELT (partitions, i, partition) FOR_EACH_VEC_ELT (partitions, i, partition)
{ {
if (partition_builtin_p (partition)) if (partition_builtin_p (partition))
(*nb_calls)++; (*nb_calls)++;
generate_code_for_partition (loop, partition, i < nbp - 1); *destroy_p |= generate_code_for_partition (loop, partition, i < nbp - 1);
} }
ldist_done: ldist_done:
...@@ -1702,6 +1706,7 @@ pass_loop_distribution::execute (function *fun) ...@@ -1702,6 +1706,7 @@ pass_loop_distribution::execute (function *fun)
bool changed = false; bool changed = false;
basic_block bb; basic_block bb;
control_dependences *cd = NULL; control_dependences *cd = NULL;
auto_vec<loop_p> loops_to_be_destroyed;
FOR_ALL_BB_FN (bb, fun) FOR_ALL_BB_FN (bb, fun)
{ {
...@@ -1787,8 +1792,12 @@ out: ...@@ -1787,8 +1792,12 @@ out:
cd = new control_dependences (create_edge_list ()); cd = new control_dependences (create_edge_list ());
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);
} }
bool destroy_p;
nb_generated_loops = distribute_loop (loop, work_list, cd, nb_generated_loops = distribute_loop (loop, work_list, cd,
&nb_generated_calls); &nb_generated_calls,
&destroy_p);
if (destroy_p)
loops_to_be_destroyed.safe_push (loop);
} }
if (nb_generated_loops + nb_generated_calls > 0) if (nb_generated_loops + nb_generated_calls > 0)
...@@ -1806,6 +1815,12 @@ out: ...@@ -1806,6 +1815,12 @@ out:
if (cd) if (cd)
delete cd; delete cd;
/* Destroy loop bodies that could not be reused. Do this late as we
otherwise can end up refering to stale data in control dependences. */
unsigned i;
FOR_EACH_VEC_ELT (loops_to_be_destroyed, i, loop)
destroy_loop (loop);
if (changed) if (changed)
{ {
/* Cached scalar evolutions now may refer to wrong or non-existing /* Cached scalar evolutions now may refer to wrong or non-existing
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment