From: Jan Hubicka Date: Tue, 23 Oct 2012 09:57:36 +0000 (+0200) Subject: re PR tree-optimization/54967 (ICE in check_loop_closed_ssa_use, at tree-ssa-loop... X-Git-Tag: releases/gcc-4.8.0~2623 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a7de2015dfb81f40015a95be98abe50ad7382f0;p=thirdparty%2Fgcc.git re PR tree-optimization/54967 (ICE in check_loop_closed_ssa_use, at tree-ssa-loop-manip.c:55) PR middle-end/54967 * cfgloopmanip.c (fix_bb_placements): Add loop_closed_ssa_invalidated; track basic blocks that moved out of their loops. (unloop): Likewise. (remove_path): Update. (fix_loop_placements): Update. * tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Add loop_closed_ssa_invalidated parameter; pass it around. (canonicalize_loop_induction_variables): Update loop closed SSA form if needed. (tree_unroll_loops_completely): Likewise; do irred update out of the outer loop; verify that SSA form is closed. * cfgloop.h (unrloop): Update. * gfortran.dg/pr54967.f90: New testcase. From-SVN: r192709 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 236464f4dc1d..d9c294eb2ab4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2012-10-23 Jan Hubicka + + PR middle-end/54967 + * cfgloopmanip.c (fix_bb_placements): Add loop_closed_ssa_invalidated; + track basic blocks that moved out of their loops. + (unloop): Likewise. + (remove_path): Update. + (fix_loop_placements): Update. + * tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Add + loop_closed_ssa_invalidated parameter; pass it around. + (canonicalize_loop_induction_variables): Update loop closed + SSA form if needed. + (tree_unroll_loops_completely): Likewise; do irred update out of + the outer loop; verify that SSA form is closed. + * cfgloop.h (unrloop): Update. + 2012-10-23 Terry Guo PR target/55019 diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index a48550445a37..94ad6372d284 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -321,7 +321,7 @@ extern struct loop *loopify (edge, edge, struct loop * loop_version (struct loop *, void *, basic_block *, unsigned, unsigned, unsigned, bool); extern bool remove_path (edge); -extern void unloop (struct loop *, bool *); +extern void unloop (struct loop *, bool *, bitmap); extern void scale_loop_frequencies (struct loop *, int, int); /* Induction variable analysis. */ diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 97a90bbff1d4..eae68ca43c79 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -36,7 +36,7 @@ static bool rpe_enum_p (const_basic_block, const void *); static int find_path (edge, basic_block **); static void fix_loop_placements (struct loop *, bool *); static bool fix_bb_placement (basic_block); -static void fix_bb_placements (basic_block, bool *); +static void fix_bb_placements (basic_block, bool *, bitmap); /* Checks whether basic block BB is dominated by DATA. */ static bool @@ -159,11 +159,15 @@ fix_loop_placement (struct loop *loop) successors we consider edges coming out of the loops. If the changes may invalidate the information about irreducible regions, - IRRED_INVALIDATED is set to true. */ + IRRED_INVALIDATED is set to true. + + If LOOP_CLOSED_SSA_INVLIDATED is non-zero then all basic blocks with + changed loop_father are collected there. */ static void fix_bb_placements (basic_block from, - bool *irred_invalidated) + bool *irred_invalidated, + bitmap loop_closed_ssa_invalidated) { sbitmap in_queue; basic_block *queue, *qtop, *qbeg, *qend; @@ -218,6 +222,8 @@ fix_bb_placements (basic_block from, /* Ordinary basic block. */ if (!fix_bb_placement (from)) continue; + if (loop_closed_ssa_invalidated) + bitmap_set_bit (loop_closed_ssa_invalidated, from->index); target_loop = from->loop_father; } @@ -312,7 +318,7 @@ remove_path (edge e) { f = loop_outer (l); if (dominated_by_p (CDI_DOMINATORS, l->latch, e->dest)) - unloop (l, &irred_invalidated); + unloop (l, &irred_invalidated, NULL); } /* Identify the path. */ @@ -385,7 +391,7 @@ remove_path (edge e) /* Fix placements of basic blocks inside loops and the placement of loops in the loop tree. */ - fix_bb_placements (from, &irred_invalidated); + fix_bb_placements (from, &irred_invalidated, NULL); fix_loop_placements (from->loop_father, &irred_invalidated); if (irred_invalidated @@ -892,10 +898,14 @@ loopify (edge latch_edge, edge header_edge, have no successor, which caller is expected to fix somehow. If this may cause the information about irreducible regions to become - invalid, IRRED_INVALIDATED is set to true. */ + invalid, IRRED_INVALIDATED is set to true. + + LOOP_CLOSED_SSA_INVALIDATED, if non-NULL, is a bitmap where we store + basic blocks that had non-trivial update on their loop_father.*/ void -unloop (struct loop *loop, bool *irred_invalidated) +unloop (struct loop *loop, bool *irred_invalidated, + bitmap loop_closed_ssa_invalidated) { basic_block *body; struct loop *ploop; @@ -937,7 +947,7 @@ unloop (struct loop *loop, bool *irred_invalidated) /* We do not pass IRRED_INVALIDATED to fix_bb_placements here, as even if there is an irreducible region inside the cancelled loop, the flags will be still correct. */ - fix_bb_placements (latch, &dummy); + fix_bb_placements (latch, &dummy, loop_closed_ssa_invalidated); } /* Fix placement of superloops of LOOP inside loop tree, i.e. ensure that @@ -965,7 +975,7 @@ fix_loop_placements (struct loop *loop, bool *irred_invalidated) to the loop. So call fix_bb_placements to fix up the placement of the preheader and (possibly) of its predecessors. */ fix_bb_placements (loop_preheader_edge (loop)->src, - irred_invalidated); + irred_invalidated, NULL); loop = outer; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 16e6dd6b4277..7daf70e366d5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-10-23 Jan Hubicka + + PR middle-end/54967 + * gfortran.dg/pr54967.f90: New testcase. + 2012-10-23 Terry Guo PR target/55019 diff --git a/gcc/testsuite/gfortran.dg/pr54967.f90 b/gcc/testsuite/gfortran.dg/pr54967.f90 new file mode 100644 index 000000000000..f674e3ec19c8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr54967.f90 @@ -0,0 +1,36 @@ + SUBROUTINE calc_S_derivs() + INTEGER, DIMENSION(6, 2) :: c_map_mat + INTEGER, DIMENSION(:), POINTER:: C_mat + DO j=1,3 + DO m=j,3 + n=n+1 + c_map_mat(n,1)=j + IF(m==j)CYCLE + c_map_mat(n,2)=m + END DO + END DO + DO m=1,6 + DO j=1,2 + IF(c_map_mat(m,j)==0)CYCLE + CALL foo(C_mat(c_map_mat(m,j))) + END DO + END DO + END SUBROUTINE calc_S_derivs + SUBROUTINE calc_S_derivs() + INTEGER, DIMENSION(6, 2) :: c_map_mat + INTEGER, DIMENSION(:), POINTER:: C_mat + DO j=1,3 + DO m=j,3 + n=n+1 + c_map_mat(n,1)=j + IF(m==j)CYCLE + c_map_mat(n,2)=m + END DO + END DO + DO m=1,6 + DO j=1,2 + IF(c_map_mat(m,j)==0)CYCLE + CALL foo(C_mat(c_map_mat(m,j))) + END DO + END DO + END SUBROUTINE calc_S_derivs diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 81bf09e9f8ab..323045f32eb9 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -390,13 +390,16 @@ loop_edge_to_cancel (struct loop *loop) EXIT is the exit of the loop that should be eliminated. IRRED_INVALIDATED is used to bookkeep if information about irreducible regions may become invalid as a result - of the transformation. */ + of the transformation. + LOOP_CLOSED_SSA_INVALIDATED is used to bookkepp the case + when we need to go into loop closed SSA form. */ static bool try_unroll_loop_completely (struct loop *loop, edge exit, tree niter, enum unroll_level ul, - bool *irred_invalidated) + bool *irred_invalidated, + bitmap loop_closed_ssa_invalidated) { unsigned HOST_WIDE_INT n_unroll, ninsns, max_unroll, unr_insns; gimple cond; @@ -562,7 +565,7 @@ try_unroll_loop_completely (struct loop *loop, locus = latch_edge->goto_locus; /* Unloop destroys the latch edge. */ - unloop (loop, irred_invalidated); + unloop (loop, irred_invalidated, loop_closed_ssa_invalidated); /* Create new basic block for the latch edge destination and wire it in. */ @@ -615,7 +618,8 @@ static bool canonicalize_loop_induction_variables (struct loop *loop, bool create_iv, enum unroll_level ul, bool try_eval, - bool *irred_invalidated) + bool *irred_invalidated, + bitmap loop_closed_ssa_invalidated) { edge exit = NULL; tree niter; @@ -663,7 +667,8 @@ canonicalize_loop_induction_variables (struct loop *loop, (int)max_loop_iterations_int (loop)); } - if (try_unroll_loop_completely (loop, exit, niter, ul, irred_invalidated)) + if (try_unroll_loop_completely (loop, exit, niter, ul, irred_invalidated, + loop_closed_ssa_invalidated)) return true; if (create_iv @@ -683,13 +688,15 @@ canonicalize_induction_variables (void) struct loop *loop; bool changed = false; bool irred_invalidated = false; + bitmap loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL); FOR_EACH_LOOP (li, loop, 0) { changed |= canonicalize_loop_induction_variables (loop, true, UL_SINGLE_ITER, true, - &irred_invalidated); + &irred_invalidated, + loop_closed_ssa_invalidated); } gcc_assert (!need_ssa_update_p (cfun)); @@ -701,6 +708,13 @@ canonicalize_induction_variables (void) evaluation could reveal new information. */ scev_reset (); + if (!bitmap_empty_p (loop_closed_ssa_invalidated)) + { + gcc_checking_assert (loops_state_satisfies_p (LOOP_CLOSED_SSA)); + rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); + } + BITMAP_FREE (loop_closed_ssa_invalidated); + if (changed) return TODO_cleanup_cfg; return 0; @@ -794,11 +808,15 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) bool changed; enum unroll_level ul; int iteration = 0; + bool irred_invalidated = false; do { - bool irred_invalidated = false; changed = false; + bitmap loop_closed_ssa_invalidated = NULL; + + if (loops_state_satisfies_p (LOOP_CLOSED_SSA)) + loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL); FOR_EACH_LOOP (li, loop, 0) { @@ -812,9 +830,9 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) else ul = UL_NO_GROWTH; - if (canonicalize_loop_induction_variables (loop, false, ul, - !flag_tree_loop_ivcanon, - &irred_invalidated)) + if (canonicalize_loop_induction_variables + (loop, false, ul, !flag_tree_loop_ivcanon, + &irred_invalidated, loop_closed_ssa_invalidated)) { changed = true; /* If we'll continue unrolling, we need to propagate constants @@ -834,11 +852,14 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) struct loop **iter; unsigned i; - if (irred_invalidated - && loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)) - mark_irreducible_loops (); + /* We can not use TODO_update_ssa_no_phi because VOPS gets confused. */ - update_ssa (TODO_update_ssa); + if (loop_closed_ssa_invalidated + && !bitmap_empty_p (loop_closed_ssa_invalidated)) + rewrite_into_loop_closed_ssa (loop_closed_ssa_invalidated, + TODO_update_ssa); + else + update_ssa (TODO_update_ssa); /* Propagate the constants within the new basic blocks. */ FOR_EACH_VEC_ELT (loop_p, father_stack, i, iter) @@ -861,12 +882,22 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) /* Clean up the information about numbers of iterations, since complete unrolling might have invalidated it. */ scev_reset (); +#ifdef ENABLE_CHECKING + if (loops_state_satisfies_p (LOOP_CLOSED_SSA)) + verify_loop_closed_ssa (true); +#endif } + if (loop_closed_ssa_invalidated) + BITMAP_FREE (loop_closed_ssa_invalidated); } while (changed && ++iteration <= PARAM_VALUE (PARAM_MAX_UNROLL_ITERATIONS)); VEC_free (loop_p, stack, father_stack); + if (irred_invalidated + && loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)) + mark_irreducible_loops (); + return 0; }