From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25949 invoked by alias); 20 Mar 2012 15:21:13 -0000 Received: (qmail 25847 invoked by uid 22791); 20 Mar 2012 15:20:50 -0000 X-SWARE-Spam-Status: No, hits=-5.7 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,TW_CF,TW_JL,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 20 Mar 2012 15:20:25 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx2.suse.de (Postfix) with ESMTP id 67E299043F for ; Tue, 20 Mar 2012 16:20:23 +0100 (CET) Date: Tue, 20 Mar 2012 15:21:00 -0000 From: Richard Guenther To: gcc-patches@gcc.gnu.org Subject: [PATCH] Preserve loops from tree to RTL loop optimizers Message-ID: User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2012-03/txt/msg01360.txt.bz2 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. Bootstrapped on x86_64-unknown-linux-gnu, testing shows some remaining libstdc++ errors, I am investigating them now but don't expect major issues. Comments? The patch is ontop of the early RTL pass merge. Thanks, Richard. 2012-03-20 Richard Guenther * 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. * cfgcleanup.c (merge_blocks_move): Protect loop latches. (cleanup_cfg): If we did something and have loops around, fix them up. * 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-20 10:54:47.000000000 +0100 --- gcc/loop-init.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/cgraph.c 2012-03-20 13:33:27.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-20 11:36:14.000000000 +0100 --- gcc/cfgexpand.c 2012-03-20 13:33:55.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-20 10:54:47.000000000 +0100 --- gcc/cfgloop.c 2012-03-20 13:33:27.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-20 11:14:19.000000000 +0100 --- gcc/tree-pass.h 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/tree-ssa-loop.c 2012-03-20 13:33:27.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-20 11:03:49.000000000 +0100 --- gcc/cfgcleanup.c 2012-03-20 13:33:27.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,3001 ---- if (!(mode & CLEANUP_CFGLAYOUT)) delete_dead_jumptables (); + /* ??? We do this way too often. */ + if (current_loops) + { + 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-20 10:54:47.000000000 +0100 --- gcc/cfghooks.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/cfganal.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/cfgrtl.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/cprop.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/omp-low.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/tree-inline.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/tree-mudflap.c 2012-03-20 13:33:27.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-20 11:36:41.000000000 +0100 --- gcc/Makefile.in 2012-03-20 14:37:29.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-20 10:54:47.000000000 +0100 --- gcc/trans-mem.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/tree-ssa-threadupdate.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/cfgloopmanip.c 2012-03-20 13:33:27.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-20 10:54:47.000000000 +0100 --- gcc/tree-cfgcleanup.c 2012-03-20 13:33:27.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-20 10:51:26.000000000 +0100 --- gcc/except.c 2012-03-20 13:50:05.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-02-10 15:44:24.000000000 +0100 --- gcc/tree-eh.c 2012-03-20 14:37:11.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, *** 3062,3067 **** --- 3063,3070 ---- e = make_edge (bb, new_bb, EDGE_FALLTHRU); e->count = bb->count; e->probability = REG_BR_PROB_BASE; + if (current_loops) + add_bb_to_loop (new_bb, bb->loop_father); } else {