loop-init.c (loop_optimizer_init): If loops are preserved perform incremental initialization of required loop features.
2012-03-28 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. From-SVN: r185913
This commit is contained in:
parent
911ba85554
commit
7d776ee252
24 changed files with 252 additions and 30 deletions
|
@ -1,3 +1,63 @@
|
|||
2012-03-28 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.
|
||||
|
||||
2012-03-28 Georg-Johann Lay <avr@gjlay.de>
|
||||
|
||||
PR target/52692
|
||||
|
|
|
@ -2159,7 +2159,7 @@ trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
|||
$(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
|
||||
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 \
|
||||
|
@ -2468,7 +2468,8 @@ tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
|
|||
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_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) \
|
||||
|
@ -2814,7 +2815,7 @@ except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
|||
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)
|
||||
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 \
|
||||
|
@ -2912,7 +2913,7 @@ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
|||
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)
|
||||
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) \
|
||||
|
@ -3029,7 +3030,7 @@ cprop.o : cprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
|||
$(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)
|
||||
$(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) \
|
||||
|
@ -3149,7 +3150,7 @@ cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
|||
$(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)
|
||||
$(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) \
|
||||
|
@ -3158,7 +3159,8 @@ cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
|
|||
$(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)
|
||||
$(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
|
||||
|
|
|
@ -741,6 +741,7 @@ edge find_edge (basic_block, basic_block);
|
|||
#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 *,
|
||||
|
|
|
@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#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 {
|
||||
|
@ -94,6 +95,17 @@ forwarder_block_p (const_basic_block bb)
|
|||
|| !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;
|
||||
|
|
|
@ -779,6 +779,11 @@ merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
|
|||
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);
|
||||
|
||||
|
@ -2976,6 +2981,23 @@ cleanup_cfg (int mode)
|
|||
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;
|
||||
|
|
|
@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#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. */
|
||||
|
@ -1940,6 +1941,8 @@ expand_gimple_cond (basic_block bb, gimple stmt)
|
|||
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;
|
||||
|
@ -4118,6 +4121,8 @@ construct_init_block (void)
|
|||
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;
|
||||
|
@ -4185,6 +4190,8 @@ construct_exit_block (void)
|
|||
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))
|
||||
|
@ -4556,6 +4563,8 @@ gimple_expand_cfg (void)
|
|||
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. */
|
||||
|
|
|
@ -508,6 +508,7 @@ delete_basic_block (basic_block bb)
|
|||
{
|
||||
loop->header = NULL;
|
||||
loop->latch = NULL;
|
||||
loops_state_set (LOOPS_NEED_FIXUP);
|
||||
}
|
||||
|
||||
remove_bb_from_loops (bb);
|
||||
|
@ -682,8 +683,18 @@ merge_blocks (basic_block a, basic_block b)
|
|||
|
||||
cfg_hooks->merge_blocks (a, b);
|
||||
|
||||
/* If we merge a loop header into its predecessor, update the loop
|
||||
structure. */
|
||||
if (current_loops != NULL)
|
||||
remove_bb_from_loops (b);
|
||||
{
|
||||
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
|
||||
|
@ -999,6 +1010,18 @@ duplicate_block (basic_block bb, edge e, basic_block after)
|
|||
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;
|
||||
|
|
|
@ -1317,9 +1317,13 @@ verify_loop_structure (void)
|
|||
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, verify them. */
|
||||
verify_dominators (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);
|
||||
|
@ -1563,6 +1567,8 @@ verify_loop_structure (void)
|
|||
gcc_assert (!err);
|
||||
|
||||
free (sizes);
|
||||
if (!dom_available)
|
||||
free_dominance_info (CDI_DOMINATORS);
|
||||
}
|
||||
|
||||
/* Returns latch edge of LOOP. */
|
||||
|
|
|
@ -1728,6 +1728,8 @@ fix_loop_structure (bitmap changed_bbs)
|
|||
if (record_exits)
|
||||
record_loop_exits ();
|
||||
|
||||
loops_state_clear (LOOPS_NEED_FIXUP);
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
verify_loop_structure ();
|
||||
#endif
|
||||
|
|
|
@ -727,6 +727,10 @@ rtl_can_merge_blocks (basic_block a, basic_block b)
|
|||
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
|
||||
|
@ -2786,6 +2790,10 @@ cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
|
|||
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. */
|
||||
|
|
|
@ -99,6 +99,7 @@ The callgraph:
|
|||
#include "ipa-utils.h"
|
||||
#include "lto-streamer.h"
|
||||
#include "ipa-inline.h"
|
||||
#include "cfgloop.h"
|
||||
|
||||
const char * const ld_plugin_symbol_resolution_names[]=
|
||||
{
|
||||
|
@ -1363,6 +1364,12 @@ cgraph_release_function_body (struct cgraph_node *node)
|
|||
{
|
||||
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;
|
||||
|
@ -1379,7 +1386,6 @@ cgraph_release_function_body (struct cgraph_node *node)
|
|||
}
|
||||
if (cfun->value_histograms)
|
||||
free_histograms ();
|
||||
gcc_assert (!current_loops);
|
||||
pop_cfun();
|
||||
gimple_set_body (node->decl, NULL);
|
||||
VEC_free (ipa_opt_pass, heap,
|
||||
|
|
12
gcc/cprop.c
12
gcc/cprop.c
|
@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "df.h"
|
||||
#include "dbgcnt.h"
|
||||
#include "target.h"
|
||||
#include "cfgloop.h"
|
||||
|
||||
|
||||
/* An obstack for our working variables. */
|
||||
|
@ -1610,6 +1611,17 @@ bypass_block (basic_block bb, rtx setcc, rtx jump)
|
|||
&& 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.
|
||||
|
|
|
@ -7451,7 +7451,7 @@ rest_of_handle_cse (void)
|
|||
{
|
||||
timevar_push (TV_JUMP);
|
||||
rebuild_jump_labels (get_insns ());
|
||||
cleanup_cfg (0);
|
||||
cleanup_cfg (CLEANUP_CFG_CHANGED);
|
||||
timevar_pop (TV_JUMP);
|
||||
}
|
||||
else if (tem == 1 || optimize > 1)
|
||||
|
@ -7511,7 +7511,7 @@ rest_of_handle_cse2 (void)
|
|||
{
|
||||
timevar_push (TV_JUMP);
|
||||
rebuild_jump_labels (get_insns ());
|
||||
cleanup_cfg (0);
|
||||
cleanup_cfg (CLEANUP_CFG_CHANGED);
|
||||
timevar_pop (TV_JUMP);
|
||||
}
|
||||
else if (tem == 1)
|
||||
|
@ -7572,7 +7572,7 @@ rest_of_handle_cse_after_global_opts (void)
|
|||
{
|
||||
timevar_push (TV_JUMP);
|
||||
rebuild_jump_labels (get_insns ());
|
||||
cleanup_cfg (0);
|
||||
cleanup_cfg (CLEANUP_CFG_CHANGED);
|
||||
timevar_pop (TV_JUMP);
|
||||
}
|
||||
else if (tem == 1)
|
||||
|
|
12
gcc/except.c
12
gcc/except.c
|
@ -144,6 +144,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#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. */
|
||||
|
@ -898,7 +899,7 @@ static basic_block
|
|||
emit_to_new_bb_before (rtx seq, rtx insn)
|
||||
{
|
||||
rtx last;
|
||||
basic_block bb;
|
||||
basic_block bb, prev_bb;
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
|
@ -913,9 +914,16 @@ emit_to_new_bb_before (rtx seq, rtx insn)
|
|||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,15 +42,28 @@ along with GCC; see the file COPYING3. If not see
|
|||
void
|
||||
loop_optimizer_init (unsigned flags)
|
||||
{
|
||||
struct loops *loops;
|
||||
if (!current_loops)
|
||||
{
|
||||
struct loops *loops = ggc_alloc_cleared_loops ();
|
||||
|
||||
gcc_assert (!current_loops);
|
||||
loops = ggc_alloc_cleared_loops ();
|
||||
gcc_assert (!(cfun->curr_properties & PROP_loops));
|
||||
|
||||
/* Find the loops. */
|
||||
/* Find the loops. */
|
||||
|
||||
flow_loops_find (loops);
|
||||
current_loops = 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)
|
||||
{
|
||||
|
@ -104,6 +117,22 @@ loop_optimizer_finalize (void)
|
|||
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)
|
||||
|
@ -112,8 +141,6 @@ loop_optimizer_finalize (void)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
|
@ -200,6 +227,8 @@ struct rtl_opt_pass pass_rtl_loop_init =
|
|||
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);
|
||||
|
||||
|
@ -223,7 +252,7 @@ struct rtl_opt_pass pass_rtl_loop_done =
|
|||
TV_LOOP, /* tv_id */
|
||||
0, /* properties_required */
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
PROP_loops, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
TODO_verify_flow
|
||||
| TODO_verify_rtl_sharing /* todo_flags_finish */
|
||||
|
|
|
@ -1242,7 +1242,7 @@ finalize_task_copyfn (gimple task_stmt)
|
|||
|
||||
/* Inform the callgraph about the new function. */
|
||||
DECL_STRUCT_FUNCTION (child_fn)->curr_properties
|
||||
= cfun->curr_properties;
|
||||
= cfun->curr_properties & ~PROP_loops;
|
||||
|
||||
old_fn = current_function_decl;
|
||||
push_cfun (child_cfun);
|
||||
|
@ -3562,7 +3562,7 @@ expand_omp_taskreg (struct omp_region *region)
|
|||
|
||||
/* Inform the callgraph about the new function. */
|
||||
DECL_STRUCT_FUNCTION (child_fn)->curr_properties
|
||||
= cfun->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
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#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)
|
||||
|
@ -1270,6 +1271,12 @@ tm_log_emit_save_or_restores (basic_block entry_block,
|
|||
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);
|
||||
|
@ -2682,6 +2689,8 @@ expand_transaction (struct tm_region *region)
|
|||
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);
|
||||
|
@ -2719,6 +2728,8 @@ expand_transaction (struct tm_region *region)
|
|||
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);
|
||||
|
|
|
@ -793,7 +793,6 @@ repair_loop_structures (void)
|
|||
#endif
|
||||
scev_reset ();
|
||||
|
||||
loops_state_clear (LOOPS_NEED_FIXUP);
|
||||
timevar_pop (TV_REPAIR_LOOPS);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#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. */
|
||||
|
@ -3041,6 +3042,8 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
|
|||
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);
|
||||
|
||||
|
|
|
@ -2093,7 +2093,7 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
|
|||
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->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;
|
||||
|
|
|
@ -45,6 +45,8 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "cgraph.h"
|
||||
#include "gimple.h"
|
||||
|
||||
extern void add_bb_to_loop (basic_block, struct loop *);
|
||||
|
||||
/* Internal function decls */
|
||||
|
||||
|
||||
|
@ -560,6 +562,10 @@ mf_build_check_statement_for (tree base, tree limit,
|
|||
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");
|
||||
|
|
|
@ -239,6 +239,7 @@ struct dump_file_info
|
|||
#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)
|
||||
|
|
|
@ -92,7 +92,7 @@ struct gimple_opt_pass pass_tree_loop_init =
|
|||
0, /* static_pass_number */
|
||||
TV_TREE_LOOP_INIT, /* tv_id */
|
||||
PROP_cfg, /* properties_required */
|
||||
0, /* properties_provided */
|
||||
PROP_loops, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
0 /* todo_flags_finish */
|
||||
|
|
|
@ -624,6 +624,7 @@ thread_block (basic_block bb, bool noloop_only)
|
|||
{
|
||||
loop->header = NULL;
|
||||
loop->latch = NULL;
|
||||
loops_state_set (LOOPS_NEED_FIXUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -969,6 +970,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
|
|||
original header. */
|
||||
loop->header = NULL;
|
||||
loop->latch = NULL;
|
||||
loops_state_set (LOOPS_NEED_FIXUP);
|
||||
return thread_block (header, false);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue