Пример #1
0
/* Process the death of hard register REGNO.  This updates
   hard_regs_live and START_DYING.  */
static void
make_hard_regno_dead (int regno)
{
  lra_assert (regno < FIRST_PSEUDO_REGISTER);
  if (! TEST_HARD_REG_BIT (hard_regs_live, regno))
    return;
  sparseset_set_bit (start_dying, regno);
  CLEAR_HARD_REG_BIT (hard_regs_live, regno);
}
Пример #2
0
static void
recompute_gain_for_pattern_seq (pattern_seq pseq)
{
  matching_seq mseq;
  rtx x;
  int i;
  int hascall;
  HARD_REG_SET linkregs;

  /* Initialize data.  */
  SET_HARD_REG_SET (linkregs);
  pseq->link_reg = NULL_RTX;
  pseq->abstracted_length = 0;

  pseq->gain = -(seq_call_cost - seq_jump_cost + seq_return_cost);

  /* Determine ABSTRACTED_LENGTH and COST for matching sequences of PSEQ.
     ABSTRACTED_LENGTH may be less than MATCHING_LENGTH if sequences in the
     same block overlap. */

  for (mseq = pseq->matching_seqs; mseq; mseq = mseq->next_matching_seq)
    {
      /* Determine ABSTRACTED_LENGTH.  */
      if (mseq->next_matching_seq)
        mseq->abstracted_length = (int)(mseq->next_matching_seq->idx -
                                        mseq->idx);
      else
        mseq->abstracted_length = mseq->matching_length;

      if (mseq->abstracted_length > mseq->matching_length)
        mseq->abstracted_length = mseq->matching_length;

      /* Compute the cost of sequence.  */
      RECOMPUTE_COST (mseq);

      /* If COST is big enough registers live in this matching sequence
         should not be used as a link register. Also set ABSTRACTED_LENGTH
         of PSEQ.  */
      if (mseq->cost > seq_call_cost)
        {
          clear_regs_live_in_seq (&linkregs, mseq->insn,
                                  mseq->abstracted_length);
          if (mseq->abstracted_length > pseq->abstracted_length)
            pseq->abstracted_length = mseq->abstracted_length;
        }
    }

  /* Modify ABSTRACTED_LENGTH of PSEQ if pattern sequence overlaps with one
     of the matching sequences.  */
  for (mseq = pseq->matching_seqs; mseq; mseq = mseq->next_matching_seq)
    {
      x = pseq->insn;
      for (i = 0; (i < pseq->abstracted_length) && (x != mseq->insn); i++)
        x = prev_insn_in_block (x);
      pseq->abstracted_length = i;
    }

  /* Compute the cost of pattern sequence.  */
  RECOMPUTE_COST (pseq);

  /* No gain if COST is too small.  */
  if (pseq->cost <= seq_call_cost)
  {
    pseq->gain = -1;
    return;
  }

  /* Ensure that no matching sequence is longer than the pattern sequence.  */
  for (mseq = pseq->matching_seqs; mseq; mseq = mseq->next_matching_seq)
    {
      if (mseq->abstracted_length > pseq->abstracted_length)
        {
          mseq->abstracted_length = pseq->abstracted_length;
          RECOMPUTE_COST (mseq);
        }
      /* Once the length is stabilizing the gain can be calculated.  */
      if (mseq->cost > seq_call_cost)
        pseq->gain += mseq->cost - seq_call_cost;
    }

  /* No need to do further work if there is no gain.  */
  if (pseq->gain <= 0)
    return;

  /* Should not use registers live in the pattern sequence as link register.
   */
  clear_regs_live_in_seq (&linkregs, pseq->insn, pseq->abstracted_length);

  /* Determine whether pattern sequence contains a call_insn.  */
  hascall = 0;
  x = pseq->insn;
  for (i = 0; i < pseq->abstracted_length; i++)
    {
      if (CALL_P (x))
        {
          hascall = 1;
          break;
        }
      x = prev_insn_in_block (x);
    }

  /* Should not use a register as a link register if - it is a fixed
     register, or - the sequence contains a call insn and the register is a
     call used register, or - the register needs to be saved if used in a
     function but was not used before (since saving it can invalidate already
     computed frame pointer offsets), or - the register cannot be used as a
     base register.  */

  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    if (fixed_regs[i]
#ifdef REGNO_OK_FOR_INDIRECT_JUMP_P
        || (!REGNO_OK_FOR_INDIRECT_JUMP_P (i, Pmode))
#else
        || (!ok_for_base_p_1 (i, Pmode, MEM, SCRATCH))
        || (!reg_class_subset_p (REGNO_REG_CLASS (i),
				 base_reg_class (VOIDmode, MEM, SCRATCH)))
#endif
        || (hascall && call_used_regs[i])
        || (!call_used_regs[i] && !df_regs_ever_live_p (i)))
      CLEAR_HARD_REG_BIT (linkregs, i);

  /* Find an appropriate register to be used as the link register.  */
  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    if (TEST_HARD_REG_BIT (linkregs, i))
      {
        pseq->link_reg = gen_rtx_REG (Pmode, i);
        break;
      }

  /* Abstraction is not possible if no link register is available, so set
     gain to 0.  */
  if (!pseq->link_reg)
    pseq->gain = 0;
}