]> gcc.gnu.org Git - gcc.git/commitdiff
loop-init.c (loop_optimizer_init): If loops are preserved perform incremental initial...
authorRichard Guenther <rguenther@suse.de>
Wed, 28 Mar 2012 12:14:26 +0000 (12:14 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 28 Mar 2012 12:14:26 +0000 (12:14 +0000)
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

24 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/basic-block.h
gcc/cfganal.c
gcc/cfgcleanup.c
gcc/cfgexpand.c
gcc/cfghooks.c
gcc/cfgloop.c
gcc/cfgloopmanip.c
gcc/cfgrtl.c
gcc/cgraph.c
gcc/cprop.c
gcc/cse.c
gcc/except.c
gcc/loop-init.c
gcc/omp-low.c
gcc/trans-mem.c
gcc/tree-cfgcleanup.c
gcc/tree-eh.c
gcc/tree-inline.c
gcc/tree-mudflap.c
gcc/tree-pass.h
gcc/tree-ssa-loop.c
gcc/tree-ssa-threadupdate.c

index 2491a8cdf16d0b019235f1cda946325d48eebf48..3509bda22595133523742ccceff7da95a8ffe9c9 100644 (file)
@@ -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
index 716b3a43d2a48dd5145aef297aad0e5067424089..d50faccca52acc155982470f5912389112d5c8f3 100644 (file)
@@ -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
index 3ff1cd645ea42194ab51e4f6ad7be05cb514a37b..fb17bad9d0548924607fb6333a338cf1ae8e9eb2 100644 (file)
@@ -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 *,
index e27bbb2c6be79bbcb8edc5ff470cc6953d2874d6..d361ff08f98d3a27066a50e319615a8b7498c1f5 100644 (file)
@@ -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;
index c695878802c2dd358f8517e597f718f1bccf0f6d..3824797485dca9d3bf072db0a5b7ba340a276958 100644 (file)
@@ -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;
index 75d2b1628659ce80d46f397c891c8dba2c9be13b..d148853143b3b3ac8964c3c4453a75608b3cd406 100644 (file)
@@ -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.  */
index c4c51cc44042cf4258d9fbbe23c1aa8218578164..1dca79a70cf2952d04eb4ab737846ae64e745b21 100644 (file)
@@ -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;
index 160486f13b12717d07eac7c66ac46f58c3012fac..94ba874b1010da58ebaf7d94369b8fc550acb0c5 100644 (file)
@@ -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.  */
index 33bcf4b987279f500c834564b28145b7a5ccb102..5292ae536b568139d9f8171e4aab92487363b227 100644 (file)
@@ -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
index b86cc74b6a45f996ff0a79cdf56cfb1df4695711..ea293933704656a55ff34ab07135e9b55c4dae6f 100644 (file)
@@ -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.  */
index 7c44c0592457f49eabfd8f79d340a23478a06c6f..e429a91d82e4cec158d5190d0f2ab77af785d11b 100644 (file)
@@ -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,
index 01f40f0bc724e0b4d899396a42b5d23d5965798b..024dd207655b5648154e40b4331122af434173a9 100644 (file)
@@ -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"
 
 \f
 /* 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.
index a414590718387c40c609c5d49506dd8197def931..d8f07e95eac0ec3598627742a6046f5a0a4e7bd3 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -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)
index eb27648786cf4f09502abe1e8a813c45832c7fe3..ddc865217bd467c82110d655145cb9d25a809faa 100644 (file)
@@ -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;
 }
 \f
index daf5fa074100019221cea3a81e52e160c7124666..b8d7b7ee7ce9b3801a6c0fa202634f362d296be1 100644 (file)
@@ -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 (!(cfun->curr_properties & PROP_loops));
 
-  gcc_assert (!current_loops);
-  loops = ggc_alloc_cleared_loops ();
+      /* Find the loops.  */
 
-  /* Find the loops.  */
+      flow_loops_find (loops);
+      current_loops = loops;
+    }
+  else
+    {
+      gcc_assert (cfun->curr_properties & PROP_loops);
 
-  flow_loops_find (loops);
-  current_loops = 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 */
index 84986efcddad8b16fc913f94fd0fcda44edfb6ee..ec1a5522d7f8ebcbe830a038beef6fef28fcaf09 100644 (file)
@@ -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
index 2badf250650850b2d0216b150ade3d07b3567dd6..65f40e69c1bfa461963a4de569fa3dc6dd505cab 100644 (file)
@@ -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);
index 0c8c0852024bc63c53fb379bf7d548e4752677e0..d28783b6b98c7d43c8d67ee74cf55af15b967527 100644 (file)
@@ -793,7 +793,6 @@ repair_loop_structures (void)
 #endif
   scev_reset ();
 
-  loops_state_clear (LOOPS_NEED_FIXUP);
   timevar_pop (TV_REPAIR_LOOPS);
 }
 
index 521e2f7f44a451fe2a3ce583e05892708a41bcef..f19dc2cdffb582f0f055825af5bff1e0126d3993 100644 (file)
@@ -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);
 
index 5d58c5169bb5aa53c0e03dd6db7331df1b722279..d61b6b6a023d3704a9457682d344b3ea881c33c4 100644 (file)
@@ -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;
index e4f6ec0b3319c94599400e20f0df673409c353df..cc8b98d1ea40c59b1b05dfd82644b8a78b3b1015 100644 (file)
@@ -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");
index f5cffa3375bfc2f510de1a05f1837d37b9ee5fb6..f849a54246571b307f0a84a044708de62a16582c 100644 (file)
@@ -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)
index 91eeb16cec9b9993a0e906b83786320c9e7335f9..a91bf3919add63eb47c6acddf31b5e8682ba31c4 100644 (file)
@@ -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 */
index 6000a0331c08e43107ccac962950205d4a778da1..4532886ca965d4baa8fad1641e17af23a82e3715 100644 (file)
@@ -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);
     }
 
This page took 0.112396 seconds and 5 git commands to generate.