Пример #1
0
/* Splits superblocks.  */
static void
break_superblocks (void)
{
  sbitmap superblocks;
  int i, need;

  superblocks = sbitmap_alloc (n_basic_blocks);
  sbitmap_zero (superblocks);

  need = 0;

  for (i = 0; i < n_basic_blocks; i++)
    if (BASIC_BLOCK(i)->flags & BB_SUPERBLOCK)
      {
	BASIC_BLOCK(i)->flags &= ~BB_SUPERBLOCK;
	SET_BIT (superblocks, i);
	need = 1;
      }

  if (need)
    {
      rebuild_jump_labels (get_insns ());
      find_many_sub_basic_blocks (superblocks);
    }

  free (superblocks);
}
Пример #2
0
/* Splits superblocks.  */
void
break_superblocks (void)
{
  sbitmap superblocks;
  bool need = false;
  basic_block bb;

  superblocks = sbitmap_alloc (last_basic_block);
  sbitmap_zero (superblocks);

  FOR_EACH_BB (bb)
    if (bb->flags & BB_SUPERBLOCK)
      {
	bb->flags &= ~BB_SUPERBLOCK;
	SET_BIT (superblocks, bb->index);
	need = true;
      }

  if (need)
    {
      rebuild_jump_labels (get_insns ());
      find_many_sub_basic_blocks (superblocks);
    }

  free (superblocks);
}
static bool
reachable_at_most_once (basic_block va_arg_bb, basic_block va_start_bb)
{
  VEC (edge, heap) *stack = NULL;
  edge e;
  edge_iterator ei;
  sbitmap visited;
  bool ret;

  if (va_arg_bb == va_start_bb)
    return true;

  if (! dominated_by_p (CDI_DOMINATORS, va_arg_bb, va_start_bb))
    return false;

  visited = sbitmap_alloc (last_basic_block);
  sbitmap_zero (visited);
  ret = true;

  FOR_EACH_EDGE (e, ei, va_arg_bb->preds)
    VEC_safe_push (edge, heap, stack, e);

  while (! VEC_empty (edge, stack))
    {
      basic_block src;

      e = VEC_pop (edge, stack);
      src = e->src;

      if (e->flags & EDGE_COMPLEX)
	{
	  ret = false;
	  break;
	}

      if (src == va_start_bb)
	continue;

      /* va_arg_bb can be executed more times than va_start_bb.  */
      if (src == va_arg_bb)
	{
	  ret = false;
	  break;
	}

      gcc_assert (src != ENTRY_BLOCK_PTR);

      if (! TEST_BIT (visited, src->index))
	{
	  SET_BIT (visited, src->index);
	  FOR_EACH_EDGE (e, ei, src->preds)
	    VEC_safe_push (edge, heap, stack, e);
	}
    }

  VEC_free (edge, heap, stack);
  sbitmap_free (visited);
  return ret;
}
basic_block *
blocks_in_phiopt_order (void)
{
    basic_block x, y;
    basic_block *order = XNEWVEC (basic_block, n_basic_blocks);
    unsigned n = n_basic_blocks - NUM_FIXED_BLOCKS;
    unsigned np, i;
    sbitmap visited = sbitmap_alloc (last_basic_block);

#define MARK_VISITED(BB) (SET_BIT (visited, (BB)->index))
#define VISITED_P(BB) (TEST_BIT (visited, (BB)->index))

    sbitmap_zero (visited);

    MARK_VISITED (ENTRY_BLOCK_PTR);
    FOR_EACH_BB (x)
    {
        if (VISITED_P (x))
            continue;

        /* Walk the predecessors of x as long as they have precisely one
        predecessor and add them to the list, so that they get stored
         after x.  */
        for (y = x, np = 1;
                single_pred_p (y) && !VISITED_P (single_pred (y));
                y = single_pred (y))
            np++;
        for (y = x, i = n - np;
                single_pred_p (y) && !VISITED_P (single_pred (y));
                y = single_pred (y), i++)
        {
            order[i] = y;
            MARK_VISITED (y);
        }
        order[i] = y;
        MARK_VISITED (y);

        gcc_assert (i == n - 1);
        n -= np;
    }

    sbitmap_free (visited);
    gcc_assert (n == 0);
    return order;

#undef MARK_VISITED
#undef VISITED_P
}
Пример #5
0
static void
dump_copy_of (FILE *file, tree var)
{
  tree val;
  sbitmap visited;

  print_generic_expr (file, var, dump_flags);

  if (TREE_CODE (var) != SSA_NAME)
    return;
    
  visited = sbitmap_alloc (num_ssa_names);
  sbitmap_zero (visited);
  SET_BIT (visited, SSA_NAME_VERSION (var));
  
  fprintf (file, " copy-of chain: ");

  val = var;
  print_generic_expr (file, val, 0);
  fprintf (file, " ");
  while (copy_of[SSA_NAME_VERSION (val)].value)
    {
      fprintf (file, "-> ");
      val = copy_of[SSA_NAME_VERSION (val)].value;
      print_generic_expr (file, val, 0);
      fprintf (file, " ");
      if (TEST_BIT (visited, SSA_NAME_VERSION (val)))
        break;
      SET_BIT (visited, SSA_NAME_VERSION (val));
    }

  val = get_copy_of_val (var)->value;
  if (val == NULL_TREE)
    fprintf (file, "[UNDEFINED]");
  else if (val != var)
    fprintf (file, "[COPY]");
  else
    fprintf (file, "[NOT A COPY]");
  
  sbitmap_free (visited);
}
Пример #6
0
static void
compute_farthest (struct edge_list *edge_list, int n_exprs,
		  sbitmap *st_avout, sbitmap *st_avin, sbitmap *st_antin,
		  sbitmap *kill, sbitmap *farthest)
{
  sbitmap difference, temp_bitmap;
  int x, num_edges;
  basic_block pred, succ;

  num_edges = NUM_EDGES (edge_list);

  difference = sbitmap_alloc (n_exprs);
  temp_bitmap = sbitmap_alloc (n_exprs);

  for (x = 0; x < num_edges; x++)
    {
      pred = INDEX_EDGE_PRED_BB (edge_list, x);
      succ = INDEX_EDGE_SUCC_BB (edge_list, x);
      if (succ == EXIT_BLOCK_PTR)
	sbitmap_copy (farthest[x], st_avout[pred->index]);
      else
	{
	  if (pred == ENTRY_BLOCK_PTR)
	    sbitmap_zero (farthest[x]);
	  else
	    {
	      sbitmap_difference (difference, st_avout[pred->index],
				  st_antin[succ->index]);
	      sbitmap_not (temp_bitmap, st_avin[succ->index]);
	      sbitmap_a_and_b_or_c (farthest[x], difference,
				    kill[succ->index], temp_bitmap);
	    }
	}
    }

  sbitmap_free (temp_bitmap);
  sbitmap_free (difference);
}
Пример #7
0
static void
compute_antinout_edge (sbitmap *antloc, sbitmap *transp, sbitmap *antin,
		       sbitmap *antout)
{
  basic_block bb;
  edge e;
  basic_block *worklist, *qin, *qout, *qend;
  unsigned int qlen;
  edge_iterator ei;

  /* Allocate a worklist array/queue.  Entries are only added to the
     list if they were not already on the list.  So the size is
     bounded by the number of basic blocks.  */
  qin = qout = worklist = XNEWVEC (basic_block, n_basic_blocks);

  /* We want a maximal solution, so make an optimistic initialization of
     ANTIN.  */
  sbitmap_vector_ones (antin, last_basic_block);

  /* Put every block on the worklist; this is necessary because of the
     optimistic initialization of ANTIN above.  */
  FOR_EACH_BB_REVERSE (bb)
    {
      *qin++ = bb;
      bb->aux = bb;
    }

  qin = worklist;
  qend = &worklist[n_basic_blocks - NUM_FIXED_BLOCKS];
  qlen = n_basic_blocks - NUM_FIXED_BLOCKS;

  /* Mark blocks which are predecessors of the exit block so that we
     can easily identify them below.  */
  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
    e->src->aux = EXIT_BLOCK_PTR;

  /* Iterate until the worklist is empty.  */
  while (qlen)
    {
      /* Take the first entry off the worklist.  */
      bb = *qout++;
      qlen--;

      if (qout >= qend)
	qout = worklist;

      if (bb->aux == EXIT_BLOCK_PTR)
	/* Do not clear the aux field for blocks which are predecessors of
	   the EXIT block.  That way we never add then to the worklist
	   again.  */
	sbitmap_zero (antout[bb->index]);
      else
	{
	  /* Clear the aux field of this block so that it can be added to
	     the worklist again if necessary.  */
	  bb->aux = NULL;
	  sbitmap_intersection_of_succs (antout[bb->index], antin, bb->index);
	}

      if (sbitmap_a_or_b_and_c_cg (antin[bb->index], antloc[bb->index],
				   transp[bb->index], antout[bb->index]))
	/* If the in state of this block changed, then we need
	   to add the predecessors of this block to the worklist
	   if they are not already on the worklist.  */
	FOR_EACH_EDGE (e, ei, bb->preds)
	  if (!e->src->aux && e->src != ENTRY_BLOCK_PTR)
	    {
	      *qin++ = e->src;
	      e->src->aux = e;
	      qlen++;
	      if (qin >= qend)
		qin = worklist;
	    }
    }

  clear_aux_for_edges ();
  clear_aux_for_blocks ();
  free (worklist);
}
Пример #8
0
void
compute_available (sbitmap *avloc, sbitmap *kill, sbitmap *avout,
		   sbitmap *avin)
{
  edge e;
  basic_block *worklist, *qin, *qout, *qend, bb;
  unsigned int qlen;
  edge_iterator ei;

  /* Allocate a worklist array/queue.  Entries are only added to the
     list if they were not already on the list.  So the size is
     bounded by the number of basic blocks.  */
  qin = qout = worklist =
    XNEWVEC (basic_block, n_basic_blocks - NUM_FIXED_BLOCKS);

  /* We want a maximal solution.  */
  sbitmap_vector_ones (avout, last_basic_block);

  /* Put every block on the worklist; this is necessary because of the
     optimistic initialization of AVOUT above.  */
  FOR_EACH_BB (bb)
    {
      *qin++ = bb;
      bb->aux = bb;
    }

  qin = worklist;
  qend = &worklist[n_basic_blocks - NUM_FIXED_BLOCKS];
  qlen = n_basic_blocks - NUM_FIXED_BLOCKS;

  /* Mark blocks which are successors of the entry block so that we
     can easily identify them below.  */
  FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
    e->dest->aux = ENTRY_BLOCK_PTR;

  /* Iterate until the worklist is empty.  */
  while (qlen)
    {
      /* Take the first entry off the worklist.  */
      bb = *qout++;
      qlen--;

      if (qout >= qend)
	qout = worklist;

      /* If one of the predecessor blocks is the ENTRY block, then the
	 intersection of avouts is the null set.  We can identify such blocks
	 by the special value in the AUX field in the block structure.  */
      if (bb->aux == ENTRY_BLOCK_PTR)
	/* Do not clear the aux field for blocks which are successors of the
	   ENTRY block.  That way we never add then to the worklist again.  */
	sbitmap_zero (avin[bb->index]);
      else
	{
	  /* Clear the aux field of this block so that it can be added to
	     the worklist again if necessary.  */
	  bb->aux = NULL;
	  sbitmap_intersection_of_preds (avin[bb->index], avout, bb->index);
	}

      if (sbitmap_union_of_diff_cg (avout[bb->index], avloc[bb->index],
				    avin[bb->index], kill[bb->index]))
	/* If the out state of this block changed, then we need
	   to add the successors of this block to the worklist
	   if they are not already on the worklist.  */
	FOR_EACH_EDGE (e, ei, bb->succs)
	  if (!e->dest->aux && e->dest != EXIT_BLOCK_PTR)
	    {
	      *qin++ = e->dest;
	      e->dest->aux = e;
	      qlen++;

	      if (qin >= qend)
		qin = worklist;
	    }
    }

  clear_aux_for_edges ();
  clear_aux_for_blocks ();
  free (worklist);
}
Пример #9
0
int
flow_loops_find (struct loops *loops, int flags)
{
  int i;
  int b;
  int num_loops;
  edge e;
  sbitmap headers;
  int *dfs_order;
  int *rc_order;
  basic_block header;
  basic_block bb;

  /* This function cannot be repeatedly called with different
     flags to build up the loop information.  The loop tree
     must always be built if this function is called.  */
  if (! (flags & LOOP_TREE))
    abort ();

  memset (loops, 0, sizeof *loops);

  /* Taking care of this degenerate case makes the rest of
     this code simpler.  */
  if (n_basic_blocks == 0)
    return 0;

  dfs_order = NULL;
  rc_order = NULL;

  /* Join loops with shared headers.  */
  canonicalize_loop_headers ();

  /* Compute the dominators.  */
  calculate_dominance_info (CDI_DOMINATORS);

  /* Count the number of loop headers.  This should be the
     same as the number of natural loops.  */
  headers = sbitmap_alloc (last_basic_block);
  sbitmap_zero (headers);

  num_loops = 0;
  FOR_EACH_BB (header)
    {
      int more_latches = 0;

      header->loop_depth = 0;

      /* If we have an abnormal predecessor, do not consider the
	 loop (not worth the problems).  */
      for (e = header->pred; e; e = e->pred_next)
	if (e->flags & EDGE_ABNORMAL)
	  break;
      if (e)
	continue;

      for (e = header->pred; e; e = e->pred_next)
	{
	  basic_block latch = e->src;

	  if (e->flags & EDGE_ABNORMAL)
	    abort ();

	  /* Look for back edges where a predecessor is dominated
	     by this block.  A natural loop has a single entry
	     node (header) that dominates all the nodes in the
	     loop.  It also has single back edge to the header
	     from a latch node.  */
	  if (latch != ENTRY_BLOCK_PTR
	      && dominated_by_p (CDI_DOMINATORS, latch, header))
	    {
	      /* Shared headers should be eliminated by now.  */
	      if (more_latches)
		abort ();
	      more_latches = 1;
	      SET_BIT (headers, header->index);
	      num_loops++;
	    }
	}
    }

  /* Allocate loop structures.  */
  loops->parray = xcalloc (num_loops + 1, sizeof (struct loop *));

  /* Dummy loop containing whole function.  */
  loops->parray[0] = xcalloc (1, sizeof (struct loop));
  loops->parray[0]->next = NULL;
  loops->parray[0]->inner = NULL;
  loops->parray[0]->outer = NULL;
  loops->parray[0]->depth = 0;
  loops->parray[0]->pred = NULL;
  loops->parray[0]->num_nodes = n_basic_blocks + 2;
  loops->parray[0]->latch = EXIT_BLOCK_PTR;
  loops->parray[0]->header = ENTRY_BLOCK_PTR;
  ENTRY_BLOCK_PTR->loop_father = loops->parray[0];
  EXIT_BLOCK_PTR->loop_father = loops->parray[0];

  loops->tree_root = loops->parray[0];

  /* Find and record information about all the natural loops
     in the CFG.  */
  loops->num = 1;
  FOR_EACH_BB (bb)
    bb->loop_father = loops->tree_root;

  if (num_loops)
    {
      /* Compute depth first search order of the CFG so that outer
	 natural loops will be found before inner natural loops.  */
      dfs_order = xmalloc (n_basic_blocks * sizeof (int));
      rc_order = xmalloc (n_basic_blocks * sizeof (int));
      flow_depth_first_order_compute (dfs_order, rc_order);

      /* Save CFG derived information to avoid recomputing it.  */
      loops->cfg.dfs_order = dfs_order;
      loops->cfg.rc_order = rc_order;

      num_loops = 1;

      for (b = 0; b < n_basic_blocks; b++)
	{
	  struct loop *loop;

	  /* Search the nodes of the CFG in reverse completion order
	     so that we can find outer loops first.  */
	  if (!TEST_BIT (headers, rc_order[b]))
	    continue;

	  header = BASIC_BLOCK (rc_order[b]);

	  loop = loops->parray[num_loops] = xcalloc (1, sizeof (struct loop));

	  loop->header = header;
	  loop->num = num_loops;
	  num_loops++;

	  /* Look for the latch for this header block.  */
	  for (e = header->pred; e; e = e->pred_next)
	    {
	      basic_block latch = e->src;

	      if (latch != ENTRY_BLOCK_PTR
		  && dominated_by_p (CDI_DOMINATORS, latch, header))
		{
		  loop->latch = latch;
		  break;
		}
	    }

	  flow_loop_tree_node_add (header->loop_father, loop);
	  loop->num_nodes = flow_loop_nodes_find (loop->header, loop);
	}

      /* Assign the loop nesting depth and enclosed loop level for each
	 loop.  */
      loops->levels = flow_loops_level_compute (loops);

      /* Scan the loops.  */
      for (i = 1; i < num_loops; i++)
	flow_loop_scan (loops->parray[i], flags);

      loops->num = num_loops;
    }
  else
    {
      free_dominance_info (CDI_DOMINATORS);
    }

  sbitmap_free (headers);

  loops->state = 0;
#ifdef ENABLE_CHECKING
  verify_flow_info ();
  verify_loop_structure (loops);
#endif

  return loops->num;
}
static void
tail_duplicate (void)
{
  fibnode_t *blocks = XCNEWVEC (fibnode_t, last_basic_block);
  basic_block *trace = XNEWVEC (basic_block, n_basic_blocks);
  int *counts = XNEWVEC (int, last_basic_block);
  int ninsns = 0, nduplicated = 0;
  gcov_type weighted_insns = 0, traced_insns = 0;
  fibheap_t heap = fibheap_new ();
  gcov_type cover_insns;
  int max_dup_insns;
  basic_block bb;

  /* Create an oversized sbitmap to reduce the chance that we need to
     resize it.  */
  bb_seen = sbitmap_alloc (last_basic_block * 2);
  sbitmap_zero (bb_seen);
  initialize_original_copy_tables ();

  if (profile_info && flag_branch_probabilities)
    probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
  else
    probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
  probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;

  branch_ratio_cutoff =
    (REG_BR_PROB_BASE / 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO));

  FOR_EACH_BB (bb)
    {
      int n = count_insns (bb);
      if (!ignore_bb_p (bb))
	blocks[bb->index] = fibheap_insert (heap, -bb->frequency,
					    bb);

      counts [bb->index] = n;
      ninsns += n;
      weighted_insns += n * bb->frequency;
    }

  if (profile_info && flag_branch_probabilities)
    cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
  else
    cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
  cover_insns = (weighted_insns * cover_insns + 50) / 100;
  max_dup_insns = (ninsns * PARAM_VALUE (TRACER_MAX_CODE_GROWTH) + 50) / 100;

  while (traced_insns < cover_insns && nduplicated < max_dup_insns
         && !fibheap_empty (heap))
    {
      basic_block bb = (basic_block) fibheap_extract_min (heap);
      int n, pos;

      if (!bb)
	break;

      blocks[bb->index] = NULL;

      if (ignore_bb_p (bb))
	continue;
      gcc_assert (!bb_seen_p (bb));

      n = find_trace (bb, trace);

      bb = trace[0];
      traced_insns += bb->frequency * counts [bb->index];
      if (blocks[bb->index])
	{
	  fibheap_delete_node (heap, blocks[bb->index]);
	  blocks[bb->index] = NULL;
	}

      for (pos = 1; pos < n; pos++)
	{
	  basic_block bb2 = trace[pos];

	  if (blocks[bb2->index])
	    {
	      fibheap_delete_node (heap, blocks[bb2->index]);
	      blocks[bb2->index] = NULL;
	    }
	  traced_insns += bb2->frequency * counts [bb2->index];
	  if (EDGE_COUNT (bb2->preds) > 1
	      && can_duplicate_block_p (bb2))
	    {
	      edge e;
	      basic_block copy;

	      nduplicated += counts [bb2->index];

	      e = find_edge (bb, bb2);

	      copy = duplicate_block (bb2, e, bb);
	      flush_pending_stmts (e);

	      add_phi_args_after_copy (&copy, 1, NULL);

	      /* Reconsider the original copy of block we've duplicated.
	         Removing the most common predecessor may make it to be
	         head.  */
	      blocks[bb2->index] =
		fibheap_insert (heap, -bb2->frequency, bb2);

	      if (dump_file)
		fprintf (dump_file, "Duplicated %i as %i [%i]\n",
			 bb2->index, copy->index, copy->frequency);

	      bb2 = copy;
	    }
	  mark_bb_seen (bb2);
	  bb = bb2;
	  /* In case the trace became infrequent, stop duplicating.  */
	  if (ignore_bb_p (bb))
	    break;
	}
      if (dump_file)
	fprintf (dump_file, " covered now %.1f\n\n",
		 traced_insns * 100.0 / weighted_insns);
    }
  if (dump_file)
    fprintf (dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
	     nduplicated * 100 / ninsns);

  free_original_copy_tables ();
  sbitmap_free (bb_seen);
  free (blocks);
  free (trace);
  free (counts);
  fibheap_delete (heap);
}
Пример #11
0
static struct loop *
unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
               rtx cond, rtx cinsn)
{
    edge entry, latch_edge, true_edge, false_edge, e;
    basic_block switch_bb, unswitch_on_alt;
    struct loop *nloop;
    sbitmap zero_bitmap;
    int irred_flag, prob;
    rtx seq;

    /* Some sanity checking.  */
    gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
    gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
    gcc_assert (just_once_each_iteration_p (loop, unswitch_on));
    gcc_assert (!loop->inner);
    gcc_assert (flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 0)->dest));
    gcc_assert (flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 1)->dest));

    entry = loop_preheader_edge (loop);

    /* Make a copy.  */
    irred_flag = entry->flags & EDGE_IRREDUCIBLE_LOOP;
    entry->flags &= ~EDGE_IRREDUCIBLE_LOOP;
    zero_bitmap = sbitmap_alloc (2);
    sbitmap_zero (zero_bitmap);
    if (!duplicate_loop_to_header_edge (loop, entry, loops, 1,
                                        zero_bitmap, NULL, NULL, NULL, 0))
    {
        sbitmap_free (zero_bitmap);
        return NULL;
    }
    sbitmap_free (zero_bitmap);
    entry->flags |= irred_flag;

    /* Record the block with condition we unswitch on.  */
    unswitch_on_alt = get_bb_copy (unswitch_on);
    true_edge = BRANCH_EDGE (unswitch_on_alt);
    false_edge = FALLTHRU_EDGE (unswitch_on);
    latch_edge = single_succ_edge (get_bb_copy (loop->latch));

    /* Create a block with the condition.  */
    prob = true_edge->probability;
    switch_bb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
    seq = compare_and_jump_seq (XEXP (cond, 0), XEXP (cond, 1), GET_CODE (cond),
                                block_label (true_edge->dest),
                                prob, cinsn);
    emit_insn_after (seq, BB_END (switch_bb));
    e = make_edge (switch_bb, true_edge->dest, 0);
    e->probability = prob;
    e->count = latch_edge->count * prob / REG_BR_PROB_BASE;
    e = make_edge (switch_bb, FALLTHRU_EDGE (unswitch_on)->dest, EDGE_FALLTHRU);
    e->probability = false_edge->probability;
    e->count = latch_edge->count * (false_edge->probability) / REG_BR_PROB_BASE;

    if (irred_flag)
    {
        switch_bb->flags |= BB_IRREDUCIBLE_LOOP;
        EDGE_SUCC (switch_bb, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
        EDGE_SUCC (switch_bb, 1)->flags |= EDGE_IRREDUCIBLE_LOOP;
    }
    else
    {
        switch_bb->flags &= ~BB_IRREDUCIBLE_LOOP;
        EDGE_SUCC (switch_bb, 0)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
        EDGE_SUCC (switch_bb, 1)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
    }

    /* Loopify from the copy of LOOP body, constructing the new loop.  */
    nloop = loopify (loops, latch_edge,
                     single_pred_edge (get_bb_copy (loop->header)), switch_bb,
                     BRANCH_EDGE (switch_bb), FALLTHRU_EDGE (switch_bb), true);

    /* Remove branches that are now unreachable in new loops.  */
    remove_path (loops, true_edge);
    remove_path (loops, false_edge);

    /* One of created loops do not have to be subloop of the outer loop now,
       so fix its placement in loop data structure.  */
    fix_loop_placement (loop);
    fix_loop_placement (nloop);

    /* Preserve the simple loop preheaders.  */
    loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
    loop_split_edge_with (loop_preheader_edge (nloop), NULL_RTX);

    return nloop;
}
Пример #12
0
static unsigned int
copyprop_hardreg_forward (void)
{
  struct value_data *all_vd;
  basic_block bb;
  sbitmap visited;
  bool analyze_called = false;

  all_vd = XNEWVEC (struct value_data, last_basic_block);

  visited = sbitmap_alloc (last_basic_block);
  sbitmap_zero (visited);

  if (MAY_HAVE_DEBUG_INSNS)
    debug_insn_changes_pool
      = create_alloc_pool ("debug insn changes pool",
			   sizeof (struct queued_debug_insn_change), 256);

  FOR_EACH_BB (bb)
    {
      SET_BIT (visited, bb->index);

      /* If a block has a single predecessor, that we've already
	 processed, begin with the value data that was live at
	 the end of the predecessor block.  */
      /* ??? Ought to use more intelligent queuing of blocks.  */
      if (single_pred_p (bb)
	  && TEST_BIT (visited, single_pred (bb)->index)
	  && ! (single_pred_edge (bb)->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)))
	{
	  all_vd[bb->index] = all_vd[single_pred (bb)->index];
	  if (all_vd[bb->index].n_debug_insn_changes)
	    {
	      unsigned int regno;

	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
		{
		  if (all_vd[bb->index].e[regno].debug_insn_changes)
		    {
		      all_vd[bb->index].e[regno].debug_insn_changes = NULL;
		      if (--all_vd[bb->index].n_debug_insn_changes == 0)
			break;
		    }
		}
	    }
	}
      else
	init_value_data (all_vd + bb->index);

      copyprop_hardreg_forward_1 (bb, all_vd + bb->index);
    }

  if (MAY_HAVE_DEBUG_INSNS)
    {
      FOR_EACH_BB (bb)
	if (TEST_BIT (visited, bb->index)
	    && all_vd[bb->index].n_debug_insn_changes)
	  {
	    unsigned int regno;
	    bitmap live;

	    if (!analyze_called)
	      {
		df_analyze ();
		analyze_called = true;
	      }
	    live = df_get_live_out (bb);
	    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
	      if (all_vd[bb->index].e[regno].debug_insn_changes)
		{
		  if (REGNO_REG_SET_P (live, regno))
		    apply_debug_insn_changes (all_vd + bb->index, regno);
		  if (all_vd[bb->index].n_debug_insn_changes == 0)
		    break;
		}
	  }

      free_alloc_pool (debug_insn_changes_pool);
    }

  sbitmap_free (visited);
  free (all_vd);
  return 0;
}