]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/reload.c
(make_insn_raw): Eliminate unused argument pat_formals. All calls changed.
[gcc.git] / gcc / reload.c
index a1415c2268cf1a3e199f35d2f0af0b211f9dcf58..3dfcb2db04eb7f2faa5f9bbbd97ce52cebb6568e 100644 (file)
@@ -207,6 +207,17 @@ static int n_replacements;
 static rtx memlocs[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
 static int n_memlocs;
 
+#ifdef SECONDARY_MEMORY_NEEDED
+
+/* Save MEMs needed to copy from one class of registers to another.  One MEM
+   is used per mode, but normally only one or two modes are ever used.  
+
+   We keep two versions, before and after register elimination.  */
+
+static rtx secondary_memlocs[NUM_MACHINE_MODES];
+static rtx secondary_memlocs_elim[NUM_MACHINE_MODES];
+#endif
+
 /* The instruction we are doing reloads for;
    so we can test whether a register dies in it.  */
 static rtx this_insn;
@@ -369,6 +380,73 @@ find_secondary_reload (x, reload_class, reload_mode, in_p, picode, pmode,
 }
 #endif /* HAVE_SECONDARY_RELOADS */
 \f
+#ifdef SECONDARY_MEMORY_NEEDED
+
+/* Return a memory location that will be used to copy X in mode MODE.  
+   If we haven't already made a location for this mode in this insn,
+   call find_reloads_address on the location being returned.  */
+
+rtx
+get_secondary_mem (x, mode)
+     rtx x;
+     enum machine_mode mode;
+{
+  rtx loc;
+  int mem_valid;
+
+  /* If MODE is narrower than a word, widen it.  This is required because
+     most machines that require these memory locations do not support
+     short load and stores from all registers (e.g., FP registers).  We could
+     possibly conditionalize this, but we lose nothing by doing the wider
+     mode.  */
+
+  if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
+    mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
+
+  /* If we already have made a MEM for this insn, return it.  */
+  if (secondary_memlocs_elim[(int) mode] != 0)
+    return secondary_memlocs_elim[(int) mode];
+
+  /* If this is the first time we've tried to get a MEM for this mode, 
+     allocate a new one.  `something_changed' in reload will get set
+     by noticing that the frame size has changed.  */
+
+  if (secondary_memlocs[(int) mode] == 0)
+    secondary_memlocs[(int) mode]
+      = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
+
+  /* Get a version of the address doing any eliminations needed.  If that
+     didn't give us a new MEM, make a new one if it isn't valid.  */
+
+  loc = eliminate_regs (secondary_memlocs[(int) mode], 0, NULL_RTX);
+  mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
+
+  if (! mem_valid && loc == secondary_memlocs[(int) mode])
+    loc = copy_rtx (loc);
+
+  /* The only time the call below will do anything is if the stack
+     offset is too large.  In that case IND_LEVELS doesn't matter, so we
+     can just pass a zero.  */
+  if (! mem_valid)
+    find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0), x, 0);
+
+  secondary_memlocs_elim[(int) mode] = loc;
+
+  return loc;
+}
+
+/* Clear any secondary memory locations we've made.  */
+
+void
+clear_secondary_mem ()
+{
+  int i;
+
+  for (i = 0; i < NUM_MACHINE_MODES; i++)
+    secondary_memlocs[i] = 0;
+}
+#endif /* SECONDARY_MEMORY_NEEDED */
+\f
 /* Record one (sometimes two) reload that needs to be performed.
    IN is an rtx saying where the data are to be found before this instruction.
    OUT says where they must be stored after the instruction.
@@ -476,7 +554,10 @@ push_reload (in, out, inloc, outloc, class,
      we can't handle it here because CONST_INT does not indicate a mode.
 
      Similarly, we must reload the inside expression if we have a
-     STRICT_LOW_PART (presumably, in == out in the cas).  */
+     STRICT_LOW_PART (presumably, in == out in the cas).
+
+     Also reload the inner expression if it does not require a secondary
+     reload but the SUBREG does.  */
 
   if (in != 0 && GET_CODE (in) == SUBREG
       && (GET_CODE (SUBREG_REG (in)) != REG
@@ -494,7 +575,15 @@ push_reload (in, out, inloc, outloc, class,
                      && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
                           / UNITS_PER_WORD)
                          != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
-                                              GET_MODE (SUBREG_REG (in)))))))))
+                                              GET_MODE (SUBREG_REG (in)))))))
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+         || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
+             && (SECONDARY_INPUT_RELOAD_CLASS (class,
+                                               GET_MODE (SUBREG_REG (in)),
+                                               SUBREG_REG (in))
+                 == NO_REGS))
+#endif
+         ))
     {
       in_subreg_loc = inloc;
       inloc = &SUBREG_REG (in);
@@ -529,7 +618,15 @@ push_reload (in, out, inloc, outloc, class,
                      && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
                           / UNITS_PER_WORD)
                          != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
-                                              GET_MODE (SUBREG_REG (out)))))))))
+                                              GET_MODE (SUBREG_REG (out)))))))
+#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+         || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
+             && (SECONDARY_OUTPUT_RELOAD_CLASS (class,
+                                                GET_MODE (SUBREG_REG (out)),
+                                                SUBREG_REG (out))
+                 == NO_REGS))
+#endif
+         ))
     {
       out_subreg_loc = outloc;
       outloc = &SUBREG_REG (out);
@@ -547,14 +644,35 @@ push_reload (in, out, inloc, outloc, class,
   /* If IN appears in OUT, we can't share any input-only reload for IN.  */
   if (in != 0 && out != 0 && GET_CODE (out) == MEM
       && (GET_CODE (in) == REG || GET_CODE (in) == MEM)
-      && reg_overlap_mentioned_p (in, XEXP (out, 0)))
+      && reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
     dont_share = 1;
 
+  /* If IN is a SUBREG of a hard register, make a new REG.  This
+     simplifies some of the cases below.  */
+
+  if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
+      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
+    in = gen_rtx (REG, GET_MODE (in),
+                 REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
+
+  /* Similarly for OUT.  */
+  if (out != 0 && GET_CODE (out) == SUBREG
+      && GET_CODE (SUBREG_REG (out)) == REG
+      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
+    out = gen_rtx (REG, GET_MODE (out),
+                 REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
+
   /* Narrow down the class of register wanted if that is
      desirable on this machine for efficiency.  */
   if (in != 0)
     class = PREFERRED_RELOAD_CLASS (in, class);
 
+  /* Output reloads may need analagous treatment, different in detail.  */
+#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
+  if (out != 0)
+    class = PREFERRED_OUTPUT_RELOAD_CLASS (out, class);
+#endif
+
   /* Make sure we use a class that can handle the actual pseudo
      inside any subreg.  For example, on the 386, QImode regs
      can appear within SImode subregs.  Although GENERAL_REGS
@@ -709,8 +827,8 @@ push_reload (in, out, inloc, outloc, class,
              || secondary_icode != CODE_FOR_nothing
              || secondary_out_icode != CODE_FOR_nothing))
        {
-         push_reload (0, out, 0, outloc, class, VOIDmode, outmode,
-                      strict_low, optional, needed_for);
+         push_reload (NULL_RTX, out, NULL_PTR, outloc, class,
+                      VOIDmode, outmode, strict_low, optional, needed_for);
          out = 0;
          outloc = 0;
          outmode = VOIDmode;
@@ -839,6 +957,19 @@ push_reload (in, out, inloc, outloc, class,
 
              n_reloads++;
              i = n_reloads;
+
+#ifdef SECONDARY_MEMORY_NEEDED
+             /* If we need a memory location to copy between the two
+                reload regs, set it up now.  */
+
+             if (in != 0 && secondary_icode == CODE_FOR_nothing
+                 && SECONDARY_MEMORY_NEEDED (secondary_class, class, inmode))
+               get_secondary_mem (in, inmode);
+
+             if (out != 0 && secondary_icode == CODE_FOR_nothing
+                 && SECONDARY_MEMORY_NEEDED (class, secondary_class, outmode))
+               get_secondary_mem (out, outmode);
+#endif
            }
        }
 #endif
@@ -864,6 +995,21 @@ push_reload (in, out, inloc, outloc, class,
       reload_secondary_p[i] = 0;
 
       n_reloads++;
+
+#ifdef SECONDARY_MEMORY_NEEDED
+      /* If a memory location is needed for the copy, make one.  */
+      if (in != 0 && GET_CODE (in) == REG
+         && REGNO (in) < FIRST_PSEUDO_REGISTER
+         && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
+                                    class, inmode))
+       get_secondary_mem (in, inmode);
+
+      if (out != 0 && GET_CODE (out) == REG
+         && REGNO (out) < FIRST_PSEUDO_REGISTER
+         && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)),
+                                     outmode))
+       get_secondary_mem (out, outmode);
+#endif
     }
   else
     {
@@ -1104,8 +1250,8 @@ combine_reloads ()
            /* Args reversed because the first arg seems to be
               the one that we imagine being modified
               while the second is the one that might be affected.  */
-           || (! reg_overlap_mentioned_p (reload_out[output_reload],
-                                          reload_in[i])
+           || (! reg_overlap_mentioned_for_reload_p (reload_out[output_reload],
+                                                     reload_in[i])
                /* However, if the input is a register that appears inside
                   the output, then we also can't share.
                   Imagine (set (mem (reg 69)) (plus (reg 69) ...)).
@@ -1113,8 +1259,8 @@ combine_reloads ()
                   result to be stored in memory, then that result
                   will clobber the address of the memory ref.  */
                && ! (GET_CODE (reload_in[i]) == REG
-                     && reg_overlap_mentioned_p (reload_in[i],
-                                                 reload_out[output_reload])))))
+                     && reg_overlap_mentioned_for_reload_p (reload_in[i],
+                                                            reload_out[output_reload])))))
       {
        int j;
 
@@ -1162,8 +1308,8 @@ combine_reloads ()
   for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
     if (REG_NOTE_KIND (note) == REG_DEAD
        && GET_CODE (XEXP (note, 0)) == REG
-       && ! reg_overlap_mentioned_p (XEXP (note, 0),
-                                     reload_out[output_reload])
+       && ! reg_overlap_mentioned_for_reload_p (XEXP (note, 0),
+                                                reload_out[output_reload])
        && REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
        && HARD_REGNO_MODE_OK (REGNO (XEXP (note, 0)), reload_outmode[output_reload])
        && TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[output_reload]],
@@ -1292,7 +1438,7 @@ find_dummy_reload (real_in, real_out, inloc, outloc, class, for_real)
       register int regno = REGNO (in) + in_offset;
       int nwords = HARD_REGNO_NREGS (regno, GET_MODE (real_in));
 
-      if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, 0)
+      if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, NULL_PTR)
          && ! hard_reg_set_here_p (regno, regno + nwords,
                                    PATTERN (this_insn)))
        {
@@ -1472,6 +1618,11 @@ operands_match_p (x, y)
       int val;
       switch (fmt[i])
        {
+       case 'w':
+         if (XWINT (x, i) != XWINT (y, i))
+           return 0;
+         break;
+
        case 'i':
          if (XINT (x, i) != XINT (y, i))
            return 0;
@@ -1502,7 +1653,7 @@ operands_match_p (x, y)
 \f
 /* Return the number of times character C occurs in string S.  */
 
-static int
+int
 n_occurrences (c, s)
      char c;
      char *s;
@@ -1518,8 +1669,8 @@ struct decomposition
   int reg_flag;
   int safe;
   rtx base;
-  int start;
-  int end;
+  HOST_WIDE_INT start;
+  HOST_WIDE_INT end;
 };
 
 /* Describe the range of registers or memory referenced by X.
@@ -1662,7 +1813,7 @@ immune_p (x, y, ydata)
   struct decomposition xdata;
 
   if (ydata.reg_flag)
-    return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, 0);
+    return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, NULL_PTR);
   if (ydata.safe)
     return 1;
 
@@ -1696,7 +1847,7 @@ immune_p (x, y, ydata)
   return (xdata.start >= ydata.end || ydata.start >= xdata.end);
 }
 
-/* Similiar, but calls decompose.  */
+/* Similar, but calls decompose.  */
 
 int
 safe_from_earlyclobber (op, clobber)
@@ -1805,6 +1956,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
     no_output_reloads = 1;
 #endif
      
+#ifdef SECONDARY_MEMORY_NEEDED
+  /* The eliminated forms of any secondary memory locations are per-insn, so
+     clear them out here.  */
+
+  bzero (secondary_memlocs_elim, sizeof secondary_memlocs_elim);
+#endif
+
   /* Find what kind of insn this is.  NOPERANDS gets number of operands.
      Make OPERANDS point to a vector of operand values.
      Make OPERAND_LOCS point to a vector of pointers to
@@ -1913,13 +2071,17 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       while (c = *p++)
        if (c == '%')
          {
-           /* The last operand should not be marked commutative.  This
-              problem is hard to detect, so make it obvious by calling
-              abort here.  */
+           /* The last operand should not be marked commutative.  */
            if (i == noperands - 1)
-             abort ();
-
-           commutative = i;
+             {
+               if (this_insn_is_asm)
+                 warning_for_asm (this_insn,
+                                  "`%%' constraint used with last operand");
+               else
+                 abort ();
+             }
+           else
+             commutative = i;
          }
        else if (c >= '0' && c <= '9')
          {
@@ -1966,7 +2128,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
       if (constraints[i][0] == 'p')
        {
-         find_reloads_address (VOIDmode, 0,
+         find_reloads_address (VOIDmode, NULL_PTR,
                                recog_operand[i], recog_operand_loc[i],
                                recog_operand[i], ind_levels);
          substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
@@ -2041,7 +2203,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
           ? reg_preferred_class (REGNO (recog_operand[i])) : NO_REGS);
       pref_or_nothing[i]
        = (code == REG && REGNO (recog_operand[i]) > FIRST_PSEUDO_REGISTER
-          && reg_preferred_or_nothing (REGNO (recog_operand[i])));
+          && reg_alternate_class (REGNO (recog_operand[i])) == NO_REGS);
     }
 
   /* If this is simply a copy from operand 1 to operand 0, merge the
@@ -2339,7 +2501,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                /* Match any floating double constant, but only if
                   we can examine the bits of it reliably.  */
                if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-                    || HOST_BITS_PER_INT != BITS_PER_WORD)
+                    || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
                    && GET_MODE (operand) != VOIDmode && ! flag_pretend_float)
                  break;
                if (GET_CODE (operand) == CONST_DOUBLE)
@@ -2786,10 +2948,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                 && GET_CODE (recog_operand[i]) == MEM)
          {
            operand_reloadnum[i]
-             = push_reload (XEXP (recog_operand[i], 0), 0,
-                            &XEXP (recog_operand[i], 0), 0,
+             = push_reload (XEXP (recog_operand[i], 0), NULL_RTX,
+                            &XEXP (recog_operand[i], 0), NULL_PTR,
                             BASE_REG_CLASS, GET_MODE (XEXP (recog_operand[i], 0)),
-                            VOIDmode, 0, 0, 0);
+                            VOIDmode, 0, 0, NULL_RTX);
            reload_inc[operand_reloadnum[i]]
              = GET_MODE_SIZE (GET_MODE (recog_operand[i]));
          }
@@ -2804,7 +2966,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                         (modified[i] == RELOAD_READ ? VOIDmode : operand_mode[i]),
                         (insn_code_number < 0 ? 0
                          : insn_operand_strict_low[insn_code_number][i]),
-                        0, 0);
+                        0, NULL_RTX);
        /* In a matching pair of operands, one must be input only
           and the other must be output only.
           Pass the input operand as IN and the other as OUT.  */
@@ -2819,7 +2981,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                             (enum reg_class) goal_alternative[i],
                             operand_mode[i],
                             operand_mode[goal_alternative_matched[i]],
-                            0, 0, 0);
+                            0, 0, NULL_RTX);
            operand_reloadnum[goal_alternative_matched[i]] = output_reloadnum;
          }
        else if (modified[i] == RELOAD_WRITE
@@ -2833,7 +2995,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                             (enum reg_class) goal_alternative[i],
                             operand_mode[goal_alternative_matched[i]],
                             operand_mode[i],
-                            0, 0, 0);
+                            0, 0, NULL_RTX);
            operand_reloadnum[i] = output_reloadnum;
          }
        else if (insn_code_number >= 0)
@@ -2877,7 +3039,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                           (modified[i] == RELOAD_READ ? VOIDmode : operand_mode[i]),
                           (insn_code_number < 0 ? 0
                            : insn_operand_strict_low[insn_code_number][i]),
-                          1, 0);
+                          1, NULL_RTX);
        /* Make an optional reload for an explicit mem ref.  */
        else if (GET_CODE (operand) == MEM
                 && (enum reg_class) goal_alternative[i] != NO_REGS
@@ -2895,7 +3057,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                           (modified[i] == RELOAD_READ ? VOIDmode : operand_mode[i]),
                           (insn_code_number < 0 ? 0
                            : insn_operand_strict_low[insn_code_number][i]),
-                          1, 0);
+                          1, NULL_RTX);
        else
          non_reloaded_operands[n_non_reloaded_operands++] = recog_operand[i];
       }
@@ -2996,7 +3158,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
          /* Now get the operand values out of the insn.  */
 
-         decode_asm_operands (body, recog_operand, recog_operand_loc, 0, 0);
+         decode_asm_operands (body, recog_operand, recog_operand_loc,
+                              NULL_PTR, NULL_PTR);
          break;
        }
 
@@ -3019,7 +3182,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
       if (insn_code_number >= 0)
        if (insn_operand_address_p[insn_code_number][i])
-         find_reloads_address (VOIDmode, 0,
+         find_reloads_address (VOIDmode, NULL_PTR,
                                recog_operand[i], recog_operand_loc[i],
                                recog_operand[i], ind_levels);
       if (code == MEM)
@@ -3187,7 +3350,7 @@ find_reloads_toplev (x, ind_levels, is_set_dest)
 
          x = gen_rtx (MEM, GET_MODE (x), addr);
          RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
-         find_reloads_address (GET_MODE (x), 0,
+         find_reloads_address (GET_MODE (x), NULL_PTR,
                                XEXP (x, 0),
                                &XEXP (x, 0), x, ind_levels);
        }
@@ -3270,7 +3433,7 @@ find_reloads_toplev (x, ind_levels, is_set_dest)
          addr = plus_constant (addr, offset);
          x = gen_rtx (MEM, GET_MODE (x), addr);
          RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
-         find_reloads_address (GET_MODE (x), 0,
+         find_reloads_address (GET_MODE (x), NULL_PTR,
                                XEXP (x, 0),
                                &XEXP (x, 0), x, ind_levels);
        }
@@ -3358,9 +3521,9 @@ find_reloads_address (mode, memrefloc, ad, loc, operand, ind_levels)
       else if (reg_equiv_address[regno] != 0)
        {
          tem = make_memloc (ad, regno);
-         find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
+         find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
                                &XEXP (tem, 0), operand, ind_levels);
-         push_reload (tem, 0, loc, 0, BASE_REG_CLASS,
+         push_reload (tem, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
                       GET_MODE (ad), VOIDmode, 0, 0,
                       operand);
          return 1;
@@ -3395,7 +3558,7 @@ find_reloads_address (mode, memrefloc, ad, loc, operand, ind_levels)
        return 0;
 
       /* If we do not have one of the cases above, we must do the reload.  */
-      push_reload (ad, 0, loc, 0, BASE_REG_CLASS,
+      push_reload (ad, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
                   GET_MODE (ad), VOIDmode, 0, 0, operand);
       return 1;
     }
@@ -3454,7 +3617,7 @@ find_reloads_address (mode, memrefloc, ad, loc, operand, ind_levels)
        {
          /* Must use TEM here, not AD, since it is the one that will
             have any subexpressions reloaded, if needed.  */
-         push_reload (tem, 0, loc, 0,
+         push_reload (tem, NULL_RTX, loc, NULL_PTR,
                       BASE_REG_CLASS, GET_MODE (tem), VOIDmode, 0,
                       0, operand);
          return 1;
@@ -3909,7 +4072,7 @@ find_reloads_address_1 (x, context, loc, operand, ind_levels)
              register rtx link;
 
              int reloadnum
-               = push_reload (x, 0, loc, 0,
+               = push_reload (x, NULL_RTX, loc, NULL_PTR,
                               context ? INDEX_REG_CLASS : BASE_REG_CLASS,
                               GET_MODE (x), GET_MODE (x), VOIDmode, 0, operand);
              reload_inc[reloadnum]
@@ -3949,7 +4112,7 @@ find_reloads_address_1 (x, context, loc, operand, ind_levels)
                                XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
                                operand, ind_levels);
 
-         reloadnum = push_reload (x, 0, loc, 0,
+         reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR,
                                   context ? INDEX_REG_CLASS : BASE_REG_CLASS,
                                   GET_MODE (x), VOIDmode, 0, 0, operand);
          reload_inc[reloadnum]
@@ -3979,7 +4142,7 @@ find_reloads_address_1 (x, context, loc, operand, ind_levels)
       find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
                            operand, ind_levels);
 
-      push_reload (*loc, 0, loc, 0,
+      push_reload (*loc, NULL_RTX, loc, NULL_PTR,
                   context ? INDEX_REG_CLASS : BASE_REG_CLASS,
                   GET_MODE (x), VOIDmode, 0, 0, operand);
       return 1;
@@ -3990,7 +4153,7 @@ find_reloads_address_1 (x, context, loc, operand, ind_levels)
 
       if (reg_equiv_constant[regno] != 0)
        {
-         push_reload (reg_equiv_constant[regno], 0, loc, 0,
+         push_reload (reg_equiv_constant[regno], NULL_RTX, loc, NULL_PTR,
                       context ? INDEX_REG_CLASS : BASE_REG_CLASS,
                       GET_MODE (x), VOIDmode, 0, 0, operand);
          return 1;
@@ -4000,7 +4163,7 @@ find_reloads_address_1 (x, context, loc, operand, ind_levels)
         that feeds this insn.  */
       if (reg_equiv_mem[regno] != 0)
        {
-         push_reload (reg_equiv_mem[regno], 0, loc, 0,
+         push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR,
                       context ? INDEX_REG_CLASS : BASE_REG_CLASS,
                       GET_MODE (x), VOIDmode, 0, 0, operand);
          return 1;
@@ -4019,7 +4182,7 @@ find_reloads_address_1 (x, context, loc, operand, ind_levels)
           || !(context ? REGNO_OK_FOR_INDEX_P (regno)
                : REGNO_OK_FOR_BASE_P (regno))))
        {
-         push_reload (x, 0, loc, 0,
+         push_reload (x, NULL_RTX, loc, NULL_PTR,
                       context ? INDEX_REG_CLASS : BASE_REG_CLASS,
                       GET_MODE (x), VOIDmode, 0, 0, operand);
          return 1;
@@ -4031,7 +4194,7 @@ find_reloads_address_1 (x, context, loc, operand, ind_levels)
         from before this insn to after it.  */
       if (regno_clobbered_p (regno, this_insn))
        {
-         push_reload (x, 0, loc, 0,
+         push_reload (x, NULL_RTX, loc, NULL_PTR,
                       context ? INDEX_REG_CLASS : BASE_REG_CLASS,
                       GET_MODE (x), VOIDmode, 0, 0, operand);
          return 1;
@@ -4097,7 +4260,8 @@ find_reloads_address_part (x, loc, class, mode, needed_for, ind_levels)
                            needed_for, ind_levels);
     }
 
-  push_reload (x, 0, loc, 0, class, mode, VOIDmode, 0, 0, needed_for);
+  push_reload (x, NULL_RTX, loc, NULL_PTR, class,
+              mode, VOIDmode, 0, 0, needed_for);
 }
 \f
 /* Substitute into X the registers into which we have reloaded
@@ -4260,15 +4424,20 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
     case REG:
       i = REGNO (x);
 
-      if (i >= FIRST_PSEUDO_REGISTER && reg_renumber[i] == -1
-         && ((reg_equiv_address[i]
-              && refers_to_regno_for_reload_p (regno, endregno,
-                                               reg_equiv_address[i], 0))
-             || (reg_equiv_mem[i]
-                 && refers_to_regno_for_reload_p (regno, endregno,
-                                                  XEXP (reg_equiv_mem[i], 0),
-                                                  0))))
-       return 1;
+      /* If this is a pseudo, a hard register must not have been allocated.
+        X must therefore either be a constant or be in memory.  */
+      if (i >= FIRST_PSEUDO_REGISTER)
+       {
+         if (reg_equiv_memory_loc[i])
+           return refers_to_regno_for_reload_p (regno, endregno,
+                                                reg_equiv_memory_loc[i],
+                                                NULL_PTR);
+
+         if (reg_equiv_constant[i])
+           return 0;
+
+         abort ();
+       }
 
       return (endregno > i
              && regno < i + (i < FIRST_PSEUDO_REGISTER 
@@ -4343,6 +4512,86 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
     }
   return 0;
 }
+
+/* Nonzero if modifying X will affect IN.  If X is a register or a SUBREG,
+   we check if any register number in X conflicts with the relevant register
+   numbers.  If X is a constant, return 0.  If X is a MEM, return 1 iff IN
+   contains a MEM (we don't bother checking for memory addresses that can't
+   conflict because we expect this to be a rare case. 
+
+   This function is similar to reg_overlap_mention_p in rtlanal.c except
+   that we look at equivalences for pseudos that didn't get hard registers.  */
+
+int
+reg_overlap_mentioned_for_reload_p (x, in)
+     rtx x, in;
+{
+  int regno, endregno;
+
+  if (GET_CODE (x) == SUBREG)
+    {
+      regno = REGNO (SUBREG_REG (x));
+      if (regno < FIRST_PSEUDO_REGISTER)
+       regno += SUBREG_WORD (x);
+    }
+  else if (GET_CODE (x) == REG)
+    {
+      regno = REGNO (x);
+
+      /* If this is a pseudo, it must not have been assigned a hard register.
+        Therefore, it must either be in memory or be a constant.  */
+
+      if (regno >= FIRST_PSEUDO_REGISTER)
+       {
+         if (reg_equiv_memory_loc[regno])
+           return refers_to_mem_for_reload_p (in);
+         else if (reg_equiv_constant[regno])
+           return 0;
+         abort ();
+       }
+    }
+  else if (CONSTANT_P (x))
+    return 0;
+  else if (GET_CODE (x) == MEM)
+    return refers_to_mem_for_reload_p (in);
+  else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
+          || GET_CODE (x) == CC0)
+    return reg_mentioned_p (x, in);
+  else
+    abort ();
+
+  endregno = regno + (regno < FIRST_PSEUDO_REGISTER
+                     ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+
+  return refers_to_regno_for_reload_p (regno, endregno, in, NULL_PTR);
+}
+
+/* Return nonzero if anything in X contains a MEM.  Look also for pseudo
+   registers.  */
+
+int
+refers_to_mem_for_reload_p (x)
+     rtx x;
+{
+  char *fmt;
+  int i;
+
+  if (GET_CODE (x) == MEM)
+    return 1;
+
+  if (GET_CODE (x) == REG)
+    return (REGNO (x) >= FIRST_PSEUDO_REGISTER
+           && reg_equiv_memory_loc[REGNO (x)]);
+                       
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    if (fmt[i] == 'e'
+       && (GET_CODE (XEXP (x, i)) == MEM
+           || refers_to_mem_for_reload_p (XEXP (x, i))))
+      return 1;
+  
+  return 0;
+}
 \f
 #if 0
 
@@ -4536,10 +4785,12 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                  /* If we are looking for a constant,
                     and something equivalent to that constant was copied
                     into a reg, we can use that reg.  */
-                 || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0))
+                 || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
+                                                         NULL_RTX))
                      && rtx_equal_p (XEXP (tem, 0), goal)
                      && (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0)
-                 || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0))
+                 || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
+                                                         NULL_RTX))
                      && GET_CODE (SET_DEST (pat)) == REG
                      && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                      && GET_MODE_CLASS (GET_MODE (XEXP (tem, 0))) == MODE_FLOAT
@@ -4548,7 +4799,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                      && (valtry = operand_subword (SET_DEST (pat), 0, 0,
                                                    VOIDmode))
                      && (valueno = true_regnum (valtry)) >= 0)
-                 || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0))
+                 || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
+                                                         NULL_RTX))
                      && GET_CODE (SET_DEST (pat)) == REG
                      && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                      && GET_MODE_CLASS (GET_MODE (XEXP (tem, 0))) == MODE_FLOAT
@@ -4584,7 +4836,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
   /* If we propose to get the value from the stack pointer or if GOAL is
      a MEM based on the stack pointer, we need a stable SP.  */
   if (valueno == STACK_POINTER_REGNUM
-      || (goal_mem && reg_overlap_mentioned_p (stack_pointer_rtx, goal)))
+      || (goal_mem && reg_overlap_mentioned_for_reload_p (stack_pointer_rtx,
+                                                         goal)))
     need_stable_sp = 1;
 
   /* Reject VALUE if the copy-insn moved the wrong sort of datum.  */
@@ -4595,9 +4848,10 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
      and is also a register that appears in the address of GOAL.  */
 
   if (goal_mem && value == SET_DEST (PATTERN (where))
-      && refers_to_regno_p (valueno,
-                           valueno + HARD_REGNO_NREGS (valueno, mode),
-                           goal, 0))
+      && refers_to_regno_for_reload_p (valueno,
+                                      (valueno
+                                       + HARD_REGNO_NREGS (valueno, mode)),
+                                      goal, NULL_PTR))
     return 0;
 
   /* Reject registers that overlap GOAL.  */
@@ -4710,7 +4964,7 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                      && xregno + xnregs > valueno)
                    return 0;
                  if (goal_mem_addr_varies
-                     && reg_overlap_mentioned_p (dest, goal))
+                     && reg_overlap_mentioned_for_reload_p (dest, goal))
                    return 0;
                }
              else if (goal_mem && GET_CODE (dest) == MEM
@@ -4748,7 +5002,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                              && xregno + xnregs > valueno)
                            return 0;
                          if (goal_mem_addr_varies
-                             && reg_overlap_mentioned_p (dest, goal))
+                             && reg_overlap_mentioned_for_reload_p (dest,
+                                                                    goal))
                            return 0;
                        }
                      else if (goal_mem && GET_CODE (dest) == MEM
@@ -4779,7 +5034,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                  if (incno < valueno + valuenregs && incno >= valueno)
                    return 0;
                  if (goal_mem_addr_varies
-                     && reg_overlap_mentioned_p (XEXP (link, 0), goal))
+                     && reg_overlap_mentioned_for_reload_p (XEXP (link, 0),
+                                                            goal))
                    return 0;
                }
          }
This page took 0.055012 seconds and 5 git commands to generate.