From: Richard Biener Date: Tue, 17 May 2016 12:53:30 +0000 (+0000) Subject: re PR tree-optimization/71132 (gcc ICE at -O3 on valid code on x86_64-linux-gnu with... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b71b7a8ed8d39eb48751b6f84f41c2be45e9ed44;p=gcc.git 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 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3c6030d427a..72ea2966c1f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2016-05-17 Richard Biener + + 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 PR target/70809 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 51126cb2df2..cc3570ca7ba 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-05-17 Richard Biener + + PR tree-optimization/71132 + * gcc.dg/torture/pr71132.c: New testcase. + 2016-05-17 Christophe Lyon * g++.dg/inherit/think1.C: Fix dg-do and dg-skip order. diff --git a/gcc/testsuite/gcc.dg/torture/pr71132.c b/gcc/testsuite/gcc.dg/torture/pr71132.c new file mode 100644 index 00000000000..2991718ad3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr71132.c @@ -0,0 +1,24 @@ +/* { 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++) + ; + } +} diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index 3e1074090ac..a801348453a 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -312,7 +312,7 @@ create_rdg_flow_edges (struct graph *rdg) /* Creates the edges of the reduced dependence graph RDG. */ 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; @@ -324,6 +324,7 @@ create_rdg_cd_edges (struct graph *rdg, control_dependences *cd) edge_iterator ei; edge e; 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); } else @@ -455,7 +456,7 @@ build_rdg (vec loop_nest, control_dependences *cd) create_rdg_flow_edges (rdg); if (cd) - create_rdg_cd_edges (rdg, cd); + create_rdg_cd_edges (rdg, cd, loop_nest[0]); datarefs.release (); @@ -917,9 +918,9 @@ destroy_loop (struct loop *loop) 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, partition *partition, bool copy_p) { @@ -930,7 +931,7 @@ generate_code_for_partition (struct loop *loop, gcc_assert (!partition_reduction_p (partition) || !copy_p); generate_loops_for_partition (loop, partition, copy_p); - return; + return false; case PKIND_MEMSET: generate_memset_builtin (loop, partition); @@ -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 partition for which we generate code, we have to destroy the loop. */ if (!copy_p) - destroy_loop (loop); + return true; + return false; } @@ -1397,11 +1399,12 @@ pgcmp (const void *v1_, const void *v2_) /* Distributes the code from LOOP in such a way that producer statements are placed before consumer statements. Tries to separate 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 distribute_loop (struct loop *loop, vec stmts, - control_dependences *cd, int *nb_calls) + control_dependences *cd, int *nb_calls, bool *destroy_p) { struct graph *rdg; partition *partition; @@ -1644,11 +1647,12 @@ distribute_loop (struct loop *loop, vec stmts, if (dump_file && (dump_flags & TDF_DETAILS)) dump_rdg_partitions (dump_file, partitions); + *destroy_p = false; FOR_EACH_VEC_ELT (partitions, i, partition) { if (partition_builtin_p (partition)) (*nb_calls)++; - generate_code_for_partition (loop, partition, i < nbp - 1); + *destroy_p |= generate_code_for_partition (loop, partition, i < nbp - 1); } ldist_done: @@ -1702,6 +1706,7 @@ pass_loop_distribution::execute (function *fun) bool changed = false; basic_block bb; control_dependences *cd = NULL; + auto_vec loops_to_be_destroyed; FOR_ALL_BB_FN (bb, fun) { @@ -1787,8 +1792,12 @@ out: cd = new control_dependences (create_edge_list ()); free_dominance_info (CDI_POST_DOMINATORS); } + bool destroy_p; 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) @@ -1806,6 +1815,12 @@ out: if (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) { /* Cached scalar evolutions now may refer to wrong or non-existing