This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Cleanup bb copying


Hello,

this patch adds a more clear way to copy set of basic blocks, and
uses it to decrease level of dark magic in loop duplication
significantly.

Zdenek

	* cfglayout.c (cfg_layout_duplicate_bb): Do not update frequencies
	at all if edge is not specified.
	(can_copy_bbs_p, copy_bbs): New.
	* cfglayout.h (can_copy_bbs_p, copy_bbs): Declare.
	* cfgloop.c (get_loop_body): Comment more precisely.
	* cfgloopmanip.c (copy_bbs, record_exit_edges): Removed.
	(scale_bbs_frequencies): Fix comment typo.
	(can_duplicate_loop_p): Use can_copy_bbs_p.
	(duplicate_loop_to_header_edge): Simplify by using copy_bbs.

Index: cfglayout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfglayout.c,v
retrieving revision 1.38
diff -c -3 -p -r1.38 cfglayout.c
*** cfglayout.c	27 Jun 2003 09:49:30 -0000	1.38
--- cfglayout.c	1 Jul 2003 00:34:13 -0000
*************** duplicate_insn_chain (rtx from, rtx to)
*** 1029,1035 ****
    delete_insn (last);
    return insn;
  }
! /* Create a duplicate of the basic block BB and redirect edge E into it.  */
  
  basic_block
  cfg_layout_duplicate_bb (basic_block bb, edge e)
--- 1029,1037 ----
    delete_insn (last);
    return insn;
  }
! /* Create a duplicate of the basic block BB and redirect edge E into it.
!    If E is not specified, BB is just copied, but updating the frequencies
!    etc. is left to the caller.  */
  
  basic_block
  cfg_layout_duplicate_bb (basic_block bb, edge e)
*************** cfg_layout_duplicate_bb (basic_block bb,
*** 1091,1119 ****
  	 is no need to actually check for duplicated edges.  */
        n = unchecked_make_edge (new_bb, s->dest, s->flags);
        n->probability = s->probability;
!       if (new_count)
! 	/* Take care for overflows!  */
! 	n->count = s->count * (new_count * 10000 / bb->count) / 10000;
        else
! 	n->count = 0;
!       s->count -= n->count;
      }
  
-   new_bb->count = new_count;
-   bb->count -= new_count;
- 
    if (e)
      {
        new_bb->frequency = EDGE_FREQUENCY (e);
        bb->frequency -= EDGE_FREQUENCY (e);
  
        redirect_edge_and_branch_force (e, new_bb);
-     }
  
!   if (bb->count < 0)
!     bb->count = 0;
!   if (bb->frequency < 0)
!     bb->frequency = 0;
  
    RBI (new_bb)->original = bb;
    RBI (bb)->copy = new_bb;
--- 1093,1129 ----
  	 is no need to actually check for duplicated edges.  */
        n = unchecked_make_edge (new_bb, s->dest, s->flags);
        n->probability = s->probability;
!       if (e && bb->count)
! 	{
! 	  /* Take care for overflows!  */
! 	  n->count = s->count * (new_count * 10000 / bb->count) / 10000;
! 	  s->count -= n->count;
! 	}
        else
! 	n->count = s->count;
!       n->aux = s->aux;
      }
  
    if (e)
      {
+       new_bb->count = new_count;
+       bb->count -= new_count;
+ 
        new_bb->frequency = EDGE_FREQUENCY (e);
        bb->frequency -= EDGE_FREQUENCY (e);
  
        redirect_edge_and_branch_force (e, new_bb);
  
!       if (bb->count < 0)
! 	bb->count = 0;
!       if (bb->frequency < 0)
! 	bb->frequency = 0;
!     }
!   else
!     {
!       new_bb->count = bb->count;
!       new_bb->frequency = bb->frequency;
!     }
  
    RBI (new_bb)->original = bb;
    RBI (bb)->copy = new_bb;
*************** cfg_layout_finalize (void)
*** 1189,1194 ****
--- 1199,1321 ----
  #ifdef ENABLE_CHECKING
    verify_flow_info ();
  #endif
+ }
+ 
+ /* Checks whether all N blocks in BBS array can be copied.  */
+ bool
+ can_copy_bbs_p (basic_block *bbs, unsigned n)
+ {
+   unsigned i;
+   edge e;
+   int ret = true;
+ 
+   for (i = 0; i < n; i++)
+     RBI (bbs[i])->duplicated = 1;
+ 
+   for (i = 0; i < n; i++)
+     {
+       /* In case we should redirect abnormal edge during duplication, fail.  */
+       for (e = bbs[i]->succ; e; e = e->succ_next)
+ 	if ((e->flags & EDGE_ABNORMAL)
+ 	    && RBI (e->dest)->duplicated)
+ 	  {
+ 	    ret = false;
+ 	    goto end;
+ 	  }
+ 
+       if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
+ 	{
+ 	  ret = false;
+ 	  break;
+ 	}
+     }
+ 
+ end:
+   for (i = 0; i < n; i++)
+     RBI (bbs[i])->duplicated = 0;
+ 
+   return ret;
+ }
+ 
+ /* Duplicates N basic blocks stored in array BBS.  Newly created basic blocks
+    are placed into array NEW_BBS in the same order.  Edges from basic blocks
+    in BBS are also duplicated and copies of those of them
+    that lead into BBS are redirected to appropriate newly created block.  The
+    function assigns bbs into loops (copy of basic block bb is assigned to
+    bb->loop_father->copy loop, so this must be set up correctly in advance)
+    and updates dominators locally (LOOPS structure that contains the information
+    about dominators is passed to enable this).
+ 
+    BASE is the superloop to that basic block belongs; if its header or latch
+    is copied, we do not set the new blocks as header or latch.
+ 
+    Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES,
+    also in the same order.  */
+ 
+ void
+ copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
+ 	  edge *edges, unsigned n_edges, edge *new_edges,
+ 	  struct loop *base, struct loops *loops)
+ {
+   unsigned i, j;
+   basic_block bb, new_bb, dom_bb;
+   edge e;
+ 
+   /* Duplicate bbs, update dominators, assign bbs to loops.  */
+   for (i = 0; i < n; i++)
+     {
+       /* Duplicate.  */
+       bb = bbs[i];
+       new_bb = new_bbs[i] = cfg_layout_duplicate_bb (bb, NULL);
+       RBI (bb)->duplicated = 1;
+       /* Add to loop.  */
+       add_bb_to_loop (new_bb, bb->loop_father->copy);
+       add_to_dominance_info (loops->cfg.dom, new_bb);
+       /* Possibly set header.  */
+       if (bb->loop_father->header == bb && bb->loop_father != base)
+ 	new_bb->loop_father->header = new_bb;
+       /* Or latch.  */
+       if (bb->loop_father->latch == bb && bb->loop_father != base)
+ 	new_bb->loop_father->latch = new_bb;
+     }
+ 
+   /* Set dominators.  */
+   for (i = 0; i < n; i++)
+     {
+       bb = bbs[i];
+       new_bb = new_bbs[i];
+ 
+       dom_bb = get_immediate_dominator (loops->cfg.dom, bb);
+       if (RBI (dom_bb)->duplicated)
+ 	{
+ 	  dom_bb = RBI (dom_bb)->copy;
+ 	  set_immediate_dominator (loops->cfg.dom, new_bb, dom_bb);
+ 	}
+     }
+ 
+   /* Redirect edges.  */
+   for (j = 0; j < n_edges; j++)
+     new_edges[j] = NULL;
+   for (i = 0; i < n; i++)
+     {
+       new_bb = new_bbs[i];
+       bb = bbs[i];
+ 
+       for (e = new_bb->succ; e; e = e->succ_next)
+ 	{
+ 	  for (j = 0; j < n_edges; j++)
+ 	    if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest)
+ 	      new_edges[j] = e;
+ 
+ 	  if (!RBI (e->dest)->duplicated)
+ 	    continue;
+ 	  redirect_edge_and_branch_force (e, RBI (e->dest)->copy);
+ 	}
+     }
+ 
+   /* Clear information about duplicates.  */
+   for (i = 0; i < n; i++)
+     RBI (bbs[i])->duplicated = 0;
  }
  
  #include "gt-cfglayout.h"
Index: cfglayout.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfglayout.h,v
retrieving revision 1.7
diff -c -3 -p -r1.7 cfglayout.h
*** cfglayout.h	22 Jun 2003 15:03:26 -0000	1.7
--- cfglayout.h	1 Jul 2003 00:34:13 -0000
*************** extern bool cfg_layout_can_duplicate_bb_
*** 43,45 ****
--- 43,48 ----
  extern basic_block cfg_layout_duplicate_bb (basic_block, edge);
  extern void insn_locators_initialize (void);
  extern void reemit_insn_block_notes (void);
+ extern bool can_copy_bbs_p (basic_block *, unsigned);
+ extern void copy_bbs (basic_block *, unsigned, basic_block *,
+ 		      edge *, unsigned, edge *, struct loop *, struct loops *);
Index: cfgloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.c,v
retrieving revision 1.22
diff -c -3 -p -r1.22 cfgloop.c
*** cfgloop.c	22 Jun 2003 15:03:26 -0000	1.22
--- cfgloop.c	1 Jul 2003 00:34:14 -0000
*************** glb_enum_p (basic_block bb, void *glb_he
*** 960,966 ****
    return bb != (basic_block) glb_header;
  }
  
! /* Gets basic blocks of a loop.  */
  basic_block *
  get_loop_body (const struct loop *loop)
  {
--- 960,968 ----
    return bb != (basic_block) glb_header;
  }
  
! /* Gets basic blocks of a LOOP.  Header is the 0-th block, rest is in dfs
!    order against direction of edges from latch.  Specially, if
!    header != latch, latch is the 1-st block.  */
  basic_block *
  get_loop_body (const struct loop *loop)
  {
Index: cfgloopmanip.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloopmanip.c,v
retrieving revision 1.9
diff -c -3 -p -r1.9 cfgloopmanip.c
*** cfgloopmanip.c	22 Jun 2003 15:03:26 -0000	1.9
--- cfgloopmanip.c	1 Jul 2003 00:34:15 -0000
*************** static void copy_loops_to (struct loops 
*** 36,43 ****
  			   struct loop *);
  static void loop_redirect_edge (edge, basic_block);
  static bool loop_delete_branch_edge (edge, int);
- static void copy_bbs (basic_block *, int, edge, edge, basic_block **,
- 		      struct loops *, edge *, edge *, int);
  static void remove_bbs (dominance_info, basic_block *, int);
  static bool rpe_enum_p (basic_block, void *);
  static int find_path (edge, dominance_info, basic_block **);
--- 36,41 ----
*************** static void fix_bb_placements (struct lo
*** 49,56 ****
  static void place_new_loop (struct loops *, struct loop *);
  static void scale_loop_frequencies (struct loop *, int, int);
  static void scale_bbs_frequencies (basic_block *, int, int, int);
- static void record_exit_edges (edge, basic_block *, int, edge *, unsigned *,
- 			       int);
  static basic_block create_preheader (struct loop *, dominance_info, int);
  static void fix_irreducible_loops (basic_block);
  
--- 47,52 ----
*************** add_loop (struct loops *loops, struct lo
*** 471,477 ****
    free (bbs);
  }
  
! /* Multiply all frequencies of basic blocks in array BBS of lenght NBBS
     by NUM/DEN.  */
  static void
  scale_bbs_frequencies (basic_block *bbs, int nbbs, int num, int den)
--- 467,473 ----
    free (bbs);
  }
  
! /* Multiply all frequencies of basic blocks in array BBS of length NBBS
     by NUM/DEN.  */
  static void
  scale_bbs_frequencies (basic_block *bbs, int nbbs, int num, int den)
*************** loop_delete_branch_edge (edge e, int rea
*** 820,1038 ****
    return false;  /* To avoid warning, cannot get here.  */
  }
  
- /* Duplicates N basic blocks stored in array BBS (they form a body of
-    duplicated loop).  Newly created basic blocks are placed into array NEW_BBS
-    that we allocate.  Edges from basic blocks in BBS are also duplicated and
-    copies of those of them that lead into BBS are redirected to appropriate
-    newly created block.  The function also assigns bbs into loops and updates
-    dominators.  If ADD_IRREDUCIBLE_FLAG is set, newly created basic blocks that
-    are not members of any inner loop are marked irreducible.
- 
-    Additionally, we perform following manipulation with edges:
-    We have two special edges given. LATCH_EDGE is the latch edge of the
-    duplicated loop and leads into its header (one of blocks in BBS);
-    it does not have neccessarily lead from one of the blocks, because
-    we may be copying the loop body several times in unrolling.
-    Edge ENTRY leads also leads to header, and it is either latch or entry
-    edge.  Copy of LATCH_EDGE is redirected to header and is stored in
-    HEADER_EDGE, the ENTRY edge is redirected into copy of header and
-    returned as COPY_HEADER_EDGE.  The effect is following:
-    if LATCH_EDGE == ENTRY, then the loop is unrolled by one copy,
-      HEADER_EDGE is latch of a new loop, COPY_HEADER_EDGE leads from original
-      latch source to first block in copy.
-    if LATCH_EDGE != ENTRY, then the loop is peeled by one copy,
-      HEADER_EDGE is entry edge of the loop, COPY_HEADER_EDGE leads from
-      original entry block to first block in peeled copy.
-  */
- static void
- copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge,
- 	  basic_block **new_bbs, struct loops *loops, edge *header_edge,
- 	  edge *copy_header_edge, int add_irreducible_flag)
- {
-   int i;
-   basic_block bb, new_bb, header = entry->dest, dom_bb;
-   edge e;
- 
-   /* Duplicate bbs, update dominators, assign bbs to loops.  */
-   (*new_bbs) = xcalloc (n, sizeof (basic_block));
-   for (i = 0; i < n; i++)
-     {
-       /* Duplicate.  */
-       bb = bbs[i];
-       new_bb = (*new_bbs)[i] = cfg_layout_duplicate_bb (bb, NULL);
-       RBI (new_bb)->duplicated = 1;
-       /* Add to loop.  */
-       add_bb_to_loop (new_bb, bb->loop_father->copy);
-       add_to_dominance_info (loops->cfg.dom, new_bb);
-       /* Possibly set header.  */
-       if (bb->loop_father->header == bb && bb != header)
- 	new_bb->loop_father->header = new_bb;
-       /* Or latch.  */
-       if (bb->loop_father->latch == bb &&
- 	  bb->loop_father != header->loop_father)
- 	new_bb->loop_father->latch = new_bb;
-       /* Take care of irreducible loops.  */
-       if (add_irreducible_flag
- 	  && bb->loop_father == header->loop_father)
- 	new_bb->flags |= BB_IRREDUCIBLE_LOOP;
-     }
- 
-   /* Set dominators.  */
-   for (i = 0; i < n; i++)
-     {
-       bb = bbs[i];
-       new_bb = (*new_bbs)[i];
-       if (bb != header)
- 	{
- 	  /* For anything else than loop header, just copy it.  */
- 	  dom_bb = get_immediate_dominator (loops->cfg.dom, bb);
- 	  dom_bb = RBI (dom_bb)->copy;
- 	}
-       else
- 	{
- 	  /* Copy of header is dominated by entry source.  */
- 	  dom_bb = entry->src;
- 	}
-       if (!dom_bb)
- 	abort ();
-       set_immediate_dominator (loops->cfg.dom, new_bb, dom_bb);
-     }
- 
-   /* Redirect edges.  */
-   for (i = 0; i < n; i++)
-     {
-       edge e_pred;
-       new_bb = (*new_bbs)[i];
-       bb = bbs[i];
-       for (e = bb->pred; e; e = e_pred)
- 	{
- 	  basic_block src = e->src;
- 
- 	  e_pred = e->pred_next;
- 
- 	  if (!RBI (src)->duplicated)
- 	    continue;
- 
- 	  /* Leads to copied loop and it is not latch edge, redirect it.  */
- 	  if (bb != header)
- 	    loop_redirect_edge (e, new_bb);
- 
- 	  if (add_irreducible_flag
- 	      && (bb->loop_father == header->loop_father
- 		  || RBI (src)->original->loop_father == header->loop_father))
- 	    e->flags |= EDGE_IRREDUCIBLE_LOOP;
- 	}
-     }
- 
-   /* Redirect header edge.  */
-   bb = RBI (latch_edge->src)->copy;
-   for (e = bb->succ; e->dest != latch_edge->dest; e = e->succ_next);
-   *header_edge = e;
-   loop_redirect_edge (*header_edge, header);
- 
-   /* Redirect entry to copy of header.  */
-   loop_redirect_edge (entry, RBI (header)->copy);
-   *copy_header_edge = entry;
- 
-   /* Clear information about duplicates.  */
-   for (i = 0; i < n; i++)
-     RBI ((*new_bbs)[i])->duplicated = 0;
- }
- 
  /* Check whether LOOP's body can be duplicated.  */
  bool
  can_duplicate_loop_p (struct loop *loop)
  {
!   basic_block *bbs;
!   unsigned i;
! 
!   bbs = get_loop_body (loop);
! 
!   for (i = 0; i < loop->num_nodes; i++)
!     {
!       edge e;
! 
!       /* In case loop contains abnormal edge we can not redirect,
!          we can't perform duplication.  */
! 
!       for (e = bbs[i]->succ; e; e = e->succ_next)
! 	if ((e->flags & EDGE_ABNORMAL)
! 	    && flow_bb_inside_loop_p (loop, e->dest))
! 	  {
! 	    free (bbs);
! 	    return false;
! 	  }
  
!       if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
! 	{
! 	  free (bbs);
! 	  return false;
! 	}
!     }
    free (bbs);
! 
!   return true;
  }
  
- /* Record edges, leading from NBBS basic blocks stored in BBS, that were created
-    by copying ORIG edge (or just ORIG edge if IS_ORIG is set).
-    If ORIG is NULL, then record all edges coming outside of BBS. Store them
-    into TO_REMOVE array that must be large enough to hold them all; their
-    number is returned in N_TO_REMOVE.  */
- static void
- record_exit_edges (edge orig, basic_block *bbs, int nbbs, edge *to_remove,
- 		   unsigned int *n_to_remove, int is_orig)
- {
-   sbitmap my_blocks;
-   int i;
-   edge e;
- 
-   if (orig)
-     {
-       if (is_orig)
- 	{
- 	  to_remove[(*n_to_remove)++] = orig;
- 	  return;
- 	}
- 
-       for (e = RBI (orig->src)->copy->succ; e; e = e->succ_next)
- 	if (e->dest == orig->dest)
- 	  break;
-       if (!e)
- 	abort ();
- 
-       to_remove[(*n_to_remove)++] = e;
-     }
-   else
-     {
-       my_blocks = sbitmap_alloc (last_basic_block);
-       sbitmap_zero (my_blocks);
-       for (i = 0; i < nbbs; i++)
-         SET_BIT (my_blocks, bbs[i]->index);
- 
-       for (i = 0; i < nbbs; i++)
- 	for (e = bbs[i]->succ; e; e = e->succ_next)
- 	  if (e->dest == EXIT_BLOCK_PTR ||
- 	      !TEST_BIT (my_blocks, e->dest->index))
- 	    to_remove[(*n_to_remove)++] = e;
- 
-       free (my_blocks);
-     }
- }
- 
- 
  #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
  
! /* Duplicates body of LOOP to given edge E NDUPL times.  Takes care of
!    updating LOOPS structure and dominators.  E's destination must be LOOP
!    header for this to work, i.e. it must be entry or latch edge of this loop;
!    these are unique, as the loops must have preheaders for this function to
!    work correctly (in case E is latch, the function unrolls the loop, if E is
!    entry edge, it peels the loop).  Store edges created by copying ORIG edge
!    (if NULL, then all edges leaving loop) from copies corresponding to set
!    bits in WONT_EXIT bitmap (bit 0 corresponds to original LOOP body, the
!    other copies are numbered in order given by control flow through them)
!    into TO_REMOVE array.  Returns false if duplication is impossible.  */
  int
  duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
  			       unsigned int ndupl, sbitmap wont_exit,
--- 816,846 ----
    return false;  /* To avoid warning, cannot get here.  */
  }
  
  /* Check whether LOOP's body can be duplicated.  */
  bool
  can_duplicate_loop_p (struct loop *loop)
  {
!   int ret;
!   basic_block *bbs = get_loop_body (loop);
  
!   ret = can_copy_bbs_p (bbs, loop->num_nodes);
    free (bbs);
!   
!   return ret;
  }
  
  #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
  
! /* Duplicates body of LOOP to given edge E NDUPL times.  Takes care of updating
!    LOOPS structure and dominators.  E's destination must be LOOP header for
!    this to work, i.e. it must be entry or latch edge of this loop; these are
!    unique, as the loops must have preheaders for this function to work
!    correctly (in case E is latch, the function unrolls the loop, if E is entry
!    edge, it peels the loop).  Store edges created by copying ORIG edge from
!    copies corresponding to set bits in WONT_EXIT bitmap (bit 0 corresponds to
!    original LOOP body, the other copies are numbered in order given by control
!    flow through them) into TO_REMOVE array.  Returns false if duplication is
!    impossible.  */
  int
  duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
  			       unsigned int ndupl, sbitmap wont_exit,
*************** duplicate_loop_to_header_edge (struct lo
*** 1045,1051 ****
    basic_block header = loop->header, latch = loop->latch;
    basic_block *new_bbs, *bbs, *first_active;
    basic_block new_bb, bb, first_active_latch = NULL;
!   edge ae, latch_edge, he;
    unsigned i, j, n;
    int is_latch = (latch == e->src);
    int scale_act = 0, *scale_step = NULL, scale_main = 0;
--- 853,862 ----
    basic_block header = loop->header, latch = loop->latch;
    basic_block *new_bbs, *bbs, *first_active;
    basic_block new_bb, bb, first_active_latch = NULL;
!   edge ae, latch_edge;
!   edge spec_edges[2], new_spec_edges[2];
! #define SE_LATCH 0
! #define SE_ORIG 1
    unsigned i, j, n;
    int is_latch = (latch == e->src);
    int scale_act = 0, *scale_step = NULL, scale_main = 0;
*************** duplicate_loop_to_header_edge (struct lo
*** 1070,1086 ****
    bbs = get_loop_body (loop);
  
    /* Check whether duplication is possible.  */
! 
!   for (i = 0; i < loop->num_nodes; i++)
      {
!       if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
! 	{
! 	  free (bbs);
! 	  return false;
! 	}
      }
  
!   add_irreducible_flag = !is_latch && (e->flags & EDGE_IRREDUCIBLE_LOOP);
  
    /* Find edge from latch.  */
    latch_edge = loop_latch_edge (loop);
--- 881,898 ----
    bbs = get_loop_body (loop);
  
    /* Check whether duplication is possible.  */
!   if (!can_copy_bbs_p (bbs, loop->num_nodes))
      {
!       free (bbs);
!       return false;
      }
+   new_bbs = xmalloc (sizeof (basic_block) * loop->num_nodes);
  
!   /* In case we are doing loop peeling and the loop is in the middle of
!      irreducible region, the peeled copies will be inside it too.  */
!   add_irreducible_flag = e->flags & EDGE_IRREDUCIBLE_LOOP;
!   if (is_latch && add_irreducible_flag)
!     abort ();
  
    /* Find edge from latch.  */
    latch_edge = loop_latch_edge (loop);
*************** duplicate_loop_to_header_edge (struct lo
*** 1140,1146 ****
      }
  
    /* Loop the new bbs will belong to.  */
!   target = find_common_loop (e->src->loop_father, e->dest->loop_father);
  
    /* Original loops.  */
    n_orig_loops = 0;
--- 952,958 ----
      }
  
    /* Loop the new bbs will belong to.  */
!   target = e->src->loop_father;
  
    /* Original loops.  */
    n_orig_loops = 0;
*************** duplicate_loop_to_header_edge (struct lo
*** 1152,1170 ****
  
    loop->copy = target;
  
-   /* Original basic blocks.  */
    n = loop->num_nodes;
  
!   first_active = xcalloc(n, sizeof (basic_block));
    if (is_latch)
      {
        memcpy (first_active, bbs, n * sizeof (basic_block));
        first_active_latch = latch;
      }
  
!   /* Record exit edges in original loop body.  */
!   if (TEST_BIT (wont_exit, 0))
!     record_exit_edges (orig, bbs, n, to_remove, n_to_remove, true);
  
    for (j = 0; j < ndupl; j++)
      {
--- 964,984 ----
  
    loop->copy = target;
  
    n = loop->num_nodes;
  
!   first_active = xmalloc (n * sizeof (basic_block));
    if (is_latch)
      {
        memcpy (first_active, bbs, n * sizeof (basic_block));
        first_active_latch = latch;
      }
  
!   /* Record exit edge in original loop body.  */
!   if (orig && TEST_BIT (wont_exit, 0))
!     to_remove[(*n_to_remove)++] = orig;
! 
!   spec_edges[SE_ORIG] = orig;
!   spec_edges[SE_LATCH] = latch_edge;
  
    for (j = 0; j < ndupl; j++)
      {
*************** duplicate_loop_to_header_edge (struct lo
*** 1172,1249 ****
        copy_loops_to (loops, orig_loops, n_orig_loops, target);
  
        /* Copy bbs.  */
!       copy_bbs (bbs, n, e, latch_edge, &new_bbs, loops,
! 		&e, &he, add_irreducible_flag);
        if (is_latch)
! 	loop->latch = RBI (latch)->copy;
  
!       /* Record exit edges in this copy.  */
!       if (TEST_BIT (wont_exit, j + 1))
! 	record_exit_edges (orig, new_bbs, n, to_remove, n_to_remove, false);
  
!       /* Set counts and frequencies.  */
!       for (i = 0; i < n; i++)
  	{
! 	  new_bb = new_bbs[i];
! 	  bb = bbs[i];
! 
! 	  if (flags & DLTHE_FLAG_UPDATE_FREQ)
  	    {
! 	      new_bb->count = RDIV (scale_act * bb->count, REG_BR_PROB_BASE);
! 	      new_bb->frequency = RDIV (scale_act * bb->frequency,
! 					REG_BR_PROB_BASE);
  	    }
- 	  else
- 	    {
- 	      new_bb->count = bb->count;
- 	      new_bb->frequency = bb->frequency;
- 	    }
- 
- 	  for (ae = new_bb->succ; ae; ae = ae->succ_next)
- 	    ae->count = RDIV (new_bb->count * ae->probability,
- 			      REG_BR_PROB_BASE);
  	}
-       if (flags & DLTHE_FLAG_UPDATE_FREQ)
- 	scale_act = RDIV (scale_act * scale_step[j], REG_BR_PROB_BASE);
  
        if (!first_active_latch)
  	{
  	  memcpy (first_active, new_bbs, n * sizeof (basic_block));
! 	  first_active_latch = RBI (latch)->copy;
  	}
  
!       free (new_bbs);
! 
!       /* Original loop header is dominated by latch copy
! 	 if we duplicated on its only entry edge.  */
!       if (!is_latch && !header->pred->pred_next->pred_next)
! 	set_immediate_dominator (loops->cfg.dom, header, RBI (latch)->copy);
!       if (is_latch && j == 0)
  	{
! 	  /* Update edge from latch.  */
! 	  for (latch_edge = RBI (header)->copy->pred;
! 	       latch_edge->src != latch;
! 	       latch_edge = latch_edge->pred_next);
  	}
      }
!   /* Now handle original loop.  */
! 
!   /* Update edge counts.  */
    if (flags & DLTHE_FLAG_UPDATE_FREQ)
      {
!       for (i = 0; i < n; i++)
! 	{
! 	  bb = bbs[i];
! 	  bb->count = RDIV (scale_main * bb->count, REG_BR_PROB_BASE);
! 	  bb->frequency = RDIV (scale_main * bb->frequency, REG_BR_PROB_BASE);
! 	  for (ae = bb->succ; ae; ae = ae->succ_next)
! 	    ae->count = RDIV (bb->count * ae->probability, REG_BR_PROB_BASE);
! 	}
        free (scale_step);
      }
-   free (orig_loops);
  
!   /* Update dominators of other blocks if affected.  */
    for (i = 0; i < n; i++)
      {
        basic_block dominated, dom_bb, *dom_bbs;
--- 986,1060 ----
        copy_loops_to (loops, orig_loops, n_orig_loops, target);
  
        /* Copy bbs.  */
!       copy_bbs (bbs, n, new_bbs, spec_edges, 2, new_spec_edges, loop, loops);
! 
!       /* Redirect the special edges.  */
        if (is_latch)
! 	{
! 	  redirect_edge_and_branch_force (latch_edge, new_bbs[0]);
! 	  redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
! 					  loop->header);
! 	  set_immediate_dominator (loops->cfg.dom, new_bbs[0], latch);
! 	  latch = loop->latch = new_bbs[1];
! 	  e = latch_edge = new_spec_edges[SE_LATCH];
! 	}
!       else
! 	{
! 	  redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
! 					  loop->header);
! 	  redirect_edge_and_branch_force (e, new_bbs[0]);
! 	  set_immediate_dominator (loops->cfg.dom, new_bbs[0], e->src);
! 	  e = new_spec_edges[SE_LATCH];
! 	}
  
!       /* Record exit edge in this copy.  */
!       if (orig && TEST_BIT (wont_exit, j + 1))
! 	to_remove[(*n_to_remove)++] = new_spec_edges[SE_ORIG];
  
!       /* Note whether the blocks and edges belong to an irreducible loop.  */
!       if (add_irreducible_flag)
  	{
! 	  for (i = 0; i < n; i++)
  	    {
! 	      new_bb = new_bbs[i];
! 	      if (new_bb->loop_father == target)
! 		new_bb->flags |= BB_IRREDUCIBLE_LOOP;
! 
! 	      for (ae = new_bb->succ; ae; ae = ae->succ_next)
! 		if (ae->src->loop_father == target
! 		    || ae->dest->loop_father == target)
! 		  ae->flags |= EDGE_IRREDUCIBLE_LOOP;
  	    }
  	}
  
+       /* Record the first copy in the control flow order if it is not
+ 	 the original loop (i.e. in case of peeling).  */
        if (!first_active_latch)
  	{
  	  memcpy (first_active, new_bbs, n * sizeof (basic_block));
! 	  first_active_latch = latch;
  	}
  
!       /* Set counts and frequencies.  */
!       if (flags & DLTHE_FLAG_UPDATE_FREQ)
  	{
! 	  scale_bbs_frequencies (new_bbs, n, scale_act, REG_BR_PROB_BASE);
! 	  scale_act = RDIV (scale_act * scale_step[j], REG_BR_PROB_BASE);
  	}
      }
!   free (new_bbs);
!   free (orig_loops);
!   
!   /* Update the original loop.  */
!   if (!is_latch)
!     set_immediate_dominator (loops->cfg.dom, e->dest, e->src);
    if (flags & DLTHE_FLAG_UPDATE_FREQ)
      {
!       scale_bbs_frequencies (bbs, n, scale_main, REG_BR_PROB_BASE);
        free (scale_step);
      }
  
!   /* Update dominators of outer blocks if affected.  */
    for (i = 0; i < n; i++)
      {
        basic_block dominated, dom_bb, *dom_bbs;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]