OSDN Git Service

2004-10-28 Frank Ch. Eigler <fche@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / local-alloc.c
index 26cb7ed..ebda9dd 100644 (file)
@@ -1,6 +1,6 @@
 /* Allocate registers within a basic block, for GNU compiler.
    Copyright (C) 1987, 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -108,7 +108,7 @@ struct qty
 
   /* Number of words needed to hold the data in given quantity.
      This depends on its machine mode.  It is used for these purposes:
-     1. It is used in computing the relative importances of qtys,
+     1. It is used in computing the relative importance of qtys,
        which determines the order in which we look for regs for them.
      2. It is used in rules that prevent tying several registers of
        different sizes in a way that is geometrically impossible
@@ -448,9 +448,9 @@ static void
 validate_equiv_mem_from_store (rtx dest, rtx set ATTRIBUTE_UNUSED,
                               void *data ATTRIBUTE_UNUSED)
 {
-  if ((GET_CODE (dest) == REG
+  if ((REG_P (dest)
        && reg_overlap_mentioned_p (dest, equiv_mem))
-      || (GET_CODE (dest) == MEM
+      || (MEM_P (dest)
          && true_dependence (dest, VOIDmode, equiv_mem, rtx_varies_p)))
     equiv_mem_modified = 1;
 }
@@ -484,7 +484,7 @@ validate_equiv_mem (rtx start, rtx reg, rtx memref)
       if (find_reg_note (insn, REG_DEAD, reg))
        return 1;
 
-      if (GET_CODE (insn) == CALL_INSN && ! RTX_UNCHANGING_P (memref)
+      if (CALL_P (insn) && ! MEM_READONLY_P (memref)
          && ! CONST_OR_PURE_CALL_P (insn))
        return 0;
 
@@ -498,7 +498,7 @@ validate_equiv_mem (rtx start, rtx reg, rtx memref)
       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
        if ((REG_NOTE_KIND (note) == REG_INC
             || REG_NOTE_KIND (note) == REG_DEAD)
-           && GET_CODE (XEXP (note, 0)) == REG
+           && REG_P (XEXP (note, 0))
            && reg_overlap_mentioned_p (XEXP (note, 0), memref))
          return 0;
     }
@@ -518,10 +518,7 @@ equiv_init_varies_p (rtx x)
   switch (code)
     {
     case MEM:
-      return ! RTX_UNCHANGING_P (x) || equiv_init_varies_p (XEXP (x, 0));
-
-    case QUEUED:
-      return 1;
+      return !MEM_READONLY_P (x) || equiv_init_varies_p (XEXP (x, 0));
 
     case CONST:
     case CONST_INT:
@@ -538,7 +535,7 @@ equiv_init_varies_p (rtx x)
       if (MEM_VOLATILE_P (x))
        return 1;
 
-      /* FALLTHROUGH */
+      /* Fall through.  */
 
     default:
       break;
@@ -603,7 +600,7 @@ equiv_init_movable_p (rtx x, int regno)
       if (MEM_VOLATILE_P (x))
        return 0;
 
-      /* FALLTHROUGH */
+      /* Fall through.  */
 
     default:
       break;
@@ -711,7 +708,7 @@ memref_referenced_p (rtx memref, rtx x)
     case SET:
       /* If we are setting a MEM, it doesn't count (its address does), but any
         other SET_DEST that has a MEM in it is referencing the MEM.  */
-      if (GET_CODE (SET_DEST (x)) == MEM)
+      if (MEM_P (SET_DEST (x)))
        {
          if (memref_referenced_p (memref, XEXP (SET_DEST (x), 0)))
            return 1;
@@ -759,27 +756,6 @@ memref_used_between_p (rtx memref, rtx start, rtx end)
   return 0;
 }
 \f
-/* Return nonzero if the rtx X is invariant over the current function.  */
-/* ??? Actually, the places this is used in reload expect exactly what
-   is tested here, and not everything that is function invariant.  In
-   particular, the frame pointer and arg pointer are special cased;
-   pic_offset_table_rtx is not, and this will cause aborts when we
-   go to spill these things to memory.  */
-
-int
-function_invariant_p (rtx x)
-{
-  if (CONSTANT_P (x))
-    return 1;
-  if (x == frame_pointer_rtx || x == arg_pointer_rtx)
-    return 1;
-  if (GET_CODE (x) == PLUS
-      && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
-      && CONSTANT_P (XEXP (x, 1)))
-    return 1;
-  return 0;
-}
-
 /* Find registers that are equivalent to a single value throughout the
    compilation (either because they can be referenced in memory or are set once
    from a single constant).  Lower their priority for a register.
@@ -809,7 +785,9 @@ update_equiv_regs (void)
     {
       loop_depth = bb->loop_depth;
 
-      for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
+      for (insn = BB_HEAD (bb);
+          insn != NEXT_INSN (BB_END (bb));
+          insn = NEXT_INSN (insn))
        {
          rtx note;
          rtx set;
@@ -868,7 +846,7 @@ update_equiv_regs (void)
             Equivalences to MEMs should be made in another pass, after the
             reg_equiv[].replace information has been gathered.  */
 
-         if (GET_CODE (dest) == MEM && GET_CODE (src) == REG
+         if (MEM_P (dest) && REG_P (src)
              && (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
              && REG_BASIC_BLOCK (regno) >= 0
              && REG_N_SETS (regno) == 1
@@ -897,11 +875,11 @@ update_equiv_regs (void)
             preferred class of a pseudo depends on all instructions that set
             or use it.  */
 
-         if (GET_CODE (dest) != REG
+         if (!REG_P (dest)
              || (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
              || reg_equiv[regno].init_insns == const0_rtx
              || (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
-                 && GET_CODE (src) == MEM))
+                 && MEM_P (src)))
            {
              /* This might be setting a SUBREG of a pseudo, a pseudo that is
                 also set somewhere else to a constant.  */
@@ -959,7 +937,7 @@ update_equiv_regs (void)
          note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
 
          if (note == 0 && REG_BASIC_BLOCK (regno) >= 0
-             && GET_CODE (SET_SRC (set)) == MEM
+             && MEM_P (SET_SRC (set))
              && validate_equiv_mem (insn, dest, SET_SRC (set)))
            REG_NOTES (insn) = note = gen_rtx_EXPR_LIST (REG_EQUIV, SET_SRC (set),
                                                         REG_NOTES (insn));
@@ -1004,7 +982,7 @@ update_equiv_regs (void)
                    if (REG_N_REFS (regno) == 2
                        && (rtx_equal_p (XEXP (note, 0), src)
                            || ! equiv_init_varies_p (src))
-                       && GET_CODE (insn) == INSN
+                       && NONJUMP_INSN_P (insn)
                        && equiv_init_movable_p (PATTERN (insn), regno))
                      reg_equiv[regno].replace = 1;
                }
@@ -1023,13 +1001,20 @@ update_equiv_regs (void)
   FOR_EACH_BB_REVERSE (bb)
     {
       loop_depth = bb->loop_depth;
-      for (insn = bb->end; insn != PREV_INSN (bb->head); insn = PREV_INSN (insn))
+      for (insn = BB_END (bb);
+          insn != PREV_INSN (BB_HEAD (bb));
+          insn = PREV_INSN (insn))
        {
          rtx link;
 
          if (! INSN_P (insn))
            continue;
 
+         /* Don't substitute into a non-local goto, this confuses CFG.  */
+         if (JUMP_P (insn)
+             && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+           continue;
+
          for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
            {
              if (REG_NOTE_KIND (link) == REG_DEAD
@@ -1117,8 +1102,8 @@ update_equiv_regs (void)
                      REG_N_CALLS_CROSSED (regno) = 0;
                      REG_LIVE_LENGTH (regno) = 2;
 
-                     if (insn == bb->head)
-                       bb->head = PREV_INSN (insn);
+                     if (insn == BB_HEAD (bb))
+                       BB_HEAD (bb) = PREV_INSN (insn);
 
                      /* Remember to clear REGNO from all basic block's live
                         info.  */
@@ -1143,14 +1128,17 @@ update_equiv_regs (void)
            }
        }
       else
-       EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
-         {
-           FOR_EACH_BB (bb)
-             {
-               CLEAR_REGNO_REG_SET (bb->global_live_at_start, j);
-               CLEAR_REGNO_REG_SET (bb->global_live_at_end, j);
-             }
-         });
+       {
+         reg_set_iterator rsi;
+         EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j, rsi)
+           {
+             FOR_EACH_BB (bb)
+               {
+                 CLEAR_REGNO_REG_SET (bb->global_live_at_start, j);
+                 CLEAR_REGNO_REG_SET (bb->global_live_at_end, j);
+               }
+           }
+       }
     }
 
   /* Clean up.  */
@@ -1172,7 +1160,7 @@ no_equiv (rtx reg, rtx store ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
   int regno;
   rtx list;
 
-  if (GET_CODE (reg) != REG)
+  if (!REG_P (reg))
     return;
   regno = REGNO (reg);
   list = reg_equiv[regno].init_insns;
@@ -1204,13 +1192,13 @@ block_alloc (int b)
 
   /* Count the instructions in the basic block.  */
 
-  insn = BLOCK_END (b);
+  insn = BB_END (BASIC_BLOCK (b));
   while (1)
     {
-      if (GET_CODE (insn) != NOTE)
+      if (!NOTE_P (insn))
        if (++insn_count > max_uid)
          abort ();
-      if (insn == BLOCK_HEAD (b))
+      if (insn == BB_HEAD (BASIC_BLOCK (b)))
        break;
       insn = PREV_INSN (insn);
     }
@@ -1227,10 +1215,10 @@ block_alloc (int b)
      and assigns quantities to registers.
      It computes which registers to tie.  */
 
-  insn = BLOCK_HEAD (b);
+  insn = BB_HEAD (BASIC_BLOCK (b));
   while (1)
     {
-      if (GET_CODE (insn) != NOTE)
+      if (!NOTE_P (insn))
        insn_number++;
 
       if (INSN_P (insn))
@@ -1325,14 +1313,14 @@ block_alloc (int b)
                  hard_reg = get_hard_reg_initial_reg (cfun, r1);
                  if (hard_reg != NULL_RTX)
                    {
-                     if (GET_CODE (hard_reg) == REG
+                     if (REG_P (hard_reg)
                          && IN_RANGE (REGNO (hard_reg),
                                       0, FIRST_PSEUDO_REGISTER - 1)
                          && ! call_used_regs[REGNO (hard_reg)])
                        continue;
                    }
 
-                 if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
+                 if (REG_P (r0) || GET_CODE (r0) == SUBREG)
                    {
                      /* We have two priorities for hard register preferences.
                         If we have a move insn or an insn whose first input
@@ -1341,7 +1329,7 @@ block_alloc (int b)
                      int may_save_copy
                        = (r1 == recog_data.operand[i] && must_match_0 >= 0);
 
-                     if (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
+                     if (REG_P (r1) || GET_CODE (r1) == SUBREG)
                        win = combine_regs (r1, r0, may_save_copy,
                                            insn_number, insn, 0);
                    }
@@ -1367,32 +1355,30 @@ block_alloc (int b)
          if (optimize
              && GET_CODE (PATTERN (insn)) == CLOBBER
              && (r0 = XEXP (PATTERN (insn), 0),
-                 GET_CODE (r0) == REG)
+                 REG_P (r0))
              && (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0
              && XEXP (link, 0) != 0
-             && GET_CODE (XEXP (link, 0)) == INSN
+             && NONJUMP_INSN_P (XEXP (link, 0))
              && (set = single_set (XEXP (link, 0))) != 0
              && SET_DEST (set) == r0 && SET_SRC (set) == r0
              && (note = find_reg_note (XEXP (link, 0), REG_EQUAL,
                                        NULL_RTX)) != 0)
            {
-             if (r1 = XEXP (note, 0), GET_CODE (r1) == REG
+             if (r1 = XEXP (note, 0), REG_P (r1)
                  /* Check that we have such a sequence.  */
                  && no_conflict_p (insn, r0, r1))
                win = combine_regs (r1, r0, 1, insn_number, insn, 1);
              else if (GET_RTX_FORMAT (GET_CODE (XEXP (note, 0)))[0] == 'e'
                       && (r1 = XEXP (XEXP (note, 0), 0),
-                          GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
+                          REG_P (r1) || GET_CODE (r1) == SUBREG)
                       && no_conflict_p (insn, r0, r1))
                win = combine_regs (r1, r0, 0, insn_number, insn, 1);
 
              /* Here we care if the operation to be computed is
                 commutative.  */
-             else if ((GET_CODE (XEXP (note, 0)) == EQ
-                       || GET_CODE (XEXP (note, 0)) == NE
-                       || GET_RTX_CLASS (GET_CODE (XEXP (note, 0))) == 'c')
+             else if (COMMUTATIVE_P (XEXP (note, 0))
                       && (r1 = XEXP (XEXP (note, 0), 1),
-                          (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
+                          (REG_P (r1) || GET_CODE (r1) == SUBREG))
                       && no_conflict_p (insn, r0, r1))
                win = combine_regs (r1, r0, 0, insn_number, insn, 1);
 
@@ -1419,7 +1405,7 @@ block_alloc (int b)
 
          for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
            if (REG_NOTE_KIND (link) == REG_DEAD
-               && GET_CODE (XEXP (link, 0)) == REG
+               && REG_P (XEXP (link, 0))
                && combined_regno != (int) REGNO (XEXP (link, 0))
                && (no_conflict_combined_regno != (int) REGNO (XEXP (link, 0))
                    || ! find_reg_note (insn, REG_NO_CONFLICT,
@@ -1440,14 +1426,14 @@ block_alloc (int b)
 
          for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
            if (REG_NOTE_KIND (link) == REG_UNUSED
-               && GET_CODE (XEXP (link, 0)) == REG)
+               && REG_P (XEXP (link, 0)))
              wipe_dead_reg (XEXP (link, 0), 1);
 
          /* If this is an insn that has a REG_RETVAL note pointing at a
             CLOBBER insn, we have reached the end of a REG_NO_CONFLICT
             block, so clear any register number that combined within it.  */
          if ((note = find_reg_note (insn, REG_RETVAL, NULL_RTX)) != 0
-             && GET_CODE (XEXP (note, 0)) == INSN
+             && NONJUMP_INSN_P (XEXP (note, 0))
              && GET_CODE (PATTERN (XEXP (note, 0))) == CLOBBER)
            no_conflict_combined_regno = -1;
        }
@@ -1459,7 +1445,7 @@ block_alloc (int b)
       IOR_HARD_REG_SET (regs_live_at[2 * insn_number], regs_live);
       IOR_HARD_REG_SET (regs_live_at[2 * insn_number + 1], regs_live);
 
-      if (insn == BLOCK_END (b))
+      if (insn == BB_END (BASIC_BLOCK (b)))
        break;
 
       insn = NEXT_INSN (insn);
@@ -1738,18 +1724,18 @@ qty_sugg_compare_1 (const void *q1p, const void *q2p)
 
    Combining registers means marking them as having the same quantity
    and adjusting the offsets within the quantity if either of
-   them is a SUBREG).
+   them is a SUBREG.
 
    We don't actually combine a hard reg with a pseudo; instead
    we just record the hard reg as the suggestion for the pseudo's quantity.
    If we really combined them, we could lose if the pseudo lives
-   across an insn that clobbers the hard reg (eg, movstr).
+   across an insn that clobbers the hard reg (eg, movmem).
 
    ALREADY_DEAD is nonzero if USEDREG is known to be dead even though
    there is no REG_DEAD note on INSN.  This occurs during the processing
    of REG_NO_CONFLICT blocks.
 
-   MAY_SAVE_COPYCOPY is nonzero if this insn is simply copying USEDREG to
+   MAY_SAVE_COPY is nonzero if this insn is simply copying USEDREG to
    SETREG or if the input and output must share a register.
    In that case, we record a hard reg suggestion in QTY_PHYS_COPY_SUGG.
 
@@ -1772,7 +1758,7 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
     {
       rtx subreg = SUBREG_REG (usedreg);
 
-      if (GET_CODE (subreg) == REG)
+      if (REG_P (subreg))
        {
          if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
            may_save_copy = 0;
@@ -1790,12 +1776,12 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
       usedreg = subreg;
     }
 
-  if (GET_CODE (usedreg) != REG)
+  if (!REG_P (usedreg))
     return 0;
 
   ureg = REGNO (usedreg);
   if (ureg < FIRST_PSEUDO_REGISTER)
-    usize = HARD_REGNO_NREGS (ureg, GET_MODE (usedreg));
+    usize = hard_regno_nregs[ureg][GET_MODE (usedreg)];
   else
     usize = ((GET_MODE_SIZE (GET_MODE (usedreg))
              + (REGMODE_NATURAL_SIZE (GET_MODE (usedreg)) - 1))
@@ -1805,7 +1791,7 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
     {
       rtx subreg = SUBREG_REG (setreg);
 
-      if (GET_CODE (subreg) == REG)
+      if (REG_P (subreg))
        {
          if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
            may_save_copy = 0;
@@ -1823,12 +1809,12 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
       setreg = subreg;
     }
 
-  if (GET_CODE (setreg) != REG)
+  if (!REG_P (setreg))
     return 0;
 
   sreg = REGNO (setreg);
   if (sreg < FIRST_PSEUDO_REGISTER)
-    ssize = HARD_REGNO_NREGS (sreg, GET_MODE (setreg));
+    ssize = hard_regno_nregs[sreg][GET_MODE (setreg)];
   else
     ssize = ((GET_MODE_SIZE (GET_MODE (setreg))
              + (REGMODE_NATURAL_SIZE (GET_MODE (setreg)) - 1))
@@ -2003,7 +1989,7 @@ reg_is_set (rtx reg, rtx setter, void *data ATTRIBUTE_UNUSED)
      a hard register.  These may actually not exist any more.  */
 
   if (GET_CODE (reg) != SUBREG
-      && GET_CODE (reg) != REG)
+      && !REG_P (reg))
     return;
 
   /* Mark this register as being born.  If it is used in a CLOBBER, mark
@@ -2079,7 +2065,7 @@ wipe_dead_reg (rtx reg, int output_p)
        {
          rtx set = XVECEXP (PATTERN (this_insn), 0, i);
          if (GET_CODE (set) == SET
-             && GET_CODE (SET_DEST (set)) != REG
+             && !REG_P (SET_DEST (set))
              && !rtx_equal_p (reg, SET_DEST (set))
              && reg_overlap_mentioned_p (reg, SET_DEST (set)))
            output_p = 1;
@@ -2213,7 +2199,7 @@ find_free_reg (enum reg_class class, enum machine_mode mode, int qtyno,
              || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
        {
          int j;
-         int size1 = HARD_REGNO_NREGS (regno, mode);
+         int size1 = hard_regno_nregs[regno][mode];
          for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, regno + j); j++);
          if (j == size1)
            {
@@ -2271,7 +2257,7 @@ find_free_reg (enum reg_class class, enum machine_mode mode, int qtyno,
 static void
 mark_life (int regno, enum machine_mode mode, int life)
 {
-  int j = HARD_REGNO_NREGS (regno, mode);
+  int j = hard_regno_nregs[regno][mode];
   if (life)
     while (--j >= 0)
       SET_HARD_REG_BIT (regs_live, regno + j);
@@ -2288,12 +2274,8 @@ static void
 post_mark_life (int regno, enum machine_mode mode, int life, int birth,
                int death)
 {
-  int j = HARD_REGNO_NREGS (regno, mode);
-#ifdef HARD_REG_SET
-  /* Declare it register if it's a scalar.  */
-  register
-#endif
-    HARD_REG_SET this_reg;
+  int j = hard_regno_nregs[regno][mode];
+  HARD_REG_SET this_reg;
 
   CLEAR_HARD_REG_SET (this_reg);
   while (--j >= 0)
@@ -2333,8 +2315,8 @@ no_conflict_p (rtx insn, rtx r0 ATTRIBUTE_UNUSED, rtx r1)
      when we scan the insns that actually use it.  */
 
   if (note == 0
-      || (GET_CODE (r1) == REG && REGNO (r1) < FIRST_PSEUDO_REGISTER)
-      || (GET_CODE (r1) == SUBREG && GET_CODE (SUBREG_REG (r1)) == REG
+      || (REG_P (r1) && REGNO (r1) < FIRST_PSEUDO_REGISTER)
+      || (GET_CODE (r1) == SUBREG && REG_P (SUBREG_REG (r1))
          && REGNO (SUBREG_REG (r1)) < FIRST_PSEUDO_REGISTER))
     return 0;
 
@@ -2412,7 +2394,7 @@ requires_inout (const char *p)
          if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS
              && !EXTRA_ADDRESS_CONSTRAINT (c, p))
            break;
-         /* FALLTHRU */
+         /* Fall through.  */
        case 'p':
        case 'g': case 'r':
          reg_allowed = 1;