On Wed, 21 Mar 2012, Richard Sandiford wrote: > Richard Guenther <rguent...@suse.de> writes: > > This patch makes us preserve loop structures from the start of tree > > loop optimizers to the end of RTL loop optimizers. It uses a new > > property, PROP_loops to indicate we want to preserve them and > > massages loop_optimizer_init/finalize to honor that. > > > > On the RTL side the CFG manipulation was not prepared to handle > > updating loops, so this patch fills in enough to pass bootstrap > > and regtesting. We still do too much loop fixing from cleanup_cfg > > basically because callers do not tell cleanup_cfg if they have > > modified the CFG themselves (CSE for example does in some cases). > > It was suggested to use a new flag to cleanup_cfg to do that, > > other suggestions welcome.
The updated patch below does that now. > > Bootstrapped on x86_64-unknown-linux-gnu, testing shows some > > remaining libstdc++ errors, I am investigating them now but > > don't expect major issues. As expected, this was a missed patch hunk that got lost during some intermediate merging. > > Comments? The patch is ontop of the early RTL pass merge. > > Thanks for doing this (and for keeping the ~PROP_loops case around for > passes after rtl_loop_done -- I have a patch that uses it for SMS). It should even be possible to preserve loop information until SMS (basically until IRA, IRA invalidates loop information it computes in a weird way so verification between IRA / reload would fail). Bootstrapped and tested on x86_64-unknown-linux-gnu. If there are no further comments I am inclined to commit this patch early next week (possibly causing quite some fallout ...). Thanks, Richard. 2012-03-23 Richard Guenther <rguent...@suse.de> * loop-init.c (loop_optimizer_init): If loops are preserved perform incremental initialization of required loop features. (loop_optimizer_finalize): If loops are to be preserved only clean up optional loop features. (rtl_loop_done): Forcefully free loops here. * cgraph.c (cgraph_release_function_body): Forcefully free loops. * cfgexpand.c (expand_gimple_cond): Properly add new basic-blocks to existing loops. (construct_init_block): Likewise. (construct_exit_block): Likewise. (gimple_expand_cfg): Clear LOOP_CLOSED_SSA loop state. Cleanup the CFG after expanding. * cfgloop.c (verify_loop_structure): Calculate or verify dominators. If we needed to calculate them, free them afterwards. * tree-pass.h (PROP_loops): New define. * tree-ssa-loop.c (pass_tree_loop_init): Provide PROP_loops. * basic-block.h (CLEANUP_CFG_CHANGED): New. * cfgcleanup.c (merge_blocks_move): Protect loop latches. (cleanup_cfg): If we did something and have loops around, fix them up. * cse.c (rest_of_handle_cse_after_global_opts): Call cleanup_cfg with CLEANUP_CFG_CHANGED. * cfghooks.c (merge_blocks): If we merge a loop header into its predecessor, update the loop structure. (duplicate_block): If we copy a loop latch, adjust loop state to note we may have multiple latches. (delete_basic_block): Mark loops for fixup if we remove a loop. * cfganal.c (forwarder_block_p): Protect loop latches, headers and preheaders. * cfgrtl.c (rtl_can_merge_blocks): Protect loop latches. (cfg_layout_can_merge_blocks_p): Likewise. * cprop.c (bypass_block): If we create a loop with multiple entries, mark it for removal. * except.c (emit_to_new_bb_before): Add the new basic-block to existing loops. * tree-eh.c (lower_resx): Likewise. * omp-low.c (finalize_task_copyfn): Do not copy PROP_loops. (expand_omp_taskreg): Likewise. * tree-inline.c (initialize_cfun): Likewise. * tree-mudflap.c (add_bb_to_loop): Prototype. (mf_build_check_statement_for): Properly add new basic-blocks to existing loops. * tree-ssa-threadupdate.c (thread_block): Mark loops for fixup if we remove a loop. (thread_through_loop_header): Likewise. * trans-mem.c (tm_log_emit_save_or_restores): Properly add new basic-blocks to existing loops. (expand_transaction): Likewise. * Makefile.in (except.o): Add $(CFGLOOP_H). (expr.o): Likewise. (cgraph.o): Likewise. (cprop.o): Likewise. (cfgexpand.o): Likewise. (cfganal.o): Likewise. (trans-mem.o): Likewise. (tree-eh.o): Likewise. Index: gcc/loop-init.c =================================================================== *** gcc/loop-init.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/loop-init.c 2012-03-23 11:59:20.000000000 +0100 *************** along with GCC; see the file COPYING3. *** 42,56 **** void loop_optimizer_init (unsigned flags) { ! struct loops *loops; ! gcc_assert (!current_loops); ! loops = ggc_alloc_cleared_loops (); ! /* Find the loops. */ ! flow_loops_find (loops); ! current_loops = loops; if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES) { --- 42,69 ---- void loop_optimizer_init (unsigned flags) { ! if (!current_loops) ! { ! struct loops *loops = ggc_alloc_cleared_loops (); ! ! gcc_assert (!(cfun->curr_properties & PROP_loops)); ! /* Find the loops. */ ! flow_loops_find (loops); ! current_loops = loops; ! } ! else ! { ! gcc_assert (cfun->curr_properties & PROP_loops); ! /* Ensure that the dominators are computed, like flow_loops_find does. */ ! calculate_dominance_info (CDI_DOMINATORS); ! ! #ifdef ENABLE_CHECKING ! verify_loop_structure (); ! #endif ! } if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES) { *************** loop_optimizer_finalize (void) *** 104,109 **** --- 117,138 ---- struct loop *loop; basic_block bb; + if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS)) + release_recorded_exits (); + + /* If we should preserve loop structure, do not free it but clear + flags that advanced properties are there as we are not preserving + that in full. */ + if (cfun->curr_properties & PROP_loops) + { + loops_state_clear (LOOP_CLOSED_SSA + | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS + | LOOPS_HAVE_PREHEADERS + | LOOPS_HAVE_SIMPLE_LATCHES + | LOOPS_HAVE_FALLTHRU_PREHEADERS); + return; + } + gcc_assert (current_loops != NULL); FOR_EACH_LOOP (li, loop, 0) *************** loop_optimizer_finalize (void) *** 112,119 **** } /* Clean up. */ - if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS)) - release_recorded_exits (); flow_loops_free (current_loops); ggc_free (current_loops); current_loops = NULL; --- 141,146 ---- *************** struct rtl_opt_pass pass_rtl_loop_init = *** 200,205 **** --- 227,234 ---- static unsigned int rtl_loop_done (void) { + /* No longer preserve loops, remove them now. */ + cfun->curr_properties &= ~PROP_loops; loop_optimizer_finalize (); free_dominance_info (CDI_DOMINATORS); *************** struct rtl_opt_pass pass_rtl_loop_done = *** 223,229 **** TV_LOOP, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ ! 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_verify_flow | TODO_verify_rtl_sharing /* todo_flags_finish */ --- 252,258 ---- TV_LOOP, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ ! PROP_loops, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_verify_flow | TODO_verify_rtl_sharing /* todo_flags_finish */ Index: gcc/cgraph.c =================================================================== *** gcc/cgraph.c.orig 2012-03-23 09:13:53.000000000 +0100 --- gcc/cgraph.c 2012-03-23 11:59:20.000000000 +0100 *************** The callgraph: *** 99,104 **** --- 99,105 ---- #include "ipa-utils.h" #include "lto-streamer.h" #include "ipa-inline.h" + #include "cfgloop.h" const char * const ld_plugin_symbol_resolution_names[]= { *************** cgraph_release_function_body (struct cgr *** 1363,1368 **** --- 1364,1375 ---- { tree old_decl = current_function_decl; push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + if (cfun->cfg + && current_loops) + { + cfun->curr_properties &= ~PROP_loops; + loop_optimizer_finalize (); + } if (cfun->gimple_df) { current_function_decl = node->decl; *************** cgraph_release_function_body (struct cgr *** 1379,1385 **** } if (cfun->value_histograms) free_histograms (); - gcc_assert (!current_loops); pop_cfun(); gimple_set_body (node->decl, NULL); VEC_free (ipa_opt_pass, heap, --- 1386,1391 ---- Index: gcc/cfgexpand.c =================================================================== *** gcc/cfgexpand.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cfgexpand.c 2012-03-23 11:59:20.000000000 +0100 *************** along with GCC; see the file COPYING3. *** 47,52 **** --- 47,53 ---- #include "ssaexpand.h" #include "bitmap.h" #include "sbitmap.h" + #include "cfgloop.h" #include "regs.h" /* For reg_renumber. */ #include "integrate.h" /* For emit_initial_value_sets. */ #include "insn-attr.h" /* For INSN_SCHEDULING. */ *************** expand_gimple_cond (basic_block bb, gimp *** 1940,1945 **** --- 1941,1948 ---- false_edge->flags |= EDGE_FALLTHRU; new_bb->count = false_edge->count; new_bb->frequency = EDGE_FREQUENCY (false_edge); + if (current_loops && bb->loop_father) + add_bb_to_loop (new_bb, bb->loop_father); new_edge = make_edge (new_bb, dest, 0); new_edge->probability = REG_BR_PROB_BASE; new_edge->count = new_bb->count; *************** construct_init_block (void) *** 4118,4123 **** --- 4121,4128 ---- ENTRY_BLOCK_PTR); init_block->frequency = ENTRY_BLOCK_PTR->frequency; init_block->count = ENTRY_BLOCK_PTR->count; + if (current_loops && ENTRY_BLOCK_PTR->loop_father) + add_bb_to_loop (init_block, ENTRY_BLOCK_PTR->loop_father); if (e) { first_block = e->dest; *************** construct_exit_block (void) *** 4185,4190 **** --- 4190,4197 ---- EXIT_BLOCK_PTR->prev_bb); exit_block->frequency = EXIT_BLOCK_PTR->frequency; exit_block->count = EXIT_BLOCK_PTR->count; + if (current_loops && EXIT_BLOCK_PTR->loop_father) + add_bb_to_loop (exit_block, EXIT_BLOCK_PTR->loop_father); ix = 0; while (ix < EDGE_COUNT (EXIT_BLOCK_PTR->preds)) *************** gimple_expand_cfg (void) *** 4556,4561 **** --- 4563,4570 ---- timevar_push (TV_POST_EXPAND); /* We are no longer in SSA form. */ cfun->gimple_df->in_ssa_p = false; + if (current_loops) + loops_state_clear (LOOP_CLOSED_SSA); /* Expansion is used by optimization passes too, set maybe_hot_insn_p conservatively to true until they are all profile aware. */ Index: gcc/cfgloop.c =================================================================== *** gcc/cfgloop.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cfgloop.c 2012-03-23 11:59:20.000000000 +0100 *************** verify_loop_structure (void) *** 1317,1325 **** unsigned num = number_of_loops (); loop_iterator li; struct loop_exit *exit, *mexit; ! /* We need up-to-date dominators, verify them. */ ! verify_dominators (CDI_DOMINATORS); /* Check sizes. */ sizes = XCNEWVEC (unsigned, num); --- 1317,1329 ---- unsigned num = number_of_loops (); loop_iterator li; struct loop_exit *exit, *mexit; + bool dom_available = dom_info_available_p (CDI_DOMINATORS); ! /* We need up-to-date dominators, compute or verify them. */ ! if (!dom_available) ! calculate_dominance_info (CDI_DOMINATORS); ! else ! verify_dominators (CDI_DOMINATORS); /* Check sizes. */ sizes = XCNEWVEC (unsigned, num); *************** verify_loop_structure (void) *** 1563,1568 **** --- 1567,1574 ---- gcc_assert (!err); free (sizes); + if (!dom_available) + free_dominance_info (CDI_DOMINATORS); } /* Returns latch edge of LOOP. */ Index: gcc/tree-pass.h =================================================================== *** gcc/tree-pass.h.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/tree-pass.h 2012-03-23 11:59:20.000000000 +0100 *************** struct dump_file_info *** 239,244 **** --- 239,245 ---- #define PROP_gimple_lomp (1 << 8) /* lowered OpenMP directives */ #define PROP_cfglayout (1 << 9) /* cfglayout mode on RTL */ #define PROP_gimple_lcx (1 << 10) /* lowered complex */ + #define PROP_loops (1 << 11) /* preserve loop structures */ #define PROP_trees \ (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp) Index: gcc/tree-ssa-loop.c =================================================================== *** gcc/tree-ssa-loop.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/tree-ssa-loop.c 2012-03-23 11:59:20.000000000 +0100 *************** struct gimple_opt_pass pass_tree_loop_in *** 92,98 **** 0, /* static_pass_number */ TV_TREE_LOOP_INIT, /* tv_id */ PROP_cfg, /* properties_required */ ! 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ 0 /* todo_flags_finish */ --- 92,98 ---- 0, /* static_pass_number */ TV_TREE_LOOP_INIT, /* tv_id */ PROP_cfg, /* properties_required */ ! PROP_loops, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ 0 /* todo_flags_finish */ Index: gcc/cfgcleanup.c =================================================================== *** gcc/cfgcleanup.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cfgcleanup.c 2012-03-23 12:01:21.000000000 +0100 *************** merge_blocks_move (edge e, basic_block b *** 779,784 **** --- 779,789 ---- if (e->flags & EDGE_FALLTHRU) { int b_index = b->index, c_index = c->index; + + /* Protect the loop latches. */ + if (current_loops && c->loop_father->latch == c) + return NULL; + merge_blocks (b, c); update_forwarder_flag (b); *************** cleanup_cfg (int mode) *** 2976,2981 **** --- 2981,3003 ---- if (!(mode & CLEANUP_CFGLAYOUT)) delete_dead_jumptables (); + /* ??? We probably do this way too often. */ + if (current_loops + && (changed + || (mode & CLEANUP_CFG_CHANGED))) + { + bitmap changed_bbs; + timevar_push (TV_REPAIR_LOOPS); + /* The above doesn't preserve dominance info if available. */ + gcc_assert (!dom_info_available_p (CDI_DOMINATORS)); + calculate_dominance_info (CDI_DOMINATORS); + changed_bbs = BITMAP_ALLOC (NULL); + fix_loop_structure (changed_bbs); + BITMAP_FREE (changed_bbs); + free_dominance_info (CDI_DOMINATORS); + timevar_pop (TV_REPAIR_LOOPS); + } + timevar_pop (TV_CLEANUP_CFG); return changed; Index: gcc/cfghooks.c =================================================================== *** gcc/cfghooks.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cfghooks.c 2012-03-23 11:59:20.000000000 +0100 *************** delete_basic_block (basic_block bb) *** 508,513 **** --- 508,514 ---- { loop->header = NULL; loop->latch = NULL; + loops_state_set (LOOPS_NEED_FIXUP); } remove_bb_from_loops (bb); *************** merge_blocks (basic_block a, basic_block *** 682,689 **** cfg_hooks->merge_blocks (a, b); if (current_loops != NULL) ! remove_bb_from_loops (b); /* Normally there should only be one successor of A and that is B, but partway though the merge of blocks for conditional_execution we'll --- 683,700 ---- cfg_hooks->merge_blocks (a, b); + /* If we merge a loop header into its predecessor, update the loop + structure. */ if (current_loops != NULL) ! { ! if (b->loop_father->header == b) ! { ! remove_bb_from_loops (a); ! add_bb_to_loop (a, b->loop_father); ! a->loop_father->header = a; ! } ! remove_bb_from_loops (b); ! } /* Normally there should only be one successor of A and that is B, but partway though the merge of blocks for conditional_execution we'll *************** duplicate_block (basic_block bb, edge e, *** 999,1004 **** --- 1010,1027 ---- struct loop *cloop = bb->loop_father; struct loop *copy = get_loop_copy (cloop); add_bb_to_loop (new_bb, copy ? copy : cloop); + /* If we copied the loop latch block but not the loop, adjust + loop state. + ??? If we copied the loop header block but not the loop + we might either have created a loop copy or a loop with + multiple entries. In both cases we probably have to + ditch the loops and arrange for a fixup. */ + if (!copy + && cloop->latch == bb) + { + cloop->latch = NULL; + loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES); + } } return new_bb; Index: gcc/cfganal.c =================================================================== *** gcc/cfganal.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cfganal.c 2012-03-23 11:59:20.000000000 +0100 *************** along with GCC; see the file COPYING3. *** 37,42 **** --- 37,43 ---- #include "bitmap.h" #include "sbitmap.h" #include "timevar.h" + #include "cfgloop.h" /* Store the data structures necessary for depth-first search. */ struct depth_first_search_dsS { *************** forwarder_block_p (const_basic_block bb) *** 94,99 **** --- 95,111 ---- || !single_succ_p (bb)) return false; + /* Protect loop latches, headers and preheaders. */ + if (current_loops) + { + basic_block dest; + if (bb->loop_father->header == bb) + return false; + dest = EDGE_SUCC (bb, 0)->dest; + if (dest->loop_father->header == dest) + return false; + } + for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn)) if (INSN_P (insn) && flow_active_insn_p (insn)) return false; Index: gcc/cfgrtl.c =================================================================== *** gcc/cfgrtl.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cfgrtl.c 2012-03-23 11:59:20.000000000 +0100 *************** rtl_can_merge_blocks (basic_block a, bas *** 727,732 **** --- 727,736 ---- if (BB_PARTITION (a) != BB_PARTITION (b)) return false; + /* Protect the loop latches. */ + if (current_loops && b->loop_father->latch == b) + return false; + /* There must be exactly one edge in between the blocks. */ return (single_succ_p (a) && single_succ (a) == b *************** cfg_layout_can_merge_blocks_p (basic_blo *** 2786,2791 **** --- 2790,2799 ---- if (BB_PARTITION (a) != BB_PARTITION (b)) return false; + /* Protect the loop latches. */ + if (current_loops && b->loop_father->latch == b) + return false; + /* If we would end up moving B's instructions, make sure it doesn't fall through into the exit block, since we cannot recover from a fallthrough edge into the exit block occurring in the middle of a function. */ Index: gcc/cprop.c =================================================================== *** gcc/cprop.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cprop.c 2012-03-23 11:59:20.000000000 +0100 *************** along with GCC; see the file COPYING3. *** 48,53 **** --- 48,54 ---- #include "df.h" #include "dbgcnt.h" #include "target.h" + #include "cfgloop.h" /* An obstack for our working variables. */ *************** bypass_block (basic_block bb, rtx setcc, *** 1610,1615 **** --- 1611,1627 ---- && dest != old_dest && dest != EXIT_BLOCK_PTR) { + if (current_loops != NULL + && e->src->loop_father->latch == e->src) + { + /* ??? Now we are creating (or may create) a loop + with multiple entries. Simply mark it for + removal. Alternatively we could not do this + threading. */ + e->src->loop_father->header = NULL; + e->src->loop_father->latch = NULL; + } + redirect_edge_and_branch_force (e, dest); /* Copy the register setter to the redirected edge. Index: gcc/omp-low.c =================================================================== *** gcc/omp-low.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/omp-low.c 2012-03-23 11:59:20.000000000 +0100 *************** finalize_task_copyfn (gimple task_stmt) *** 1242,1248 **** /* Inform the callgraph about the new function. */ DECL_STRUCT_FUNCTION (child_fn)->curr_properties ! = cfun->curr_properties; old_fn = current_function_decl; push_cfun (child_cfun); --- 1242,1248 ---- /* Inform the callgraph about the new function. */ DECL_STRUCT_FUNCTION (child_fn)->curr_properties ! = cfun->curr_properties & ~PROP_loops; old_fn = current_function_decl; push_cfun (child_cfun); *************** expand_omp_taskreg (struct omp_region *r *** 3562,3568 **** /* Inform the callgraph about the new function. */ DECL_STRUCT_FUNCTION (child_fn)->curr_properties ! = cfun->curr_properties; cgraph_add_new_function (child_fn, true); /* Fix the callgraph edges for child_cfun. Those for cfun will be --- 3562,3568 ---- /* Inform the callgraph about the new function. */ DECL_STRUCT_FUNCTION (child_fn)->curr_properties ! = cfun->curr_properties & ~PROP_loops; cgraph_add_new_function (child_fn, true); /* Fix the callgraph edges for child_cfun. Those for cfun will be Index: gcc/tree-inline.c =================================================================== *** gcc/tree-inline.c.orig 2012-03-23 09:13:53.000000000 +0100 --- gcc/tree-inline.c 2012-03-23 11:59:20.000000000 +0100 *************** initialize_cfun (tree new_fndecl, tree c *** 2093,2099 **** cfun->static_chain_decl = src_cfun->static_chain_decl; cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area; cfun->function_end_locus = src_cfun->function_end_locus; ! cfun->curr_properties = src_cfun->curr_properties; cfun->last_verified = src_cfun->last_verified; cfun->va_list_gpr_size = src_cfun->va_list_gpr_size; cfun->va_list_fpr_size = src_cfun->va_list_fpr_size; --- 2093,2099 ---- cfun->static_chain_decl = src_cfun->static_chain_decl; cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area; cfun->function_end_locus = src_cfun->function_end_locus; ! cfun->curr_properties = src_cfun->curr_properties & ~PROP_loops; cfun->last_verified = src_cfun->last_verified; cfun->va_list_gpr_size = src_cfun->va_list_gpr_size; cfun->va_list_fpr_size = src_cfun->va_list_fpr_size; Index: gcc/tree-mudflap.c =================================================================== *** gcc/tree-mudflap.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/tree-mudflap.c 2012-03-23 11:59:20.000000000 +0100 *************** along with GCC; see the file COPYING3. *** 45,50 **** --- 45,52 ---- #include "cgraph.h" #include "gimple.h" + extern void add_bb_to_loop (basic_block, struct loop *); + /* Internal function decls */ *************** mf_build_check_statement_for (tree base, *** 560,565 **** --- 562,571 ---- set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb); } + /* Update loop info. */ + if (current_loops) + add_bb_to_loop (then_bb, cond_bb->loop_father); + /* Build our local variables. */ mf_elem = make_rename_temp (mf_cache_structptr_type, "__mf_elem"); mf_base = make_rename_temp (mf_uintptr_type, "__mf_base"); Index: gcc/Makefile.in =================================================================== *** gcc/Makefile.in.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/Makefile.in 2012-03-23 11:59:20.000000000 +0100 *************** trans-mem.o : trans-mem.c $(CONFIG_H) $( *** 2159,2165 **** $(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \ $(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \ $(PARAMS_H) $(TARGET_H) langhooks.h \ ! tree-pretty-print.h gimple-pretty-print.h ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(GGC_H) $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h \ --- 2159,2165 ---- $(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \ $(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \ $(PARAMS_H) $(TARGET_H) langhooks.h \ ! tree-pretty-print.h gimple-pretty-print.h $(CFGLOOP_H) ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(GGC_H) $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h \ *************** tree-ssa-operands.o : tree-ssa-operands. *** 2468,2474 **** tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) langhooks.h \ $(GGC_H) $(TREE_PASS_H) coretypes.h $(TIMEVAR_H) pointer-set.h \ ! $(TREE_DUMP_H) $(TREE_INLINE_H) tree-iterator.h toplev.h $(DIAGNOSTIC_CORE_H) tree-ssa-loop.o : tree-ssa-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) output.h \ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TREE_PASS_H) $(TIMEVAR_H) \ --- 2468,2475 ---- tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) langhooks.h \ $(GGC_H) $(TREE_PASS_H) coretypes.h $(TIMEVAR_H) pointer-set.h \ ! $(TREE_DUMP_H) $(TREE_INLINE_H) tree-iterator.h toplev.h \ ! $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H) tree-ssa-loop.o : tree-ssa-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) output.h \ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TREE_PASS_H) $(TIMEVAR_H) \ *************** except.o : except.c $(CONFIG_H) $(SYSTEM *** 2814,2820 **** dwarf2asm.h dwarf2out.h toplev.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) intl.h $(GGC_H) \ gt-except.h $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) $(DWARF2_H) \ $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H) $(TREE_FLOW_H) \ ! tree-pretty-print.h sbitmap.h $(COMMON_TARGET_H) expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \ $(LIBFUNCS_H) $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \ --- 2815,2821 ---- dwarf2asm.h dwarf2out.h toplev.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) intl.h $(GGC_H) \ gt-except.h $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) $(DWARF2_H) \ $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H) $(TREE_FLOW_H) \ ! tree-pretty-print.h sbitmap.h $(COMMON_TARGET_H) $(CFGLOOP_H) expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \ $(LIBFUNCS_H) $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \ *************** cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM *** 2912,2918 **** gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \ $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) cif-code.def \ value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) \ ! ipa-inline.h $(LTO_STREAMER_H) cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \ --- 2913,2919 ---- gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \ $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) cif-code.def \ value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) \ ! ipa-inline.h $(LTO_STREAMER_H) $(CFGLOOP_H) cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \ *************** cprop.o : cprop.c $(CONFIG_H) $(SYSTEM_H *** 3029,3035 **** $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \ $(TM_P_H) $(PARAMS_H) cselib.h $(EXCEPT_H) $(TREE_H) $(TIMEVAR_H) \ intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \ ! $(DF_H) gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \ --- 3030,3036 ---- $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \ $(TM_P_H) $(PARAMS_H) cselib.h $(EXCEPT_H) $(TREE_H) $(TIMEVAR_H) \ intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \ ! $(DF_H) $(CFGLOOP_H) gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \ *************** cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) *** 3149,3155 **** $(DIAGNOSTIC_H) toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \ value-prof.h $(TREE_INLINE_H) $(TARGET_H) $(SSAEXPAND_H) $(REGS_H) \ tree-pretty-print.h gimple-pretty-print.h $(BITMAP_H) sbitmap.h \ ! $(INSN_ATTR_H) $(INTEGRATE_H) cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \ $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \ output.h $(FUNCTION_H) $(EXCEPT_H) $(TM_P_H) $(INSN_ATTR_H) \ --- 3150,3156 ---- $(DIAGNOSTIC_H) toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \ value-prof.h $(TREE_INLINE_H) $(TARGET_H) $(SSAEXPAND_H) $(REGS_H) \ tree-pretty-print.h gimple-pretty-print.h $(BITMAP_H) sbitmap.h \ ! $(INSN_ATTR_H) $(INTEGRATE_H) $(CFGLOOP_H) cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \ $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \ output.h $(FUNCTION_H) $(EXCEPT_H) $(TM_P_H) $(INSN_ATTR_H) \ *************** cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM *** 3158,3164 **** $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H) cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(TM_P_H) \ ! $(TIMEVAR_H) $(OBSTACK_H) $(DIAGNOSTIC_CORE_H) vecprim.h sbitmap.h $(BITMAP_H) cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h $(DIAGNOSTIC_CORE_H) \ $(FUNCTION_H) $(EXCEPT_H) $(TIMEVAR_H) $(TREE_H) $(EXPR_H) sbitmap.h --- 3159,3166 ---- $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H) cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(TM_P_H) \ ! $(TIMEVAR_H) $(OBSTACK_H) $(DIAGNOSTIC_CORE_H) vecprim.h sbitmap.h \ ! $(BITMAP_H) $(CFGLOOP_H) cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h $(DIAGNOSTIC_CORE_H) \ $(FUNCTION_H) $(EXCEPT_H) $(TIMEVAR_H) $(TREE_H) $(EXPR_H) sbitmap.h Index: gcc/trans-mem.c =================================================================== *** gcc/trans-mem.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/trans-mem.c 2012-03-23 11:59:20.000000000 +0100 *************** *** 34,39 **** --- 34,40 ---- #include "langhooks.h" #include "tree-pretty-print.h" #include "gimple-pretty-print.h" + #include "cfgloop.h" #define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1) *************** tm_log_emit_save_or_restores (basic_bloc *** 1270,1275 **** --- 1271,1282 ---- cond_bb = create_empty_bb (before_bb); code_bb = create_empty_bb (cond_bb); *end_bb = create_empty_bb (code_bb); + if (current_loops && before_bb->loop_father) + { + add_bb_to_loop (cond_bb, before_bb->loop_father); + add_bb_to_loop (code_bb, before_bb->loop_father); + add_bb_to_loop (*end_bb, before_bb->loop_father); + } redirect_edge_pred (fallthru_edge, *end_bb); fallthru_edge->flags = EDGE_FALLTHRU; make_edge (before_bb, cond_bb, old_flags); *************** expand_transaction (struct tm_region *re *** 2682,2687 **** --- 2689,2696 ---- basic_block test_bb; test_bb = create_empty_bb (slice_bb); + if (current_loops && slice_bb->loop_father) + add_bb_to_loop (test_bb, slice_bb->loop_father); if (VEC_empty (tree, tm_log_save_addresses)) region->entry_block = test_bb; gsi = gsi_last_bb (test_bb); *************** expand_transaction (struct tm_region *re *** 2719,2724 **** --- 2728,2735 ---- basic_block empty_bb; region->entry_block = empty_bb = create_empty_bb (atomic_bb); + if (current_loops && atomic_bb->loop_father) + add_bb_to_loop (empty_bb, atomic_bb->loop_father); e = FALLTHRU_EDGE (atomic_bb); redirect_edge_pred (e, empty_bb); Index: gcc/tree-ssa-threadupdate.c =================================================================== *** gcc/tree-ssa-threadupdate.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/tree-ssa-threadupdate.c 2012-03-23 11:59:20.000000000 +0100 *************** thread_block (basic_block bb, bool noloo *** 624,629 **** --- 624,630 ---- { loop->header = NULL; loop->latch = NULL; + loops_state_set (LOOPS_NEED_FIXUP); } } *************** thread_through_loop_header (struct loop *** 969,974 **** --- 970,976 ---- original header. */ loop->header = NULL; loop->latch = NULL; + loops_state_set (LOOPS_NEED_FIXUP); return thread_block (header, false); } Index: gcc/cfgloopmanip.c =================================================================== *** gcc/cfgloopmanip.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/cfgloopmanip.c 2012-03-23 11:59:20.000000000 +0100 *************** fix_loop_structure (bitmap changed_bbs) *** 1728,1733 **** --- 1728,1735 ---- if (record_exits) record_loop_exits (); + loops_state_clear (LOOPS_NEED_FIXUP); + #ifdef ENABLE_CHECKING verify_loop_structure (); #endif Index: gcc/tree-cfgcleanup.c =================================================================== *** gcc/tree-cfgcleanup.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/tree-cfgcleanup.c 2012-03-23 11:59:20.000000000 +0100 *************** repair_loop_structures (void) *** 793,799 **** #endif scev_reset (); - loops_state_clear (LOOPS_NEED_FIXUP); timevar_pop (TV_REPAIR_LOOPS); } --- 793,798 ---- Index: gcc/except.c =================================================================== *** gcc/except.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/except.c 2012-03-23 11:59:20.000000000 +0100 *************** along with GCC; see the file COPYING3. *** 144,149 **** --- 144,150 ---- #include "tree-pass.h" #include "timevar.h" #include "tree-flow.h" + #include "cfgloop.h" /* Provide defaults for stuff that may not be defined when using sjlj exceptions. */ *************** static basic_block *** 898,904 **** emit_to_new_bb_before (rtx seq, rtx insn) { rtx last; ! basic_block bb; edge e; edge_iterator ei; --- 899,905 ---- emit_to_new_bb_before (rtx seq, rtx insn) { rtx last; ! basic_block bb, prev_bb; edge e; edge_iterator ei; *************** emit_to_new_bb_before (rtx seq, rtx insn *** 913,921 **** last = emit_insn_before (seq, insn); if (BARRIER_P (last)) last = PREV_INSN (last); ! bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb); update_bb_for_insn (bb); bb->flags |= BB_SUPERBLOCK; return bb; } --- 914,929 ---- last = emit_insn_before (seq, insn); if (BARRIER_P (last)) last = PREV_INSN (last); ! prev_bb = BLOCK_FOR_INSN (insn)->prev_bb; ! bb = create_basic_block (seq, last, prev_bb); update_bb_for_insn (bb); bb->flags |= BB_SUPERBLOCK; + if (current_loops) + { + add_bb_to_loop (bb, prev_bb->loop_father); + if (prev_bb->loop_father->header == prev_bb) + prev_bb->loop_father->header = bb; + } return bb; } Index: gcc/tree-eh.c =================================================================== *** gcc/tree-eh.c.orig 2012-03-22 13:10:50.000000000 +0100 --- gcc/tree-eh.c 2012-03-23 11:59:20.000000000 +0100 *************** along with GCC; see the file COPYING3. *** 38,43 **** --- 38,44 ---- #include "diagnostic-core.h" #include "gimple.h" #include "target.h" + #include "cfgloop.h" /* In some instances a tree and a gimple need to be stored in a same table, i.e. in hash tables. This is a structure to do this. */ *************** lower_resx (basic_block bb, gimple stmt, *** 3041,3046 **** --- 3042,3049 ---- gimple_stmt_iterator gsi2; new_bb = create_empty_bb (bb); + if (current_loops) + add_bb_to_loop (new_bb, bb->loop_father); lab = gimple_block_label (new_bb); gsi2 = gsi_start_bb (new_bb); Index: gcc/basic-block.h =================================================================== *** gcc/basic-block.h.orig 2012-01-10 10:11:18.000000000 +0100 --- gcc/basic-block.h 2012-03-23 12:00:25.000000000 +0100 *************** edge find_edge (basic_block, basic_block *** 741,746 **** --- 741,747 ---- #define CLEANUP_NO_INSN_DEL 16 /* Do not try to delete trivially dead insns. */ #define CLEANUP_CFGLAYOUT 32 /* Do cleanup in cfglayout mode. */ + #define CLEANUP_CFG_CHANGED 64 /* The caller changed the CFG. */ /* In lcm.c */ extern struct edge_list *pre_edge_lcm (int, sbitmap *, sbitmap *, Index: gcc/cse.c =================================================================== *** gcc/cse.c.orig 2012-03-22 13:12:15.000000000 +0100 --- gcc/cse.c 2012-03-23 13:00:42.000000000 +0100 *************** rest_of_handle_cse (void) *** 7451,7457 **** { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); ! cleanup_cfg (0); timevar_pop (TV_JUMP); } else if (tem == 1 || optimize > 1) --- 7451,7457 ---- { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); ! cleanup_cfg (CLEANUP_CFG_CHANGED); timevar_pop (TV_JUMP); } else if (tem == 1 || optimize > 1) *************** rest_of_handle_cse2 (void) *** 7511,7517 **** { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); ! cleanup_cfg (0); timevar_pop (TV_JUMP); } else if (tem == 1) --- 7511,7517 ---- { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); ! cleanup_cfg (CLEANUP_CFG_CHANGED); timevar_pop (TV_JUMP); } else if (tem == 1) *************** rest_of_handle_cse_after_global_opts (vo *** 7572,7578 **** { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); ! cleanup_cfg (0); timevar_pop (TV_JUMP); } else if (tem == 1) --- 7572,7578 ---- { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); ! cleanup_cfg (CLEANUP_CFG_CHANGED); timevar_pop (TV_JUMP); } else if (tem == 1)