示例#1
0
/* Generate code for transformations 3 and 4 (with MODE and OPERATION,
   operands OP1 and OP2, result TARGET, at most SUB subtractions, and
   probability of taking the optimal path(s) PROB1 and PROB2).  */
static rtx
gen_mod_subtract (enum machine_mode mode, enum rtx_code operation,
		  rtx target, rtx op1, rtx op2, int sub, int prob1, int prob2)
{
  rtx tmp, tmp1, jump;
  rtx end_label = gen_label_rtx ();
  rtx sequence;
  int i;

  start_sequence ();
  
  if (!REG_P (op2))
    {
      tmp = gen_reg_rtx (mode);
      emit_move_insn (tmp, copy_rtx (op2));
    }
  else
    tmp = op2;

  emit_move_insn (target, copy_rtx (op1));
  do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
			   NULL_RTX, end_label);

  /* Add branch probability to jump we just created.  */
  jump = get_last_insn ();
  REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					GEN_INT (prob1), REG_NOTES (jump));

  for (i = 0; i < sub; i++)
    {
      tmp1 = expand_simple_binop (mode, MINUS, target, tmp, target,
	    			  0, OPTAB_WIDEN);
      if (tmp1 != target)
	emit_move_insn (target, tmp1);
      do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
    			       NULL_RTX, end_label);

      /* Add branch probability to jump we just created.  */
      jump = get_last_insn ();
      REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					    GEN_INT (prob2), REG_NOTES (jump));
    }

  tmp1 = simplify_gen_binary (operation, mode, copy_rtx (target), copy_rtx (tmp));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (target, tmp1);
  
  emit_label (end_label);

  sequence = get_insns ();
  end_sequence ();
  rebuild_jump_labels (sequence);
  return sequence;
}
示例#2
0
static void
add_test (rtx cond, basic_block bb, basic_block dest)
{
    rtx seq, jump, label;
    enum machine_mode mode;
    rtx op0 = XEXP (cond, 0), op1 = XEXP (cond, 1);
    enum rtx_code code = GET_CODE (cond);

    mode = GET_MODE (XEXP (cond, 0));
    if (mode == VOIDmode)
        mode = GET_MODE (XEXP (cond, 1));

    start_sequence ();
    op0 = force_operand (op0, NULL_RTX);
    op1 = force_operand (op1, NULL_RTX);
    label = block_label (dest);
    do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX, NULL_RTX, label);

    jump = get_last_insn ();
    JUMP_LABEL (jump) = label;

    /* The jump is supposed to handle an unlikely special case.  */
    REG_NOTES (jump)
        = gen_rtx_EXPR_LIST (REG_BR_PROB,
                             const0_rtx, REG_NOTES (jump));

    LABEL_NUSES (label)++;

    seq = get_insns ();
    end_sequence ();
    emit_insn_after (seq, BB_END (bb));
}
示例#3
0
/* Generate code for transformation 2 (with MODE and OPERATION, operands OP1
   and OP2, result TARGET and probability of taking the optimal path PROB).  */
static rtx
gen_mod_pow2 (enum machine_mode mode, enum rtx_code operation, rtx target,
	      rtx op1, rtx op2, int prob)
{
  rtx tmp, tmp1, tmp2, tmp3, jump;
  rtx neq_label = gen_label_rtx ();
  rtx end_label = gen_label_rtx ();
  rtx sequence;

  start_sequence ();
  
  if (!REG_P (op2))
    {
      tmp = gen_reg_rtx (mode);
      emit_move_insn (tmp, copy_rtx (op2));
    }
  else
    tmp = op2;

  tmp1 = expand_simple_binop (mode, PLUS, tmp, constm1_rtx, NULL_RTX,
			      0, OPTAB_WIDEN);
  tmp2 = expand_simple_binop (mode, AND, tmp, tmp1, NULL_RTX,
			      0, OPTAB_WIDEN);
  do_compare_rtx_and_jump (tmp2, const0_rtx, NE, 0, mode, NULL_RTX,
			   NULL_RTX, neq_label);

  /* Add branch probability to jump we just created.  */
  jump = get_last_insn ();
  REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					GEN_INT (REG_BR_PROB_BASE - prob),
					REG_NOTES (jump));

  tmp3 = expand_simple_binop (mode, AND, op1, tmp1, target,
			      0, OPTAB_WIDEN);
  if (tmp3 != target)
    emit_move_insn (copy_rtx (target), tmp3);
  emit_jump_insn (gen_jump (end_label));
  emit_barrier ();

  emit_label (neq_label);
  tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), copy_rtx (tmp));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (target, tmp1);
  
  emit_label (end_label);

  sequence = get_insns ();
  end_sequence ();
  rebuild_jump_labels (sequence);
  return sequence;
}
示例#4
0
/* Generate code for transformation 1 (with MODE and OPERATION, operands OP1
   and OP2, whose value is expected to be VALUE, result TARGET and
   probability of taking the optimal path PROB).  */
static rtx
gen_divmod_fixed_value (enum machine_mode mode, enum rtx_code operation,
			rtx target, rtx op1, rtx op2, gcov_type value,
			int prob)
{
  rtx tmp, tmp1, jump;
  rtx neq_label = gen_label_rtx ();
  rtx end_label = gen_label_rtx ();
  rtx sequence;

  start_sequence ();
  
  if (!REG_P (op2))
    {
      tmp = gen_reg_rtx (mode);
      emit_move_insn (tmp, copy_rtx (op2));
    }
  else
    tmp = op2;

  do_compare_rtx_and_jump (tmp, GEN_INT (value), NE, 0, mode, NULL_RTX,
			   NULL_RTX, neq_label);

  /* Add branch probability to jump we just created.  */
  jump = get_last_insn ();
  REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					GEN_INT (REG_BR_PROB_BASE - prob),
					REG_NOTES (jump));

  tmp1 = simplify_gen_binary (operation, mode,
			      copy_rtx (op1), GEN_INT (value));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (copy_rtx (target), copy_rtx (tmp1));

  emit_jump_insn (gen_jump (end_label));
  emit_barrier ();

  emit_label (neq_label);
  tmp1 = simplify_gen_binary (operation, mode,
			      copy_rtx (op1), copy_rtx (tmp));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (copy_rtx (target), copy_rtx (tmp1));
  
  emit_label (end_label);

  sequence = get_insns ();
  end_sequence ();
  rebuild_jump_labels (sequence);
  return sequence;
}
示例#5
0
/* Verify that there is exactly single jump instruction since last and attach
   REG_BR_PROB note specifying probability.
   ??? We really ought to pass the probability down to RTL expanders and let it
   re-distribute it when the conditional expands into multiple conditionals.
   This is however difficult to do.  */
static void
add_reg_br_prob_note (FILE *dump_file, rtx last, int probability)
{
  if (profile_status == PROFILE_ABSENT)
    return;
  for (last = NEXT_INSN (last); last && NEXT_INSN (last); last = NEXT_INSN (last))
    if (GET_CODE (last) == JUMP_INSN)
      {
	/* It is common to emit condjump-around-jump sequence when we don't know
	   how to reverse the conditional.  Special case this.  */
	if (!any_condjump_p (last)
	    || GET_CODE (NEXT_INSN (last)) != JUMP_INSN
	    || !simplejump_p (NEXT_INSN (last))
	    || GET_CODE (NEXT_INSN (NEXT_INSN (last))) != BARRIER
	    || GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (last)))) != CODE_LABEL
	    || NEXT_INSN (NEXT_INSN (NEXT_INSN (NEXT_INSN (last)))))
	  goto failed;
	if (find_reg_note (last, REG_BR_PROB, 0))
	  abort ();
	REG_NOTES (last)
	  = gen_rtx_EXPR_LIST (REG_BR_PROB,
			       GEN_INT (REG_BR_PROB_BASE - probability),
			       REG_NOTES (last));
	return;
      }
  if (!last || GET_CODE (last) != JUMP_INSN || !any_condjump_p (last))
      goto failed;
  if (find_reg_note (last, REG_BR_PROB, 0))
    abort ();
  REG_NOTES (last)
    = gen_rtx_EXPR_LIST (REG_BR_PROB,
			 GEN_INT (probability), REG_NOTES (last));
  return;
failed:
  if (dump_file)
    fprintf (dump_file, "Failed to add probability note\n");
}
示例#6
0
rtx
compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob,
                      rtx cinsn)
{
    rtx seq, jump, cond;
    enum machine_mode mode;

    mode = GET_MODE (op0);
    if (mode == VOIDmode)
        mode = GET_MODE (op1);

    start_sequence ();
    if (GET_MODE_CLASS (mode) == MODE_CC)
    {
        /* A hack -- there seems to be no easy generic way how to make a
           conditional jump from a ccmode comparison.  */
        gcc_assert (cinsn);
        cond = XEXP (SET_SRC (pc_set (cinsn)), 0);
        gcc_assert (GET_CODE (cond) == comp);
        gcc_assert (rtx_equal_p (op0, XEXP (cond, 0)));
        gcc_assert (rtx_equal_p (op1, XEXP (cond, 1)));
        emit_jump_insn (copy_insn (PATTERN (cinsn)));
        jump = get_last_insn ();
        JUMP_LABEL (jump) = JUMP_LABEL (cinsn);
        LABEL_NUSES (JUMP_LABEL (jump))++;
        redirect_jump (jump, label, 0);
    }
    else
    {
        gcc_assert (!cinsn);

        op0 = force_operand (op0, NULL_RTX);
        op1 = force_operand (op1, NULL_RTX);
        do_compare_rtx_and_jump (op0, op1, comp, 0,
                                 mode, NULL_RTX, NULL_RTX, label);
        jump = get_last_insn ();
        JUMP_LABEL (jump) = label;
        LABEL_NUSES (label)++;
    }
    REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
                                          REG_NOTES (jump));
    seq = get_insns ();
    end_sequence ();

    return seq;
}
示例#7
0
文件: lists.c 项目: KangDroid/gcc
/* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached
   node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
   is made.  */
rtx_expr_list *
alloc_EXPR_LIST (int kind, rtx val, rtx next)
{
  rtx_expr_list *r;

  if (unused_expr_list)
    {
      r = as_a <rtx_expr_list *> (unused_expr_list);
      unused_expr_list = XEXP (r, 1);
      XEXP (r, 0) = val;
      XEXP (r, 1) = next;
      PUT_REG_NOTE_KIND (r, kind);
    }
  else
    r = gen_rtx_EXPR_LIST ((machine_mode) kind, val, next);

  return r;
}
示例#8
0
/* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached
   node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
   is made.  */
rtx
alloc_EXPR_LIST (int kind, rtx val, rtx next)
{
    rtx r;

    if (unused_expr_list)
    {
        r = unused_expr_list;
        unused_expr_list = XEXP (r, 1);
        XEXP (r, 0) = val;
        XEXP (r, 1) = next;
        PUT_REG_NOTE_KIND (r, kind);
    }
    else
        r = gen_rtx_EXPR_LIST (kind, val, next);

    return r;
}
示例#9
0
static void
doloop_modify (struct loop *loop, struct niter_desc *desc,
               rtx doloop_seq, rtx condition, rtx count)
{
    rtx counter_reg;
    rtx tmp, noloop = NULL_RTX;
    rtx sequence;
    rtx jump_insn;
    rtx jump_label;
    int nonneg = 0, irr;
    bool increment_count;
    basic_block loop_end = desc->out_edge->src;
    enum machine_mode mode;

    jump_insn = BB_END (loop_end);

    if (dump_file)
    {
        fprintf (dump_file, "Doloop: Inserting doloop pattern (");
        if (desc->const_iter)
            fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, desc->niter);
        else
            fputs ("runtime", dump_file);
        fputs (" iterations).\n", dump_file);
    }

    /* Discard original jump to continue loop.  The original compare
       result may still be live, so it cannot be discarded explicitly.  */
    delete_insn (jump_insn);

    counter_reg = XEXP (condition, 0);
    if (GET_CODE (counter_reg) == PLUS)
        counter_reg = XEXP (counter_reg, 0);
    mode = GET_MODE (counter_reg);

    increment_count = false;
    switch (GET_CODE (condition))
    {
    case NE:
        /* Currently only NE tests against zero and one are supported.  */
        if (XEXP (condition, 1) == const1_rtx)
        {
            increment_count = true;
            noloop = const1_rtx;
        }
        else if (XEXP (condition, 1) == const0_rtx)
            noloop = const0_rtx;
        else
            abort ();
        break;

    case GE:
        /* Currently only GE tests against zero are supported.  */
        if (XEXP (condition, 1) != const0_rtx)
            abort ();

        noloop = constm1_rtx;

        /* The iteration count does not need incrementing for a GE test.  */
        increment_count = false;

        /* Determine if the iteration counter will be non-negative.
        Note that the maximum value loaded is iterations_max - 1.  */
        if (desc->niter_max
                <= ((unsigned HOST_WIDEST_INT) 1
                    << (GET_MODE_BITSIZE (mode) - 1)))
            nonneg = 1;
        break;

    /* Abort if an invalid doloop pattern has been generated.  */
    default:
        abort ();
    }

    if (increment_count)
        count = simplify_gen_binary (PLUS, mode, count, const1_rtx);

    /* Insert initialization of the count register into the loop header.  */
    start_sequence ();
    tmp = force_operand (count, counter_reg);
    convert_move (counter_reg, tmp, 1);
    sequence = get_insns ();
    end_sequence ();
    emit_insn_after (sequence, BB_END (loop_preheader_edge (loop)->src));

    if (desc->noloop_assumptions)
    {
        rtx ass = copy_rtx (desc->noloop_assumptions);
        basic_block preheader = loop_preheader_edge (loop)->src;
        basic_block set_zero
            = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
        basic_block new_preheader
            = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
        basic_block bb;
        edge te;
        gcov_type cnt;

        /* Expand the condition testing the assumptions and if it does not pass,
        reset the count register to 0.  */
        add_test (XEXP (ass, 0), preheader, set_zero);
        EDGE_SUCC (preheader, 0)->flags &= ~EDGE_FALLTHRU;
        cnt = EDGE_SUCC (preheader, 0)->count;
        EDGE_SUCC (preheader, 0)->probability = 0;
        EDGE_SUCC (preheader, 0)->count = 0;
        irr = EDGE_SUCC (preheader, 0)->flags & EDGE_IRREDUCIBLE_LOOP;
        te = make_edge (preheader, new_preheader, EDGE_FALLTHRU | irr);
        te->probability = REG_BR_PROB_BASE;
        te->count = cnt;
        set_immediate_dominator (CDI_DOMINATORS, new_preheader, preheader);

        set_zero->count = 0;
        set_zero->frequency = 0;

        for (ass = XEXP (ass, 1); ass; ass = XEXP (ass, 1))
        {
            bb = loop_split_edge_with (te, NULL_RTX);
            te = EDGE_SUCC (bb, 0);
            add_test (XEXP (ass, 0), bb, set_zero);
            make_edge (bb, set_zero, irr);
        }

        start_sequence ();
        convert_move (counter_reg, noloop, 0);
        sequence = get_insns ();
        end_sequence ();
        emit_insn_after (sequence, BB_END (set_zero));
    }

    /* Some targets (eg, C4x) need to initialize special looping
       registers.  */
#ifdef HAVE_doloop_begin
    {
        rtx init;
        unsigned level = get_loop_level (loop) + 1;
        init = gen_doloop_begin (counter_reg,
                                 desc->const_iter ? desc->niter_expr : const0_rtx,
                                 desc->niter_max,
                                 GEN_INT (level));
        if (init)
        {
            start_sequence ();
            emit_insn (init);
            sequence = get_insns ();
            end_sequence ();
            emit_insn_after (sequence, BB_END (loop_preheader_edge (loop)->src));
        }
    }
#endif

    /* Insert the new low-overhead looping insn.  */
    emit_jump_insn_after (doloop_seq, BB_END (loop_end));
    jump_insn = BB_END (loop_end);
    jump_label = block_label (desc->in_edge->dest);
    JUMP_LABEL (jump_insn) = jump_label;
    LABEL_NUSES (jump_label)++;

    /* Ensure the right fallthru edge is marked, for case we have reversed
       the condition.  */
    desc->in_edge->flags &= ~EDGE_FALLTHRU;
    desc->out_edge->flags |= EDGE_FALLTHRU;

    /* Add a REG_NONNEG note if the actual or estimated maximum number
       of iterations is non-negative.  */
    if (nonneg)
    {
        REG_NOTES (jump_insn)
            = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX, REG_NOTES (jump_insn));
    }
}
示例#10
0
static void
fixup_reorder_chain (void)
{
  basic_block bb, prev_bb;
  int index;
  rtx insn = NULL;

  if (cfg_layout_function_header)
    {
      set_first_insn (cfg_layout_function_header);
      insn = cfg_layout_function_header;
      while (NEXT_INSN (insn))
	insn = NEXT_INSN (insn);
    }

  /* First do the bulk reordering -- rechain the blocks without regard to
     the needed changes to jumps and labels.  */

  for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
       bb != 0;
       bb = bb->aux, index++)
    {
      if (bb->il.rtl->header)
	{
	  if (insn)
	    NEXT_INSN (insn) = bb->il.rtl->header;
	  else
	    set_first_insn (bb->il.rtl->header);
	  PREV_INSN (bb->il.rtl->header) = insn;
	  insn = bb->il.rtl->header;
	  while (NEXT_INSN (insn))
	    insn = NEXT_INSN (insn);
	}
      if (insn)
	NEXT_INSN (insn) = BB_HEAD (bb);
      else
	set_first_insn (BB_HEAD (bb));
      PREV_INSN (BB_HEAD (bb)) = insn;
      insn = BB_END (bb);
      if (bb->il.rtl->footer)
	{
	  NEXT_INSN (insn) = bb->il.rtl->footer;
	  PREV_INSN (bb->il.rtl->footer) = insn;
	  while (NEXT_INSN (insn))
	    insn = NEXT_INSN (insn);
	}
    }

  gcc_assert (index == n_basic_blocks);

  NEXT_INSN (insn) = cfg_layout_function_footer;
  if (cfg_layout_function_footer)
    PREV_INSN (cfg_layout_function_footer) = insn;

  while (NEXT_INSN (insn))
    insn = NEXT_INSN (insn);

  set_last_insn (insn);
#ifdef ENABLE_CHECKING
  verify_insn_chain ();
#endif
  delete_dead_jumptables ();

  /* Now add jumps and labels as needed to match the blocks new
     outgoing edges.  */

  for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = bb->aux)
    {
      edge e_fall, e_taken, e;
      rtx bb_end_insn;
      basic_block nb;
      edge_iterator ei;

      if (EDGE_COUNT (bb->succs) == 0)
	continue;

      /* Find the old fallthru edge, and another non-EH edge for
	 a taken jump.  */
      e_taken = e_fall = NULL;

      FOR_EACH_EDGE (e, ei, bb->succs)
	if (e->flags & EDGE_FALLTHRU)
	  e_fall = e;
	else if (! (e->flags & EDGE_EH))
	  e_taken = e;

      bb_end_insn = BB_END (bb);
      if (JUMP_P (bb_end_insn))
	{
	  if (any_condjump_p (bb_end_insn))
	    {
	      /* If the old fallthru is still next, nothing to do.  */
	      if (bb->aux == e_fall->dest
		  || e_fall->dest == EXIT_BLOCK_PTR)
		continue;

	      /* The degenerated case of conditional jump jumping to the next
		 instruction can happen for jumps with side effects.  We need
		 to construct a forwarder block and this will be done just
		 fine by force_nonfallthru below.  */
	      if (!e_taken)
		;

	      /* There is another special case: if *neither* block is next,
		 such as happens at the very end of a function, then we'll
		 need to add a new unconditional jump.  Choose the taken
		 edge based on known or assumed probability.  */
	      else if (bb->aux != e_taken->dest)
		{
		  rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);

		  if (note
		      && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
		      && invert_jump (bb_end_insn,
				      (e_fall->dest == EXIT_BLOCK_PTR
				       ? NULL_RTX
				       : label_for_bb (e_fall->dest)), 0))
		    {
		      e_fall->flags &= ~EDGE_FALLTHRU;
#ifdef ENABLE_CHECKING
		      gcc_assert (could_fall_through
				  (e_taken->src, e_taken->dest));
#endif
		      e_taken->flags |= EDGE_FALLTHRU;
		      update_br_prob_note (bb);
		      e = e_fall, e_fall = e_taken, e_taken = e;
		    }
		}

	      /* If the "jumping" edge is a crossing edge, and the fall
		 through edge is non-crossing, leave things as they are.  */
	      else if ((e_taken->flags & EDGE_CROSSING)
		       && !(e_fall->flags & EDGE_CROSSING))
		continue;

	      /* Otherwise we can try to invert the jump.  This will
		 basically never fail, however, keep up the pretense.  */
	      else if (invert_jump (bb_end_insn,
				    (e_fall->dest == EXIT_BLOCK_PTR
				     ? NULL_RTX
				     : label_for_bb (e_fall->dest)), 0))
		{
		  e_fall->flags &= ~EDGE_FALLTHRU;
#ifdef ENABLE_CHECKING
		  gcc_assert (could_fall_through
			      (e_taken->src, e_taken->dest));
#endif
		  e_taken->flags |= EDGE_FALLTHRU;
		  update_br_prob_note (bb);
		  continue;
		}
	    }
	  else
	    {
	      /* Otherwise we have some return, switch or computed
		 jump.  In the 99% case, there should not have been a
		 fallthru edge.  */
	      gcc_assert (returnjump_p (bb_end_insn) || !e_fall);
	      continue;
	    }
	}
      else
	{
	  /* No fallthru implies a noreturn function with EH edges, or
	     something similarly bizarre.  In any case, we don't need to
	     do anything.  */
	  if (! e_fall)
	    continue;

	  /* If the fallthru block is still next, nothing to do.  */
	  if (bb->aux == e_fall->dest)
	    continue;

	  /* A fallthru to exit block.  */
	  if (e_fall->dest == EXIT_BLOCK_PTR)
	    continue;
	}

      /* We got here if we need to add a new jump insn.  */
      nb = force_nonfallthru (e_fall);
      if (nb)
	{
	  nb->il.rtl->visited = 1;
	  nb->aux = bb->aux;
	  bb->aux = nb;
	  /* Don't process this new block.  */
	  bb = nb;

	  /* Make sure new bb is tagged for correct section (same as
	     fall-thru source, since you cannot fall-throu across
	     section boundaries).  */
	  BB_COPY_PARTITION (e_fall->src, single_pred (bb));
	  if (flag_reorder_blocks_and_partition
	      && targetm.have_named_sections
	      && JUMP_P (BB_END (bb))
	      && !any_condjump_p (BB_END (bb))
	      && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
	    REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST
	      (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb)));
	}
    }

  /* Put basic_block_info in the new order.  */

  if (dump_file)
    {
      fprintf (dump_file, "Reordered sequence:\n");
      for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
	   bb;
	   bb = bb->aux, index++)
	{
	  fprintf (dump_file, " %i ", index);
	  if (get_bb_original (bb))
	    fprintf (dump_file, "duplicate of %i ",
		     get_bb_original (bb)->index);
	  else if (forwarder_block_p (bb)
		   && !LABEL_P (BB_HEAD (bb)))
	    fprintf (dump_file, "compensation ");
	  else
	    fprintf (dump_file, "bb %i ", bb->index);
	  fprintf (dump_file, " [%i]\n", bb->frequency);
	}
    }

  prev_bb = ENTRY_BLOCK_PTR;
  bb = ENTRY_BLOCK_PTR->next_bb;
  index = NUM_FIXED_BLOCKS;

  for (; bb; prev_bb = bb, bb = bb->aux, index ++)
    {
      bb->index = index;
      SET_BASIC_BLOCK (index, bb);

      bb->prev_bb = prev_bb;
      prev_bb->next_bb = bb;
    }
  prev_bb->next_bb = EXIT_BLOCK_PTR;
  EXIT_BLOCK_PTR->prev_bb = prev_bb;

  /* Annoying special case - jump around dead jumptables left in the code.  */
  FOR_EACH_BB (bb)
    {
      edge e;
      edge_iterator ei;

      FOR_EACH_EDGE (e, ei, bb->succs)
	if (e->flags & EDGE_FALLTHRU)
	  break;

      if (e && !can_fallthru (e->src, e->dest))
	force_nonfallthru (e);
    }
}
示例#11
0
static void
adjust_frame_related_expr (rtx last_sp_set, rtx insn,
			   HOST_WIDE_INT this_adjust)
{
  rtx note = find_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, NULL_RTX);
  rtx new_expr = NULL_RTX;

  if (note == NULL_RTX && RTX_FRAME_RELATED_P (insn))
    return;

  if (note
      && GET_CODE (XEXP (note, 0)) == SEQUENCE
      && XVECLEN (XEXP (note, 0), 0) >= 2)
    {
      rtx expr = XEXP (note, 0);
      rtx last = XVECEXP (expr, 0, XVECLEN (expr, 0) - 1);
      int i;

      if (GET_CODE (last) == SET
	  && RTX_FRAME_RELATED_P (last) == RTX_FRAME_RELATED_P (insn)
	  && SET_DEST (last) == stack_pointer_rtx
	  && GET_CODE (SET_SRC (last)) == PLUS
	  && XEXP (SET_SRC (last), 0) == stack_pointer_rtx
	  && GET_CODE (XEXP (SET_SRC (last), 1)) == CONST_INT)
	{
	  XEXP (SET_SRC (last), 1)
	    = GEN_INT (INTVAL (XEXP (SET_SRC (last), 1)) + this_adjust);
	  return;
	}

      new_expr = gen_rtx_SEQUENCE (VOIDmode,
				   rtvec_alloc (XVECLEN (expr, 0) + 1));
      for (i = 0; i < XVECLEN (expr, 0); i++)
	XVECEXP (new_expr, 0, i) = XVECEXP (expr, 0, i);
    }
  else
    {
      new_expr = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2));
      if (note)
	XVECEXP (new_expr, 0, 0) = XEXP (note, 0);
      else
	{
	  rtx expr = copy_rtx (single_set_for_csa (last_sp_set));

	  XEXP (SET_SRC (expr), 1)
	    = GEN_INT (INTVAL (XEXP (SET_SRC (expr), 1)) - this_adjust);
	  RTX_FRAME_RELATED_P (expr) = 1;
	  XVECEXP (new_expr, 0, 0) = expr;
	}
    }

  XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1)
    = copy_rtx (single_set_for_csa (insn));
  RTX_FRAME_RELATED_P (XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1))
    = RTX_FRAME_RELATED_P (insn);
  if (note)
    XEXP (note, 0) = new_expr;
  else
    REG_NOTES (last_sp_set)
      = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, new_expr,
			   REG_NOTES (last_sp_set));
}