Beispiel #1
0
void
L_sort_loops (int *loop_array, int num_loops)
{
  int i;
  Set loop_set;
  L_Loop *loop;

  loop_set = NULL;

  for (i = 0; i < num_loops; i++)
    {
      for (loop = L_fn->first_loop; loop != NULL; loop = loop->next_loop)
        {
          if (Set_in (loop_set, loop->id))
            continue;
          if (Set_subtract_empty (loop->nested_loops, loop_set))
            {
              loop_set = Set_add (loop_set, loop->id);
              loop_array[i] = loop->id;
              break;
            }
        }
      if (!loop_array[i])
        L_punt ("L_sort_loops: Loops are not properly nested");
    }

  Set_dispose (loop_set);
}
int
L_store_union_dominates_load (L_Func * fn, L_Cb * cb, L_Oper * oper, Set RDEF)
{
  int i, size;
  int *buf;
  L_Cb *def_cb, *start;
  Set cbset;
  int val;

  cbset = NULL;
  /* start needs to dominate all nodes in function */
  start = fn->first_cb;

  /* Convert RDEF is a set of cbs */
  size = Set_size (RDEF);
  if (!size)
    return 0;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (RDEF, buf);
  for (i = 0; i < size; i++)
    {
      def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      cbset = Set_add (cbset, def_cb->id);
    }
  Lcode_free (buf);

  /* Does cbset dominate cb from start */
  val = L_cb_set_dominates (fn, start, cb, cbset);
  cbset = Set_dispose (cbset);

  return val;
}
Beispiel #3
0
void
LB_elim_all_loop_backedges (L_Func * fn)
{
  int loop_count;
  L_Loop *loop;
  Set loop_done;

  /* count how many loops there are */
  loop_count = 0;
  for (loop = fn->first_loop; loop; loop = loop->next_loop)
    loop_count++;

  /* inner most to outer */
  loop_done = NULL;
  while (Set_size (loop_done) < loop_count)
    {
      for (loop = fn->first_loop; loop; loop = loop->next_loop)
	{
	  if (Set_in (loop_done, loop->id))
	    continue;
	  if (!Set_subtract_empty (loop->nested_loops, loop_done))
	    continue;
	  loop_done = Set_add (loop_done, loop->id);

	  LB_elim_loop_backedges (fn, loop);
	}
    }

  Set_dispose (loop_done);
}
Set L_callgraph_query(CallGraph *callgraph, int func_id, int jsr_id)
{
    CG_Node		*node;
    CG_Arc		*arc;

    Set jsr_set=NULL;

    if (!callgraph)
	L_punt ("L_callgraph_query: null callgraph provided\n");

    for (node = callgraph->first_node; node!=NULL; node = node->next_node)
    {
	if (node->func_id == func_id)
	{
	    for (arc = node->first_dst_arc; arc != NULL; 
		 arc = arc->next_dst_arc)
	    {
		if (arc->jsr_id == jsr_id)
		    jsr_set = Set_add(jsr_set, arc->dst_node->func_id);
	    }
	    return jsr_set;
	}
    }

    /* If we reach this point, the function is unknown! */
    return NULL;
}
Beispiel #5
0
int main(int argc, char* argv[]) {
    Set s = Set_new();
    int   a = 42;
    char* b = "hello";
    assert(Set_size(s) == 0);
    Set_show(s, stdout, &show_func);
    Set_add(s, &a);
    assert(Set_size(s) == 1);
    Set_show(s, stdout, &show_func);
    Set_add(s, b);
    assert(Set_size(s) == 2);
    Set_show(s, stdout, &show_func);
    Set_remove(s, b);
    assert(Set_size(s) == 1);
    Set_show(s, stdout, &show_func);
    Set_remove(s, b);
    assert(Set_size(s) == 1);
    Set_show(s, stdout, &show_func);

    fprintf(stdout, "All tests passed!\n");
}
int
L_loadstore_union_postdominates_amb (L_Func * fn, L_Cb * cb, L_Oper * oper,
                                     Set LDST, Set AMB)
{
  int i, size;
  int *buf;
  L_Cb *def_cb;
  Set pd_cbset;
  int val = 0;

  pd_cbset = NULL;


  /* Convert RDEF is a set of cbs */
  size = Set_size (LDST);
  if (!size)
    return 0;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (LDST, buf);
  for (i = 0; i < size; i++)
    {
      def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      pd_cbset = Set_add (pd_cbset, def_cb->id);
    }
  Lcode_free (buf);


  /* Foreach cb in AMB, Does pd_cbset post_dominate it */
  size = Set_size (AMB);
  if (!size)
    return 1;

  buf = (int *) Lcode_malloc (sizeof (int) * size);
  Set_2array (AMB, buf);
  for (i = 0; i < size; i++)
    {
      def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]);

      val = L_cb_set_dominates (fn, def_cb, cb, pd_cbset);
      if (!val)
        break;
    }

  Lcode_free (buf);
  pd_cbset = Set_dispose (pd_cbset);

  return val;
}
Beispiel #7
0
static void
AddExtensionFields (FGraph graph)
{
  Node ptr;
  Arc arc;
  struct Ext *ext;
  int change;
  Set all;
  FreeExtensionFields ();
  if (graph->nodes == 0)
    return;
  if (graph->root == 0)
    Punt ("no root node");
  all = 0;
  for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr))
    {
      nodeExt (ptr) = (others + n_others);
      others[n_others].dominator = 0;
      others[n_others].level = -1;
      others[n_others].order = n_others;
      all = Set_add (all, n_others);
      n_others += 1;
    }
  ext = (struct Ext *) nodeExt (graph->root);
  ext->level = 0;
  ext->dominator = Set_add (0, ext->order);
  for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr))
    {
      if (ptr == graph->root)
        continue;
      ext = (struct Ext *) nodeExt (ptr);
      ext->dominator = Set_union (0, all);
    }
  /*
   *  compute dominators.
   */
  change = 1;
  while (change != 0)
    {
      change = 0;
      for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr))
        {
          Set dom, temp;
          if (ptr == graph->root)
            continue;
          arc = sourceArcs (ptr);
          if (arc == 0)
            {
              dom = 0;
            }
          else
            {
              dom = Set_union (all, 0);
              for (; arc != 0; arc = nextArc (arc))
                {
                  ext = (struct Ext *) nodeExt (sourceNode (arc));
                  temp = Set_intersect (dom, ext->dominator);
                  Set_dispose (dom);
                  dom = temp;
                  temp = 0;
                }
              ext = (struct Ext *) nodeExt (ptr);
              dom = Set_add (dom, ext->order);
              if (Set_same (dom, ext->dominator))
                {
                  Set_dispose (dom);
                }
              else
                {
                  Set_dispose (ext->dominator);
                  ext->dominator = dom;
                  change += 1;
                }
            }
        }
    }
  all = Set_dispose (all);
  /*
   *  compute level.
   */
  change = 1;
  while (change != 0)
    {
      change = 0;
      for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr))
        {
          int max;
          ext = (struct Ext *) nodeExt (ptr);
          if (ext->level >= 0)
            continue;
          max = -1;
          for (arc = sourceArcs (ptr); arc != 0; arc = arc->next)
            {
              Node src;
              struct Ext *ex;
              src = sourceNode (arc);
              ex = (struct Ext *) nodeExt (src);
              /* ignore back-edges */
              if (ex->order >= ext->order)
                continue;
              if (ex->level < 0)
                break;
              if (ex->level > max)
                max = ex->level;
            }
          if (arc == 0)
            {                   /* all source have been visited */
              ext->level = max + 1;
              change += 1;
            }
        }
    }
#ifdef DEBUG
  printf ("--------------------------------------------------\n");
  for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr))
    {
      ext = nodeExt (ptr);
      printf ("# id=%d, order=%d, level=%d, ",
              ptr->id, ext->order, ext->level);
      PrintSet (stdout, "dominator", ext->dominator);
    }
#endif
}
Beispiel #8
0
L_Loop *
LB_hb_do_collapse_loops (LB_TraceRegion_Header *trh,
			 L_Func * fn, L_Loop * loop)
{
  L_Loop *child_loop;
  L_Cb *par_hdr, *chi_hdr, *back_cb;
  L_Oper *new_op;
  LB_TraceRegion *child_tr;
  L_Flow *src_flow, *dst_flow, *nxt_flow;
  double back_wt;

  if (!(child_loop = loop->child_loop))
    return 0;
  if (child_loop->sibling_loop)
    return 0;

  par_hdr = loop->header;
  chi_hdr = child_loop->header;

  if (!(child_tr = LB_find_traceregion_by_header (trh, chi_hdr)))
    return 0;

  if (!par_hdr->dest_flow || par_hdr->dest_flow->dst_cb != chi_hdr)
    return 0;

  /*
   * Restructure control flow to move outer loop header into
   * inner loop tail
   */

  back_wt = par_hdr->weight - loop->num_invocation;
  par_hdr->weight = loop->num_invocation;

  back_cb = L_create_cb (par_hdr->weight);

  L_insert_cb_after (fn, fn->last_cb, back_cb);
  L_copy_block_contents (par_hdr, back_cb);
  back_cb->dest_flow = L_copy_flow (par_hdr->dest_flow);
  src_flow = L_find_matching_flow (chi_hdr->src_flow, back_cb->dest_flow);
  src_flow = L_copy_flow (src_flow);
  back_cb->dest_flow->weight = back_wt;
  src_flow->weight = back_wt;
  chi_hdr->src_flow = L_concat_flow (chi_hdr->src_flow, src_flow);
  src_flow->src_cb = back_cb;
  L_change_src (back_cb->dest_flow, par_hdr, back_cb);

  if (L_uncond_branch (back_cb->last_op))
    {
      L_delete_operand (back_cb->last_op->src[0]);
      back_cb->last_op->src[0] = L_new_cb_operand (chi_hdr);
    }
  else
    {
      new_op = L_create_new_op (Lop_JUMP);
      new_op->src[0] = L_new_cb_operand (chi_hdr);
      L_insert_oper_after (back_cb, back_cb->last_op, new_op);
    }

  {
    L_Cb *src_cb;
    L_Oper *op, *br;

    /* Change all loop body->header flows to the new header copy
     */

    for (src_flow = par_hdr->src_flow; src_flow; src_flow = nxt_flow)
      {
	nxt_flow = src_flow->next_flow;
	src_cb = src_flow->src_cb;
	if (Set_in (loop->back_edge_cb, src_cb->id) && (src_cb != par_hdr))
	  {
	    dst_flow = L_find_matching_flow (src_cb->dest_flow, src_flow);
	    br = L_find_branch_for_flow (src_cb, dst_flow);
	    if (br)
	      {
		L_change_branch_dest (br, par_hdr, back_cb);
	      }
	    else
	      {
		op = L_create_new_op (Lop_JUMP);
		op->src[0] = L_new_cb_operand (back_cb);
		L_insert_oper_after (src_cb, src_cb->last_op, op);
	      }
	    dst_flow->dst_cb = back_cb;
	    par_hdr->src_flow = L_remove_flow (par_hdr->src_flow, src_flow);
	    src_flow->dst_cb = back_cb;
	    back_cb->src_flow = L_concat_flow (back_cb->src_flow, src_flow);
	    loop->back_edge_cb = Set_delete (loop->back_edge_cb, src_cb->id);
	  }
      }
  }

  loop->header = child_loop->header;
  loop->loop_cb = Set_add (loop->loop_cb, back_cb->id);
  loop->loop_cb = Set_delete (loop->loop_cb, par_hdr->id);
  loop->back_edge_cb = Set_add (loop->back_edge_cb, back_cb->id);
  loop->nested_loops = Set_delete (loop->nested_loops, child_loop->id);
  loop->child_loop = NULL;
  L_merge_two_loops (fn, loop, child_loop);

  /*
   * Clear HB selection flags on child region's cbs, if not included in
   * other regions
   */

  {
    LB_TraceRegion *tr;
    L_Cb *cb_iter;
    Set uncov, test, chi;

    uncov = LB_return_cbs_region_as_set (child_tr);

    chi = Set_copy (uncov);

    List_start (trh->traceregions);

    while ((tr = (LB_TraceRegion *) List_next (trh->traceregions)))
      {
	if (tr == child_tr)
	  {
	    trh->traceregions = List_delete_current(trh->traceregions);
	    LB_free_traceregion (tr);
	  }
	else
	  {
	    test = LB_return_cbs_region_as_set (tr);
	    uncov = Set_subtract_acc (uncov, test);
	    Set_dispose (test);
	  }
      }

    for (cb_iter = fn->first_cb; cb_iter; cb_iter = cb_iter->next_cb)
      {
	if (Set_in(uncov, cb_iter->id))
	  cb_iter->flags = L_CLR_BIT_FLAG (cb_iter->flags,
					   L_CB_HYPERBLOCK_LOOP);
      }


    Set_dispose (uncov);
    Set_dispose (chi);
  }

  return loop;
}
Beispiel #9
0
void
LB_elim_loop_backedges (L_Func * fn, L_Loop * loop)
{
  L_Cb *loop_header_cb = loop->header, *loop_end_cb, *cb;
  L_Flow *src_flow, *dst_flow, *back_edge_flow, *header_src_flow;
  L_Oper *oper, *branch;
  int num_back_edges, *back_edge_cb, i;

  /* We will only modify loops with more than one back edge */
  if ((num_back_edges = Set_size (loop->back_edge_cb)) <= 1)
    return;

#ifdef DEBUG
  fprintf (stderr, "Loop %d has %d backedges\n", loop->id, num_back_edges);
  Set_print (stderr, "backedges", loop->back_edge_cb);
#endif

  if (LB_functionally_equivalent_cbs (loop->back_edge_cb) &&
      !Set_in (loop->back_edge_cb, loop->header->id))
    {
#ifdef DEBUG
      fprintf (stderr, "Loop backedge cbs are equivalent!!\n");
#endif
      LB_combine_equivalent_backedges (loop);
      return;
    }

#ifdef DEBUG
  fprintf (stderr, "Loop backedge cbs are NOT equivalent!!\n");
#endif

  /* Create a cb with a back-edge to the loop header cb. */
  loop_end_cb = L_create_cb (0.0);
  header_src_flow = L_new_flow (1, loop_end_cb, loop_header_cb, 0.0);
  loop_header_cb->src_flow =
    L_concat_flow (loop_header_cb->src_flow, header_src_flow);
  back_edge_flow = L_new_flow (1, loop_end_cb, loop_header_cb, 0.0);
  loop_end_cb->dest_flow =
    L_concat_flow (loop_end_cb->dest_flow, back_edge_flow);
  L_insert_cb_after (fn, fn->last_cb, loop_end_cb);

  /* Create the jump instruction that leads to the header cb */
  oper = L_create_new_op (Lop_JUMP);
  oper->src[0] = L_new_cb_operand (loop_header_cb);
  L_insert_oper_after (loop_end_cb, loop_end_cb->first_op, oper);
#ifdef DEBUG
  fprintf (stderr, "created cb %d, placed it after cb %d\n",
	   loop_end_cb->id, loop_end_cb->prev_cb->id);
#endif

  /* 
   * Loop through all loop back-edge cbs and make them branch to the
   * to the new end loop cb.
   */

  back_edge_cb = (int *) Lcode_malloc (sizeof (int) * num_back_edges);
  Set_2array (loop->back_edge_cb, back_edge_cb);

  for (i = 0; i < num_back_edges; i++)
    {
      cb = L_cb_hash_tbl_find (fn->cb_hash_tbl, back_edge_cb[i]);

      /* 
       * Find the destination flow arc in the current cb corresponding to the 
       * loop back edge.
       */
      for (dst_flow = cb->dest_flow; dst_flow; dst_flow = dst_flow->next_flow)
	{
	  if (dst_flow->dst_cb != loop_header_cb)
	    continue;

	  /*
	   * Find the src flow arc in the loop header cb corresponding to the
	   * current back edge and delete it.
	   */
	  src_flow = L_find_flow (loop_header_cb->src_flow, dst_flow->cc,
				  dst_flow->src_cb, dst_flow->dst_cb);
	  loop_header_cb->src_flow = L_delete_flow (loop_header_cb->src_flow,
						    src_flow);

	  /* Modify the flow arc and branch target for the branch */
	  branch = L_find_branch_for_flow (cb, dst_flow);

#ifdef DEBUG
	  fprintf (stderr, "\t (cb %d) branch oper %d\n", cb->id, branch->id);
	  fprintf (stderr, "\t");
	  L_print_oper (stderr, branch);
#endif
	  if (branch)
	    {
	      L_change_branch_dest (branch, dst_flow->dst_cb, loop_end_cb);
	    }
	  else
	    {
	      L_Oper *new_op;
	      new_op = L_create_new_op (Lop_JUMP);
	      new_op->src[0] = L_new_cb_operand (loop_end_cb);
	      L_insert_oper_after (cb, cb->last_op, new_op);
	    }

	  dst_flow->dst_cb = loop_end_cb;

	  src_flow =
	    L_new_flow (dst_flow->cc, dst_flow->src_cb, dst_flow->dst_cb,
			dst_flow->weight);
	  loop_end_cb->src_flow =
	    L_concat_flow (loop_end_cb->src_flow, src_flow);
	  loop_end_cb->weight += src_flow->weight;

	  back_edge_flow->weight += src_flow->weight;
	  header_src_flow->weight += src_flow->weight;
	}
    }

  /* Add the new back-edge cb to the back edge cb list for the loop */
  loop->back_edge_cb = Set_dispose (loop->back_edge_cb);
  loop->back_edge_cb = Set_add (loop->back_edge_cb, loop_end_cb->id);
  loop->loop_cb = Set_add (loop->loop_cb, loop_end_cb->id);

  /* free up space */
  Lcode_free (back_edge_cb);

}
Beispiel #10
0
void CommandPool_add( CommandPool* self, Command* aCommand )
{
	Set_add( self->commands, aCommand );
}
Beispiel #11
0
/*! \brief Finds the natural loop corresponding to a back edge
 *
 * \param cfg
 *  control flow graph for the func being processed
 * \param be
 *  back edge going to the head of this particular natural loop
 *
 *  *** CURRENTLY NOT IN USE ***
 *
 * \return void
 */
void
PC_FindNaturalLoop (PC_Graph cfg, PC_Flow be)
{
  PC_Loop *loop = NULL;
  PC_Block bb = NULL;
  PC_Flow fl = NULL;
  Stack *st = New_Stack ();
  int lp_head = be->dest_bb->ID, lp_size = 0, i;
  int *lp_bod;
  Set lp = Set_new (), lp_exits = Set_new ();
  int num_back_edge = 0;
  int num_exit = 0;

  if (be->src_bb->ID == be->dest_bb->ID)
    P_warn ("PC_FindNaturalLoop: head and tail of back edge are same.");


  /* Build the set of all bbs in the lp body. */
  lp = Set_add (lp, lp_head);

  if (!Set_in (lp, be->src_bb->ID))
    {
      lp = Set_add (lp, be->src_bb->ID);
      Push_Top (st, be->src_bb);
    }

  while ((bb = Pop (st)) != ((void*)-1))
    {
      for (fl = bb->p_flow; fl; fl = fl->p_next_flow)
	{
	  if (!Set_in (lp, fl->src_bb->ID))
	    {
	      lp = Set_add (lp, fl->src_bb->ID);
	      Push_Top (st, fl->src_bb);
	    }
	}
    }


  /* Build the set of all bbs that are exits out of the lp. */
  lp_bod = (int *) calloc (Set_size (lp), sizeof (int));
  lp_size = Set_2array (lp, lp_bod);
  for (i = 0; i < lp_size; i++)
    {
      bb = PC_FindBlock (cfg, lp_bod[i]);
      for (fl = bb->s_flow; fl; fl = fl->s_next_flow)
	if (!Set_in (lp, fl->dest_bb->ID)) {
	  lp_exits = Set_add (lp_exits, fl->dest_bb->ID);
          num_exit++;
        }
    }
  free (lp_bod);

  /* Append this loop to the list of loops in the PC_Graph. */
  loop = &cfg->lp;
  while (*loop)
    {
      loop = &(*loop)->next;
    }
  *loop = PC_NewLoop (lp_head, lp, lp_exits, num_back_edge, num_exit);

  Set_dispose (lp);
  Set_dispose (lp_exits);
}
Beispiel #12
0
/*! \brief Finds loops in the CFG. Builds lp hdr, body and exit bb sets, and 
 *   puts this lp info in a PC_Loop struct, which is appended to the CFG lp list.
 *
 * \param cfg
 *  control flow graph for the func being processed
 *
 *  Multiple back edges coming into the same loop header are considered as one
 *  loop. The loop body is a union of the bodies of the loops corresponding to 
 *  each one of these back edges. 
 *
 * \return void
 */
void
PC_FindLoops (PC_Graph cfg)
{
  PC_Block h_bb;

  /* build dominator sets for each bb in the cfg */
  PC_BuildDomSets (cfg);

  /* check each cfg bb in turn to see if it's a lp header bb */
  for (h_bb = cfg->first_bb; h_bb; h_bb = h_bb->next)
    {
      PC_Flow be;
      PC_Loop *loop;
      int num_back_edge;
      int num_exit;
      int s_lp_head = -1;
      Set s_lp_body = Set_new (), s_lp_exits = Set_new ();

      /* check all edges coming into h_bb to see if they are back edges */
      num_back_edge = 0;
      for (be = h_bb->p_flow; be; be = be->p_next_flow)
	{
	  /* check to see if be is indeed a back edge */
	  if (PC_BB1DominatesBB2 (be->dest_bb, be->src_bb))
	    {
	      PC_Block bb;
	      Stack *st = New_Stack ();
	      Set lp_body = Set_new ();

              num_back_edge++;
	      s_lp_head = be->dest_bb->ID;

	      if (be->src_bb->ID == be->dest_bb->ID)
		P_warn
		  ("PC_FindNaturalLoop: back edge head & tail are same.");


	      /* Build the set of all bbs in the lp body. */
	      lp_body = Set_add (lp_body, s_lp_head);

	      if (!Set_in (lp_body, be->src_bb->ID))
		{
		  lp_body = Set_add (lp_body, be->src_bb->ID);
		  Push_Top (st, be->src_bb);
		}

	      while ((bb = Pop (st)) != ((void*)-1))
		{
		  PC_Flow fl;
		  for (fl = bb->p_flow; fl; fl = fl->p_next_flow)
		    {
		      if (!Set_in (lp_body, fl->src_bb->ID))
			{
			  lp_body = Set_add (lp_body, fl->src_bb->ID);
			  Push_Top (st, fl->src_bb);
			}
		    }
		}


	      /* the s_lp body is a union of all of these 'inner' lp bodies */
	      s_lp_body = Set_union (s_lp_body, lp_body);

	      Clear_Stack (st);
	      Set_dispose (lp_body);
	    }
	}

      /* If a loop was found, build its set of exits bbs, and append it to the 
         list of loops in the cfg. */
      if (s_lp_head != -1)
	{
	  int *s_lp_bod;
	  int lp_size = 0, i;

	  /* Build the set of all bbs that are exits out of the lp. */
	  s_lp_bod = (int *) calloc (Set_size (s_lp_body), sizeof (int));
	  lp_size = Set_2array (s_lp_body, s_lp_bod);
          num_exit = 0;
	  for (i = 0; i < lp_size; i++)
	    {
	      PC_Block bb;
	      PC_Flow fl;
	      bb = PC_FindBlock (cfg, s_lp_bod[i]);
	      for (fl = bb->s_flow; fl; fl = fl->s_next_flow)
		if (!Set_in (s_lp_body, fl->dest_bb->ID)) 
                  {
                    num_exit++;
                    s_lp_exits = Set_add (s_lp_exits, fl->dest_bb->ID);
                  }
	    }
	  free (s_lp_bod);

	  /* check for redundant loops */
	    {
	      PC_Loop lp = NULL;
	      int same = 0;
	      
	      for (lp = cfg->lp; lp; lp = lp->next)
		if (Set_same (s_lp_body, lp->body))
		  {
		    same = 1;
		    break;
		  }
	      
	      if (same)
		{
		  Set_dispose (s_lp_body);
		  Set_dispose (s_lp_exits);
		  continue;
		}
	    }

	  /* Create a new PC_Loop and append it to the current CFG
             loop list. */
	  loop = &cfg->lp;
	  while (*loop)
	    loop = &(*loop)->next;
	  *loop = PC_NewLoop (s_lp_head, s_lp_body, s_lp_exits, 
			      num_back_edge, num_exit);

	  cfg->lp_tree = PC_LoopTreeInsert (cfg->lp_tree, *loop, 1);
	}

      Set_dispose (s_lp_body);
      Set_dispose (s_lp_exits);
    }

  PC_SetBlockLoops (cfg);

  return;
}