Exemple #1
0
void
alloc_aux_for_edges (int size)
{
  static int initialized;

  if (!initialized)
    {
      gcc_obstack_init (&edge_aux_obstack);
      initialized = 1;
    }
  else
    /* Check whether AUX data are still allocated.  */
    gcc_assert (!first_edge_aux_obj);

  first_edge_aux_obj = obstack_alloc (&edge_aux_obstack, 0);
  if (size)
    {
      basic_block bb;

      FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
	{
	  edge e;
	  edge_iterator ei;

	  FOR_EACH_EDGE (e, ei, bb->succs)
	    alloc_aux_for_edge (e, size);
	}
    }
Exemple #2
0
/* Redirect edge and update latch and header info.  */
static void
redirect_edge_with_latch_update (edge e, basic_block to)
{
  basic_block jump;

  jump = redirect_edge_and_branch_force (e, to);
  if (jump)
    {
      alloc_aux_for_block (jump, sizeof (int));
      HEADER_BLOCK (jump) = 0;
      alloc_aux_for_edge (jump->pred, sizeof (int));
      LATCH_EDGE (jump->succ) = LATCH_EDGE (e);
      LATCH_EDGE (jump->pred) = 0;
    }
}
Exemple #3
0
static basic_block
make_forwarder_block (basic_block bb, int redirect_latch, int redirect_nonlatch, edge except, int conn_latch)
{
  edge e, next_e, fallthru;
  basic_block dummy;
  rtx insn;

  insn = PREV_INSN (first_insn_after_basic_block_note (bb));

  /* For empty block split_block will return NULL.  */
  if (BB_END (bb) == insn)
    emit_note_after (NOTE_INSN_DELETED, insn);

  fallthru = split_block (bb, insn);
  dummy = fallthru->src;
  bb = fallthru->dest;

  bb->aux = xmalloc (sizeof (int));
  HEADER_BLOCK (dummy) = 0;
  HEADER_BLOCK (bb) = 1;

  /* Redirect back edges we want to keep.  */
  for (e = dummy->pred; e; e = next_e)
    {
      next_e = e->pred_next;
      if (e == except
	  || !((redirect_latch && LATCH_EDGE (e))
	       || (redirect_nonlatch && !LATCH_EDGE (e))))
	{
	  dummy->frequency -= EDGE_FREQUENCY (e);
	  dummy->count -= e->count;
	  if (dummy->frequency < 0)
	    dummy->frequency = 0;
	  if (dummy->count < 0)
	    dummy->count = 0;
	  redirect_edge_with_latch_update (e, bb);
	}
    }

  alloc_aux_for_edge (fallthru, sizeof (int));
  LATCH_EDGE (fallthru) = conn_latch;

  return dummy;
}
Exemple #4
0
/* Takes care of merging natural loops with shared headers.  */
static void
canonicalize_loop_headers (void)
{
  basic_block header;
  edge e;

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

  alloc_aux_for_blocks (sizeof (int));
  alloc_aux_for_edges (sizeof (int));

  /* Split blocks so that each loop has only single latch.  */
  FOR_EACH_BB (header)
    {
      int num_latches = 0;
      int have_abnormal_edge = 0;

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

	  if (e->flags & EDGE_ABNORMAL)
	    have_abnormal_edge = 1;

	  if (latch != ENTRY_BLOCK_PTR
	      && dominated_by_p (CDI_DOMINATORS, latch, header))
	    {
	      num_latches++;
	      LATCH_EDGE (e) = 1;
	    }
	}
      if (have_abnormal_edge)
	HEADER_BLOCK (header) = 0;
      else
	HEADER_BLOCK (header) = num_latches;
    }

  free_dominance_info (CDI_DOMINATORS);

  if (HEADER_BLOCK (ENTRY_BLOCK_PTR->succ->dest))
    {
      basic_block bb;

      /* We could not redirect edges freely here. On the other hand,
	 we can simply split the edge from entry block.  */
      bb = split_edge (ENTRY_BLOCK_PTR->succ);

      alloc_aux_for_edge (bb->succ, sizeof (int));
      LATCH_EDGE (bb->succ) = 0;
      alloc_aux_for_block (bb, sizeof (int));
      HEADER_BLOCK (bb) = 0;
    }

  FOR_EACH_BB (header)
    {
      int num_latch;
      int want_join_latch;
      int max_freq, is_heavy;
      edge heavy;

      if (!HEADER_BLOCK (header))
	continue;

      num_latch = HEADER_BLOCK (header);

      want_join_latch = (num_latch > 1);

      if (!want_join_latch)
	continue;

      /* Find a heavy edge.  */
      is_heavy = 1;
      heavy = NULL;
      max_freq = 0;
      for (e = header->pred; e; e = e->pred_next)
	if (LATCH_EDGE (e) &&
	    EDGE_FREQUENCY (e) > max_freq)
	  max_freq = EDGE_FREQUENCY (e);
      for (e = header->pred; e; e = e->pred_next)
	if (LATCH_EDGE (e) &&
	    EDGE_FREQUENCY (e) >= max_freq / HEAVY_EDGE_RATIO)
	  {
	    if (heavy)
	      {
		is_heavy = 0;
		break;
	      }
	    else
	      heavy = e;
	  }

      if (is_heavy)
	{
	  basic_block new_header =
	    make_forwarder_block (header, true, true, heavy, 0);
	  if (num_latch > 2)
	    make_forwarder_block (new_header, true, false, NULL, 1);
	}
      else
	make_forwarder_block (header, true, false, NULL, 1);
    }

  free_aux_for_blocks ();
  free_aux_for_edges ();
}