This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Preserve loops from tree to RTL loop optimizers
On Wed, 21 Mar 2012, Richard Sandiford wrote:
> Richard Guenther <rguenther@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 <rguenther@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)