public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Preserve loops from tree to RTL loop optimizers
@ 2012-03-20 15:21 Richard Guenther
  2012-03-21 20:23 ` Richard Sandiford
  0 siblings, 1 reply; 8+ messages in thread
From: Richard Guenther @ 2012-03-20 15:21 UTC (permalink / raw)
  To: gcc-patches


This patch makes us preserve loop structures from the start of tree
loop optimizers to the end of RTL loop optimizers.  It uses a new
property, PROP_loops to indicate we want to preserve them and
massages loop_optimizer_init/finalize to honor that.

On the RTL side the CFG manipulation was not prepared to handle
updating loops, so this patch fills in enough to pass bootstrap
and regtesting.  We still do too much loop fixing from cleanup_cfg
basically because callers do not tell cleanup_cfg if they have
modified the CFG themselves (CSE for example does in some cases).
It was suggested to use a new flag to cleanup_cfg to do that,
other suggestions welcome.

Bootstrapped on x86_64-unknown-linux-gnu, testing shows some
remaining libstdc++ errors, I am investigating them now but
don't expect major issues.

Comments?  The patch is ontop of the early RTL pass merge.

Thanks,
Richard.

2012-03-20  Richard Guenther  <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.
	* cfgcleanup.c (merge_blocks_move): Protect loop latches.
	(cleanup_cfg): If we did something and have loops around, fix
	them up.
	* cfghooks.c (merge_blocks): If we merge a loop header into
	its predecessor, update the loop structure.
	(duplicate_block): If we copy a loop latch, adjust loop state
	to note we may have multiple latches.
	(delete_basic_block): Mark loops for fixup if we remove a loop.
	* cfganal.c (forwarder_block_p): Protect loop latches, headers
	and preheaders.
	* cfgrtl.c (rtl_can_merge_blocks): Protect loop latches.
	(cfg_layout_can_merge_blocks_p): Likewise.
	* cprop.c (bypass_block): If we create a loop with multiple
	entries, mark it for removal.
	* except.c (emit_to_new_bb_before): Add the new basic-block
	to existing loops.
	* tree-eh.c (lower_resx): Likewise.
	* omp-low.c (finalize_task_copyfn): Do not copy PROP_loops.
	(expand_omp_taskreg): Likewise.
	* tree-inline.c (initialize_cfun): Likewise.
	* tree-mudflap.c (add_bb_to_loop): Prototype.
	(mf_build_check_statement_for): Properly add new basic-blocks
	to existing loops.
	* tree-ssa-threadupdate.c (thread_block): Mark loops for fixup
	if we remove a loop.
	(thread_through_loop_header): Likewise.
	* trans-mem.c (tm_log_emit_save_or_restores): Properly add
	new basic-blocks to existing loops.
	(expand_transaction): Likewise.
	* Makefile.in (except.o): Add $(CFGLOOP_H).
	(expr.o): Likewise.
	(cgraph.o): Likewise.
	(cprop.o): Likewise.
	(cfgexpand.o): Likewise.
	(cfganal.o): Likewise.
	(trans-mem.o): Likewise.
	(tree-eh.o): Likewise.

Index: gcc/loop-init.c
===================================================================
*** gcc/loop-init.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/loop-init.c	2012-03-20 13:33:27.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 42,56 ****
  void
  loop_optimizer_init (unsigned flags)
  {
!   struct loops *loops;
  
!   gcc_assert (!current_loops);
!   loops = ggc_alloc_cleared_loops ();
  
!   /* Find the loops.  */
  
!   flow_loops_find (loops);
!   current_loops = loops;
  
    if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES)
      {
--- 42,69 ----
  void
  loop_optimizer_init (unsigned flags)
  {
!   if (!current_loops)
!     {
!       struct loops *loops = ggc_alloc_cleared_loops ();
! 
!       gcc_assert (!(cfun->curr_properties & PROP_loops));
  
!       /* Find the loops.  */
  
!       flow_loops_find (loops);
!       current_loops = loops;
!     }
!   else
!     {
!       gcc_assert (cfun->curr_properties & PROP_loops);
  
!       /* Ensure that the dominators are computed, like flow_loops_find does.  */
!       calculate_dominance_info (CDI_DOMINATORS);
! 
! #ifdef ENABLE_CHECKING
!       verify_loop_structure ();
! #endif
!     }
  
    if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES)
      {
*************** loop_optimizer_finalize (void)
*** 104,109 ****
--- 117,138 ----
    struct loop *loop;
    basic_block bb;
  
+   if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
+     release_recorded_exits ();
+ 
+   /* If we should preserve loop structure, do not free it but clear
+      flags that advanced properties are there as we are not preserving
+      that in full.  */
+   if (cfun->curr_properties & PROP_loops)
+     {
+       loops_state_clear (LOOP_CLOSED_SSA
+ 			 | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS
+ 			 | LOOPS_HAVE_PREHEADERS
+ 			 | LOOPS_HAVE_SIMPLE_LATCHES
+ 			 | LOOPS_HAVE_FALLTHRU_PREHEADERS);
+       return;
+     }
+ 
    gcc_assert (current_loops != NULL);
  
    FOR_EACH_LOOP (li, loop, 0)
*************** loop_optimizer_finalize (void)
*** 112,119 ****
      }
  
    /* Clean up.  */
-   if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
-     release_recorded_exits ();
    flow_loops_free (current_loops);
    ggc_free (current_loops);
    current_loops = NULL;
--- 141,146 ----
*************** struct rtl_opt_pass pass_rtl_loop_init =
*** 200,205 ****
--- 227,234 ----
  static unsigned int
  rtl_loop_done (void)
  {
+   /* No longer preserve loops, remove them now.  */
+   cfun->curr_properties &= ~PROP_loops;
    loop_optimizer_finalize ();
    free_dominance_info (CDI_DOMINATORS);
  
*************** struct rtl_opt_pass pass_rtl_loop_done =
*** 223,229 ****
    TV_LOOP,                              /* tv_id */
    0,                                    /* properties_required */
    0,                                    /* properties_provided */
!   0,                                    /* properties_destroyed */
    0,                                    /* todo_flags_start */
    TODO_verify_flow
      | TODO_verify_rtl_sharing           /* todo_flags_finish */
--- 252,258 ----
    TV_LOOP,                              /* tv_id */
    0,                                    /* properties_required */
    0,                                    /* properties_provided */
!   PROP_loops,                           /* properties_destroyed */
    0,                                    /* todo_flags_start */
    TODO_verify_flow
      | TODO_verify_rtl_sharing           /* todo_flags_finish */
Index: gcc/cgraph.c
===================================================================
*** gcc/cgraph.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/cgraph.c	2012-03-20 13:33:27.000000000 +0100
*************** The callgraph:
*** 99,104 ****
--- 99,105 ----
  #include "ipa-utils.h"
  #include "lto-streamer.h"
  #include "ipa-inline.h"
+ #include "cfgloop.h"
  
  const char * const ld_plugin_symbol_resolution_names[]=
  {
*************** cgraph_release_function_body (struct cgr
*** 1363,1368 ****
--- 1364,1375 ----
      {
        tree old_decl = current_function_decl;
        push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+       if (cfun->cfg
+ 	  && current_loops)
+ 	{
+ 	  cfun->curr_properties &= ~PROP_loops;
+ 	  loop_optimizer_finalize ();
+ 	}
        if (cfun->gimple_df)
  	{
  	  current_function_decl = node->decl;
*************** cgraph_release_function_body (struct cgr
*** 1379,1385 ****
  	}
        if (cfun->value_histograms)
  	free_histograms ();
-       gcc_assert (!current_loops);
        pop_cfun();
        gimple_set_body (node->decl, NULL);
        VEC_free (ipa_opt_pass, heap,
--- 1386,1391 ----
Index: gcc/cfgexpand.c
===================================================================
*** gcc/cfgexpand.c.orig	2012-03-20 11:36:14.000000000 +0100
--- gcc/cfgexpand.c	2012-03-20 13:33:55.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 47,52 ****
--- 47,53 ----
  #include "ssaexpand.h"
  #include "bitmap.h"
  #include "sbitmap.h"
+ #include "cfgloop.h"
  #include "regs.h" /* For reg_renumber.  */
  #include "integrate.h" /* For emit_initial_value_sets.  */
  #include "insn-attr.h" /* For INSN_SCHEDULING.  */
*************** expand_gimple_cond (basic_block bb, gimp
*** 1940,1945 ****
--- 1941,1948 ----
    false_edge->flags |= EDGE_FALLTHRU;
    new_bb->count = false_edge->count;
    new_bb->frequency = EDGE_FREQUENCY (false_edge);
+   if (current_loops && bb->loop_father)
+     add_bb_to_loop (new_bb, bb->loop_father);
    new_edge = make_edge (new_bb, dest, 0);
    new_edge->probability = REG_BR_PROB_BASE;
    new_edge->count = new_bb->count;
*************** construct_init_block (void)
*** 4118,4123 ****
--- 4121,4128 ----
  				   ENTRY_BLOCK_PTR);
    init_block->frequency = ENTRY_BLOCK_PTR->frequency;
    init_block->count = ENTRY_BLOCK_PTR->count;
+   if (current_loops && ENTRY_BLOCK_PTR->loop_father)
+     add_bb_to_loop (init_block, ENTRY_BLOCK_PTR->loop_father);
    if (e)
      {
        first_block = e->dest;
*************** construct_exit_block (void)
*** 4185,4190 ****
--- 4190,4197 ----
  				   EXIT_BLOCK_PTR->prev_bb);
    exit_block->frequency = EXIT_BLOCK_PTR->frequency;
    exit_block->count = EXIT_BLOCK_PTR->count;
+   if (current_loops && EXIT_BLOCK_PTR->loop_father)
+     add_bb_to_loop (exit_block, EXIT_BLOCK_PTR->loop_father);
  
    ix = 0;
    while (ix < EDGE_COUNT (EXIT_BLOCK_PTR->preds))
*************** gimple_expand_cfg (void)
*** 4556,4561 ****
--- 4563,4570 ----
    timevar_push (TV_POST_EXPAND);
    /* We are no longer in SSA form.  */
    cfun->gimple_df->in_ssa_p = false;
+   if (current_loops)
+     loops_state_clear (LOOP_CLOSED_SSA);
  
    /* Expansion is used by optimization passes too, set maybe_hot_insn_p
       conservatively to true until they are all profile aware.  */
Index: gcc/cfgloop.c
===================================================================
*** gcc/cfgloop.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/cfgloop.c	2012-03-20 13:33:27.000000000 +0100
*************** verify_loop_structure (void)
*** 1317,1325 ****
    unsigned num = number_of_loops ();
    loop_iterator li;
    struct loop_exit *exit, *mexit;
  
!   /* We need up-to-date dominators, verify them.  */
!   verify_dominators (CDI_DOMINATORS);
  
    /* Check sizes.  */
    sizes = XCNEWVEC (unsigned, num);
--- 1317,1329 ----
    unsigned num = number_of_loops ();
    loop_iterator li;
    struct loop_exit *exit, *mexit;
+   bool dom_available = dom_info_available_p (CDI_DOMINATORS);
  
!   /* We need up-to-date dominators, compute or verify them.  */
!   if (!dom_available)
!     calculate_dominance_info (CDI_DOMINATORS);
!   else
!     verify_dominators (CDI_DOMINATORS);
  
    /* Check sizes.  */
    sizes = XCNEWVEC (unsigned, num);
*************** verify_loop_structure (void)
*** 1563,1568 ****
--- 1567,1574 ----
    gcc_assert (!err);
  
    free (sizes);
+   if (!dom_available)
+     free_dominance_info (CDI_DOMINATORS);
  }
  
  /* Returns latch edge of LOOP.  */
Index: gcc/tree-pass.h
===================================================================
*** gcc/tree-pass.h.orig	2012-03-20 11:14:19.000000000 +0100
--- gcc/tree-pass.h	2012-03-20 13:33:27.000000000 +0100
*************** struct dump_file_info
*** 239,244 ****
--- 239,245 ----
  #define PROP_gimple_lomp	(1 << 8)	/* lowered OpenMP directives */
  #define PROP_cfglayout	 	(1 << 9)	/* cfglayout mode on RTL */
  #define PROP_gimple_lcx		(1 << 10)       /* lowered complex */
+ #define PROP_loops		(1 << 11)	/* preserve loop structures */
  
  #define PROP_trees \
    (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp)
Index: gcc/tree-ssa-loop.c
===================================================================
*** gcc/tree-ssa-loop.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/tree-ssa-loop.c	2012-03-20 13:33:27.000000000 +0100
*************** struct gimple_opt_pass pass_tree_loop_in
*** 92,98 ****
    0,					/* static_pass_number */
    TV_TREE_LOOP_INIT,			/* tv_id */
    PROP_cfg,				/* properties_required */
!   0,					/* properties_provided */
    0,					/* properties_destroyed */
    0,					/* todo_flags_start */
    0             			/* todo_flags_finish */
--- 92,98 ----
    0,					/* static_pass_number */
    TV_TREE_LOOP_INIT,			/* tv_id */
    PROP_cfg,				/* properties_required */
!   PROP_loops,				/* properties_provided */
    0,					/* properties_destroyed */
    0,					/* todo_flags_start */
    0             			/* todo_flags_finish */
Index: gcc/cfgcleanup.c
===================================================================
*** gcc/cfgcleanup.c.orig	2012-03-20 11:03:49.000000000 +0100
--- gcc/cfgcleanup.c	2012-03-20 13:33:27.000000000 +0100
*************** merge_blocks_move (edge e, basic_block b
*** 779,784 ****
--- 779,789 ----
    if (e->flags & EDGE_FALLTHRU)
      {
        int b_index = b->index, c_index = c->index;
+ 
+       /* Protect the loop latches.  */
+       if (current_loops && c->loop_father->latch == c)
+ 	return NULL;
+ 
        merge_blocks (b, c);
        update_forwarder_flag (b);
  
*************** cleanup_cfg (int mode)
*** 2976,2981 ****
--- 2981,3001 ----
    if (!(mode & CLEANUP_CFGLAYOUT))
      delete_dead_jumptables ();
  
+   /* ???  We do this way too often.  */
+   if (current_loops)
+     {
+       bitmap changed_bbs;
+       timevar_push (TV_REPAIR_LOOPS);
+       /* The above doesn't preserve dominance info if available.  */
+       gcc_assert (!dom_info_available_p (CDI_DOMINATORS));
+       calculate_dominance_info (CDI_DOMINATORS);
+       changed_bbs = BITMAP_ALLOC (NULL);
+       fix_loop_structure (changed_bbs);
+       BITMAP_FREE (changed_bbs);
+       free_dominance_info (CDI_DOMINATORS);
+       timevar_pop (TV_REPAIR_LOOPS);
+     }
+ 
    timevar_pop (TV_CLEANUP_CFG);
  
    return changed;
Index: gcc/cfghooks.c
===================================================================
*** gcc/cfghooks.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/cfghooks.c	2012-03-20 13:33:27.000000000 +0100
*************** delete_basic_block (basic_block bb)
*** 508,513 ****
--- 508,514 ----
  	{
  	  loop->header = NULL;
  	  loop->latch = NULL;
+ 	  loops_state_set (LOOPS_NEED_FIXUP);
  	}
  
        remove_bb_from_loops (bb);
*************** merge_blocks (basic_block a, basic_block
*** 682,689 ****
  
    cfg_hooks->merge_blocks (a, b);
  
    if (current_loops != NULL)
!     remove_bb_from_loops (b);
  
    /* Normally there should only be one successor of A and that is B, but
       partway though the merge of blocks for conditional_execution we'll
--- 683,700 ----
  
    cfg_hooks->merge_blocks (a, b);
  
+   /* If we merge a loop header into its predecessor, update the loop
+      structure.  */
    if (current_loops != NULL)
!     {
!       if (b->loop_father->header == b)
! 	{
! 	  remove_bb_from_loops (a);
! 	  add_bb_to_loop  (a, b->loop_father);
! 	  a->loop_father->header = a;
! 	}
!       remove_bb_from_loops (b);
!     }
  
    /* Normally there should only be one successor of A and that is B, but
       partway though the merge of blocks for conditional_execution we'll
*************** duplicate_block (basic_block bb, edge e,
*** 999,1004 ****
--- 1010,1027 ----
        struct loop *cloop = bb->loop_father;
        struct loop *copy = get_loop_copy (cloop);
        add_bb_to_loop (new_bb, copy ? copy : cloop);
+       /* If we copied the loop latch block but not the loop, adjust
+ 	 loop state.
+ 	 ???  If we copied the loop header block but not the loop
+ 	 we might either have created a loop copy or a loop with
+ 	 multiple entries.  In both cases we probably have to
+ 	 ditch the loops and arrange for a fixup.  */
+       if (!copy
+ 	  && cloop->latch == bb)
+ 	{
+ 	  cloop->latch = NULL;
+ 	  loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+ 	}
      }
  
    return new_bb;
Index: gcc/cfganal.c
===================================================================
*** gcc/cfganal.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/cfganal.c	2012-03-20 13:33:27.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 37,42 ****
--- 37,43 ----
  #include "bitmap.h"
  #include "sbitmap.h"
  #include "timevar.h"
+ #include "cfgloop.h"
  
  /* Store the data structures necessary for depth-first search.  */
  struct depth_first_search_dsS {
*************** forwarder_block_p (const_basic_block bb)
*** 94,99 ****
--- 95,111 ----
        || !single_succ_p (bb))
      return false;
  
+   /* Protect loop latches, headers and preheaders.  */
+   if (current_loops)
+     {
+       basic_block dest;
+       if (bb->loop_father->header == bb)
+ 	return false;
+       dest = EDGE_SUCC (bb, 0)->dest;
+       if (dest->loop_father->header == dest)
+ 	return false;
+     }
+ 
    for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
      if (INSN_P (insn) && flow_active_insn_p (insn))
        return false;
Index: gcc/cfgrtl.c
===================================================================
*** gcc/cfgrtl.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/cfgrtl.c	2012-03-20 13:33:27.000000000 +0100
*************** rtl_can_merge_blocks (basic_block a, bas
*** 727,732 ****
--- 727,736 ----
    if (BB_PARTITION (a) != BB_PARTITION (b))
      return false;
  
+   /* Protect the loop latches.  */
+   if (current_loops && b->loop_father->latch == b)
+     return false;
+ 
    /* There must be exactly one edge in between the blocks.  */
    return (single_succ_p (a)
  	  && single_succ (a) == b
*************** cfg_layout_can_merge_blocks_p (basic_blo
*** 2786,2791 ****
--- 2790,2799 ----
    if (BB_PARTITION (a) != BB_PARTITION (b))
      return false;
  
+   /* Protect the loop latches.  */
+   if (current_loops && b->loop_father->latch == b)
+     return false;
+ 
    /* If we would end up moving B's instructions, make sure it doesn't fall
       through into the exit block, since we cannot recover from a fallthrough
       edge into the exit block occurring in the middle of a function.  */
Index: gcc/cprop.c
===================================================================
*** gcc/cprop.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/cprop.c	2012-03-20 13:33:27.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 48,53 ****
--- 48,54 ----
  #include "df.h"
  #include "dbgcnt.h"
  #include "target.h"
+ #include "cfgloop.h"
  
  \f
  /* An obstack for our working variables.  */
*************** bypass_block (basic_block bb, rtx setcc,
*** 1610,1615 ****
--- 1611,1627 ----
  	      && dest != old_dest
  	      && dest != EXIT_BLOCK_PTR)
              {
+ 	      if (current_loops != NULL
+ 		  && e->src->loop_father->latch == e->src)
+ 		{
+ 		  /* ???  Now we are creating (or may create) a loop
+ 		     with multiple entries.  Simply mark it for
+ 		     removal.  Alternatively we could not do this
+ 		     threading.  */
+ 		  e->src->loop_father->header = NULL;
+ 		  e->src->loop_father->latch = NULL;
+ 		}
+ 
  	      redirect_edge_and_branch_force (e, dest);
  
  	      /* Copy the register setter to the redirected edge.
Index: gcc/omp-low.c
===================================================================
*** gcc/omp-low.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/omp-low.c	2012-03-20 13:33:27.000000000 +0100
*************** finalize_task_copyfn (gimple task_stmt)
*** 1242,1248 ****
  
    /* Inform the callgraph about the new function.  */
    DECL_STRUCT_FUNCTION (child_fn)->curr_properties
!     = cfun->curr_properties;
  
    old_fn = current_function_decl;
    push_cfun (child_cfun);
--- 1242,1248 ----
  
    /* Inform the callgraph about the new function.  */
    DECL_STRUCT_FUNCTION (child_fn)->curr_properties
!     = cfun->curr_properties & ~PROP_loops;
  
    old_fn = current_function_decl;
    push_cfun (child_cfun);
*************** expand_omp_taskreg (struct omp_region *r
*** 3562,3568 ****
  
        /* Inform the callgraph about the new function.  */
        DECL_STRUCT_FUNCTION (child_fn)->curr_properties
! 	= cfun->curr_properties;
        cgraph_add_new_function (child_fn, true);
  
        /* Fix the callgraph edges for child_cfun.  Those for cfun will be
--- 3562,3568 ----
  
        /* Inform the callgraph about the new function.  */
        DECL_STRUCT_FUNCTION (child_fn)->curr_properties
! 	= cfun->curr_properties & ~PROP_loops;
        cgraph_add_new_function (child_fn, true);
  
        /* Fix the callgraph edges for child_cfun.  Those for cfun will be
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/tree-inline.c	2012-03-20 13:33:27.000000000 +0100
*************** initialize_cfun (tree new_fndecl, tree c
*** 2093,2099 ****
    cfun->static_chain_decl = src_cfun->static_chain_decl;
    cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area;
    cfun->function_end_locus = src_cfun->function_end_locus;
!   cfun->curr_properties = src_cfun->curr_properties;
    cfun->last_verified = src_cfun->last_verified;
    cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
    cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
--- 2093,2099 ----
    cfun->static_chain_decl = src_cfun->static_chain_decl;
    cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area;
    cfun->function_end_locus = src_cfun->function_end_locus;
!   cfun->curr_properties = src_cfun->curr_properties & ~PROP_loops;
    cfun->last_verified = src_cfun->last_verified;
    cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
    cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
Index: gcc/tree-mudflap.c
===================================================================
*** gcc/tree-mudflap.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/tree-mudflap.c	2012-03-20 13:33:27.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 45,50 ****
--- 45,52 ----
  #include "cgraph.h"
  #include "gimple.h"
  
+ extern void add_bb_to_loop (basic_block, struct loop *);
+ 
  /* Internal function decls */
  
  
*************** mf_build_check_statement_for (tree base,
*** 560,565 ****
--- 562,571 ----
        set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
      }
  
+   /* Update loop info.  */
+   if (current_loops)
+     add_bb_to_loop (then_bb, cond_bb->loop_father);
+ 
    /* Build our local variables.  */
    mf_elem = make_rename_temp (mf_cache_structptr_type, "__mf_elem");
    mf_base = make_rename_temp (mf_uintptr_type, "__mf_base");
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig	2012-03-20 11:36:41.000000000 +0100
--- gcc/Makefile.in	2012-03-20 14:37:29.000000000 +0100
*************** trans-mem.o : trans-mem.c $(CONFIG_H) $(
*** 2159,2165 ****
  	$(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \
  	$(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \
  	$(PARAMS_H) $(TARGET_H) langhooks.h \
! 	tree-pretty-print.h gimple-pretty-print.h
  
  ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h		\
  	$(GGC_H) $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h	\
--- 2159,2165 ----
  	$(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \
  	$(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \
  	$(PARAMS_H) $(TARGET_H) langhooks.h \
! 	tree-pretty-print.h gimple-pretty-print.h $(CFGLOOP_H)
  
  ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h		\
  	$(GGC_H) $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h	\
*************** tree-ssa-operands.o : tree-ssa-operands.
*** 2468,2474 ****
  tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) langhooks.h \
     $(GGC_H) $(TREE_PASS_H) coretypes.h $(TIMEVAR_H) pointer-set.h \
!    $(TREE_DUMP_H) $(TREE_INLINE_H) tree-iterator.h toplev.h $(DIAGNOSTIC_CORE_H)
  tree-ssa-loop.o : tree-ssa-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) output.h \
     $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TREE_PASS_H) $(TIMEVAR_H) \
--- 2468,2475 ----
  tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) langhooks.h \
     $(GGC_H) $(TREE_PASS_H) coretypes.h $(TIMEVAR_H) pointer-set.h \
!    $(TREE_DUMP_H) $(TREE_INLINE_H) tree-iterator.h toplev.h \
!    $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H)
  tree-ssa-loop.o : tree-ssa-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) output.h \
     $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TREE_PASS_H) $(TIMEVAR_H) \
*************** except.o : except.c $(CONFIG_H) $(SYSTEM
*** 2814,2820 ****
     dwarf2asm.h dwarf2out.h toplev.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) intl.h $(GGC_H) \
     gt-except.h $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) $(DWARF2_H) \
     $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H) $(TREE_FLOW_H) \
!    tree-pretty-print.h sbitmap.h $(COMMON_TARGET_H)
  expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
     $(LIBFUNCS_H) $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \
--- 2815,2821 ----
     dwarf2asm.h dwarf2out.h toplev.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) intl.h $(GGC_H) \
     gt-except.h $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) $(DWARF2_H) \
     $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H) $(TREE_FLOW_H) \
!    tree-pretty-print.h sbitmap.h $(COMMON_TARGET_H) $(CFGLOOP_H)
  expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
     $(LIBFUNCS_H) $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \
*************** cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM
*** 2912,2918 ****
     gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
     $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) cif-code.def \
     value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) \
!    ipa-inline.h $(LTO_STREAMER_H)
  cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
--- 2913,2919 ----
     gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
     $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) cif-code.def \
     value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) \
!    ipa-inline.h $(LTO_STREAMER_H) $(CFGLOOP_H)
  cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
*************** cprop.o : cprop.c $(CONFIG_H) $(SYSTEM_H
*** 3029,3035 ****
     $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \
     $(TM_P_H) $(PARAMS_H) cselib.h $(EXCEPT_H) $(TREE_H) $(TIMEVAR_H) \
     intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \
!    $(DF_H)
  gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \
     $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \
--- 3030,3036 ----
     $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \
     $(TM_P_H) $(PARAMS_H) cselib.h $(EXCEPT_H) $(TREE_H) $(TIMEVAR_H) \
     intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \
!    $(DF_H) $(CFGLOOP_H)
  gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \
     $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h $(DIAGNOSTIC_CORE_H) \
*************** cfgexpand.o : cfgexpand.c $(TREE_FLOW_H)
*** 3149,3155 ****
     $(DIAGNOSTIC_H) toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \
     value-prof.h $(TREE_INLINE_H) $(TARGET_H) $(SSAEXPAND_H) $(REGS_H) \
     tree-pretty-print.h gimple-pretty-print.h $(BITMAP_H) sbitmap.h \
!    $(INSN_ATTR_H) $(INTEGRATE_H)
  cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
     $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
     output.h  $(FUNCTION_H) $(EXCEPT_H) $(TM_P_H) $(INSN_ATTR_H) \
--- 3150,3156 ----
     $(DIAGNOSTIC_H) toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \
     value-prof.h $(TREE_INLINE_H) $(TARGET_H) $(SSAEXPAND_H) $(REGS_H) \
     tree-pretty-print.h gimple-pretty-print.h $(BITMAP_H) sbitmap.h \
!    $(INSN_ATTR_H) $(INTEGRATE_H) $(CFGLOOP_H)
  cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
     $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
     output.h  $(FUNCTION_H) $(EXCEPT_H) $(TM_P_H) $(INSN_ATTR_H) \
*************** cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM
*** 3158,3164 ****
     $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H)
  cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(TM_P_H) \
!    $(TIMEVAR_H) $(OBSTACK_H) $(DIAGNOSTIC_CORE_H) vecprim.h sbitmap.h $(BITMAP_H)
  cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h $(DIAGNOSTIC_CORE_H) \
     $(FUNCTION_H) $(EXCEPT_H) $(TIMEVAR_H) $(TREE_H) $(EXPR_H) sbitmap.h
--- 3159,3166 ----
     $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H)
  cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(TM_P_H) \
!    $(TIMEVAR_H) $(OBSTACK_H) $(DIAGNOSTIC_CORE_H) vecprim.h sbitmap.h \
!    $(BITMAP_H) $(CFGLOOP_H)
  cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h $(DIAGNOSTIC_CORE_H) \
     $(FUNCTION_H) $(EXCEPT_H) $(TIMEVAR_H) $(TREE_H) $(EXPR_H) sbitmap.h
Index: gcc/trans-mem.c
===================================================================
*** gcc/trans-mem.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/trans-mem.c	2012-03-20 13:33:27.000000000 +0100
***************
*** 34,39 ****
--- 34,40 ----
  #include "langhooks.h"
  #include "tree-pretty-print.h"
  #include "gimple-pretty-print.h"
+ #include "cfgloop.h"
  
  
  #define PROB_VERY_UNLIKELY	(REG_BR_PROB_BASE / 2000 - 1)
*************** tm_log_emit_save_or_restores (basic_bloc
*** 1270,1275 ****
--- 1271,1282 ----
    cond_bb = create_empty_bb (before_bb);
    code_bb = create_empty_bb (cond_bb);
    *end_bb = create_empty_bb (code_bb);
+   if (current_loops && before_bb->loop_father)
+     {
+       add_bb_to_loop (cond_bb, before_bb->loop_father);
+       add_bb_to_loop (code_bb, before_bb->loop_father);
+       add_bb_to_loop (*end_bb, before_bb->loop_father);
+     }
    redirect_edge_pred (fallthru_edge, *end_bb);
    fallthru_edge->flags = EDGE_FALLTHRU;
    make_edge (before_bb, cond_bb, old_flags);
*************** expand_transaction (struct tm_region *re
*** 2682,2687 ****
--- 2689,2696 ----
        basic_block test_bb;
  
        test_bb = create_empty_bb (slice_bb);
+       if (current_loops && slice_bb->loop_father)
+ 	add_bb_to_loop (test_bb, slice_bb->loop_father);
        if (VEC_empty (tree, tm_log_save_addresses))
  	region->entry_block = test_bb;
        gsi = gsi_last_bb (test_bb);
*************** expand_transaction (struct tm_region *re
*** 2719,2724 ****
--- 2728,2735 ----
        basic_block empty_bb;
  
        region->entry_block = empty_bb = create_empty_bb (atomic_bb);
+       if (current_loops && atomic_bb->loop_father)
+ 	add_bb_to_loop (empty_bb, atomic_bb->loop_father);
  
        e = FALLTHRU_EDGE (atomic_bb);
        redirect_edge_pred (e, empty_bb);
Index: gcc/tree-ssa-threadupdate.c
===================================================================
*** gcc/tree-ssa-threadupdate.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/tree-ssa-threadupdate.c	2012-03-20 13:33:27.000000000 +0100
*************** thread_block (basic_block bb, bool noloo
*** 624,629 ****
--- 624,630 ----
  	{
  	  loop->header = NULL;
  	  loop->latch = NULL;
+ 	  loops_state_set (LOOPS_NEED_FIXUP);
  	}
      }
  
*************** thread_through_loop_header (struct loop
*** 969,974 ****
--- 970,976 ----
  	 original header.  */
        loop->header = NULL;
        loop->latch = NULL;
+       loops_state_set (LOOPS_NEED_FIXUP);
        return thread_block (header, false);
      }
  
Index: gcc/cfgloopmanip.c
===================================================================
*** gcc/cfgloopmanip.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/cfgloopmanip.c	2012-03-20 13:33:27.000000000 +0100
*************** fix_loop_structure (bitmap changed_bbs)
*** 1728,1733 ****
--- 1728,1735 ----
    if (record_exits)
      record_loop_exits ();
  
+   loops_state_clear (LOOPS_NEED_FIXUP);
+ 
  #ifdef ENABLE_CHECKING
    verify_loop_structure ();
  #endif
Index: gcc/tree-cfgcleanup.c
===================================================================
*** gcc/tree-cfgcleanup.c.orig	2012-03-20 10:54:47.000000000 +0100
--- gcc/tree-cfgcleanup.c	2012-03-20 13:33:27.000000000 +0100
*************** repair_loop_structures (void)
*** 793,799 ****
  #endif
    scev_reset ();
  
-   loops_state_clear (LOOPS_NEED_FIXUP);
    timevar_pop (TV_REPAIR_LOOPS);
  }
  
--- 793,798 ----
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2012-03-20 10:51:26.000000000 +0100
--- gcc/except.c	2012-03-20 13:50:05.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 144,149 ****
--- 144,150 ----
  #include "tree-pass.h"
  #include "timevar.h"
  #include "tree-flow.h"
+ #include "cfgloop.h"
  
  /* Provide defaults for stuff that may not be defined when using
     sjlj exceptions.  */
*************** static basic_block
*** 898,904 ****
  emit_to_new_bb_before (rtx seq, rtx insn)
  {
    rtx last;
!   basic_block bb;
    edge e;
    edge_iterator ei;
  
--- 899,905 ----
  emit_to_new_bb_before (rtx seq, rtx insn)
  {
    rtx last;
!   basic_block bb, prev_bb;
    edge e;
    edge_iterator ei;
  
*************** emit_to_new_bb_before (rtx seq, rtx insn
*** 913,921 ****
    last = emit_insn_before (seq, insn);
    if (BARRIER_P (last))
      last = PREV_INSN (last);
!   bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb);
    update_bb_for_insn (bb);
    bb->flags |= BB_SUPERBLOCK;
    return bb;
  }
  \f
--- 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;
  }
  \f
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c.orig	2012-02-10 15:44:24.000000000 +0100
--- gcc/tree-eh.c	2012-03-20 14:37:11.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 38,43 ****
--- 38,44 ----
  #include "diagnostic-core.h"
  #include "gimple.h"
  #include "target.h"
+ #include "cfgloop.h"
  
  /* In some instances a tree and a gimple need to be stored in a same table,
     i.e. in hash tables. This is a structure to do this. */
*************** lower_resx (basic_block bb, gimple stmt,
*** 3062,3067 ****
--- 3063,3070 ----
  	  e = make_edge (bb, new_bb, EDGE_FALLTHRU);
  	  e->count = bb->count;
  	  e->probability = REG_BR_PROB_BASE;
+ 	  if (current_loops)
+ 	    add_bb_to_loop (new_bb, bb->loop_father);
  	}
        else
  	{

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Preserve loops from tree to RTL loop optimizers
  2012-03-20 15:21 [PATCH] Preserve loops from tree to RTL loop optimizers Richard Guenther
@ 2012-03-21 20:23 ` Richard Sandiford
  2012-03-23 14:14   ` Richard Guenther
  0 siblings, 1 reply; 8+ messages in thread
From: Richard Sandiford @ 2012-03-21 20:23 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

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.
>
> Bootstrapped on x86_64-unknown-linux-gnu, testing shows some
> remaining libstdc++ errors, I am investigating them now but
> don't expect major issues.
>
> Comments?  The patch is ontop of the early RTL pass merge.

Thanks 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).

Richard

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Preserve loops from tree to RTL loop optimizers
  2012-03-21 20:23 ` Richard Sandiford
@ 2012-03-23 14:14   ` Richard Guenther
  2012-03-28 12:14     ` Richard Guenther
  0 siblings, 1 reply; 8+ messages in thread
From: Richard Guenther @ 2012-03-23 14:14 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

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"
  
  \f
  /* 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;
  }
  \f
--- 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;
  }
  \f
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)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Preserve loops from tree to RTL loop optimizers
  2012-03-23 14:14   ` Richard Guenther
@ 2012-03-28 12:14     ` Richard Guenther
  0 siblings, 0 replies; 8+ messages in thread
From: Richard Guenther @ 2012-03-28 12:14 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

[-- Attachment #1: Type: TEXT/PLAIN, Size: 43202 bytes --]

On Fri, 23 Mar 2012, Richard Guenther wrote:

> 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 ...).

Done.

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"
>   
>   \f
>   /* 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;
>   }
>   \f
> --- 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;
>   }
>   \f
> 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)
> 

-- 
Richard Guenther <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Preserve loops from tree to RTL loop optimizers
  2012-06-16 18:40   ` H.J. Lu
@ 2012-09-02 17:08     ` H.J. Lu
  0 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2012-09-02 17:08 UTC (permalink / raw)
  To: Ramana Radhakrishnan
  Cc: David Edelsohn, Richard Guenther, Richard Sandiford, GCC Patches

On Sat, Jun 16, 2012 at 9:01 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sun, Apr 1, 2012 at 11:51 PM, Ramana Radhakrishnan
> <ramana.radhakrishnan@linaro.org> wrote:
>> On 1 April 2012 23:55, David Edelsohn <dje.gcc@gmail.com> wrote:
>>>> If there are no further comments I am inclined to commit this
>>>> patch early next week (possibly causing quite some fallout ...).
>>>
>>> I am glad there was not more fallout.  Unfortunately powerpc-aix was
>>> not so lucky:
>>>
>>> /farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc: In function
>>> 'std::streamsize
>>> std::__copy_streambufs_eof(std::basic_streambuf<_CharT, _Traits>*,
>>> std::basic_streambuf<_CharT, _Traits>*, bool&) [with _CharT = wchar_t;
>>> _Traits = std::char_traits<wchar_t>; std::streamsize = long int]':
>>> /farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc:113:5: internal
>>> compiler error: in get_loop_body, at cfgloop.c:831
>>
>>
>> This looks similar to  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52800
>>
>
> This also caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53695
>

This also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54458

-- 
H.J.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Preserve loops from tree to RTL loop optimizers
  2012-04-02  6:52 ` Ramana Radhakrishnan
@ 2012-06-16 18:40   ` H.J. Lu
  2012-09-02 17:08     ` H.J. Lu
  0 siblings, 1 reply; 8+ messages in thread
From: H.J. Lu @ 2012-06-16 18:40 UTC (permalink / raw)
  To: Ramana Radhakrishnan
  Cc: David Edelsohn, Richard Guenther, Richard Sandiford, GCC Patches

On Sun, Apr 1, 2012 at 11:51 PM, Ramana Radhakrishnan
<ramana.radhakrishnan@linaro.org> wrote:
> On 1 April 2012 23:55, David Edelsohn <dje.gcc@gmail.com> wrote:
>>> If there are no further comments I am inclined to commit this
>>> patch early next week (possibly causing quite some fallout ...).
>>
>> I am glad there was not more fallout.  Unfortunately powerpc-aix was
>> not so lucky:
>>
>> /farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc: In function
>> 'std::streamsize
>> std::__copy_streambufs_eof(std::basic_streambuf<_CharT, _Traits>*,
>> std::basic_streambuf<_CharT, _Traits>*, bool&) [with _CharT = wchar_t;
>> _Traits = std::char_traits<wchar_t>; std::streamsize = long int]':
>> /farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc:113:5: internal
>> compiler error: in get_loop_body, at cfgloop.c:831
>
>
> This looks similar to  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52800
>

This also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53695


-- 
H.J.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Preserve loops from tree to RTL loop optimizers
  2012-04-01 22:55 David Edelsohn
@ 2012-04-02  6:52 ` Ramana Radhakrishnan
  2012-06-16 18:40   ` H.J. Lu
  0 siblings, 1 reply; 8+ messages in thread
From: Ramana Radhakrishnan @ 2012-04-02  6:52 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Richard Guenther, Richard Sandiford, GCC Patches

On 1 April 2012 23:55, David Edelsohn <dje.gcc@gmail.com> wrote:
>> If there are no further comments I am inclined to commit this
>> patch early next week (possibly causing quite some fallout ...).
>
> I am glad there was not more fallout.  Unfortunately powerpc-aix was
> not so lucky:
>
> /farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc: In function
> 'std::streamsize
> std::__copy_streambufs_eof(std::basic_streambuf<_CharT, _Traits>*,
> std::basic_streambuf<_CharT, _Traits>*, bool&) [with _CharT = wchar_t;
> _Traits = std::char_traits<wchar_t>; std::streamsize = long int]':
> /farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc:113:5: internal
> compiler error: in get_loop_body, at cfgloop.c:831


This looks similar to  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52800

Ramana

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Preserve loops from tree to RTL loop optimizers
@ 2012-04-01 22:55 David Edelsohn
  2012-04-02  6:52 ` Ramana Radhakrishnan
  0 siblings, 1 reply; 8+ messages in thread
From: David Edelsohn @ 2012-04-01 22:55 UTC (permalink / raw)
  To: Richard Guenther, Richard Sandiford; +Cc: GCC Patches

> If there are no further comments I am inclined to commit this
> patch early next week (possibly causing quite some fallout ...).

I am glad there was not more fallout.  Unfortunately powerpc-aix was
not so lucky:

/farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc: In function
'std::streamsize
std::__copy_streambufs_eof(std::basic_streambuf<_CharT, _Traits>*,
std::basic_streambuf<_CharT, _Traits>*, bool&) [with _CharT = wchar_t;
_Traits = std::char_traits<wchar_t>; std::streamsize = long int]':
/farm/dje/src/src/libstdc++-v3/src/c++98/streambuf.cc:113:5: internal
compiler error: in get_loop_body, at cfgloop.c:831

Line 831 is:

  gcc_assert (tv == loop->num_nodes);

Reverting the patch fixes the ICE.

- David

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-09-02 17:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-20 15:21 [PATCH] Preserve loops from tree to RTL loop optimizers Richard Guenther
2012-03-21 20:23 ` Richard Sandiford
2012-03-23 14:14   ` Richard Guenther
2012-03-28 12:14     ` Richard Guenther
2012-04-01 22:55 David Edelsohn
2012-04-02  6:52 ` Ramana Radhakrishnan
2012-06-16 18:40   ` H.J. Lu
2012-09-02 17:08     ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).