OSDN Git Service

* target-def.h: Remove usage of OBJECT_FORMAT_ROSE.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 7ab823d..9b1b148 100644 (file)
@@ -105,10 +105,6 @@ a register with any other reload.  */
 #include "function.h"
 #include "toplev.h"
 
-#ifndef REGISTER_MOVE_COST
-#define REGISTER_MOVE_COST(m, x, y) 2
-#endif
-
 #ifndef REGNO_MODE_OK_FOR_BASE_P
 #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
 #endif
@@ -840,6 +836,56 @@ reload_inner_reg_of_subreg (x, mode, output)
              != (int) HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
 }
 
+/* Return nonzero if IN can be reloaded into REGNO with mode MODE without
+   requiring an extra reload register.  The caller has already found that
+   IN contains some reference to REGNO, so check that we can produce the
+   new value in a single step.  E.g. if we have
+   (set (reg r13) (plus (reg r13) (const int 1))), and there is an
+   instruction that adds one to a register, this should succeed.
+   However, if we have something like
+   (set (reg r13) (plus (reg r13) (const int 999))), and the constant 999
+   needs to be loaded into a register first, we need a separate reload
+   register.
+   Such PLUS reloads are generated by find_reload_address_part.
+   The out-of-range PLUS expressions are usually introduced in the instruction
+   patterns by register elimination and substituting pseudos without a home
+   by their function-invariant equivalences.  */
+static int
+can_reload_into (rtx in, int regno, enum machine_mode mode)
+{
+  rtx dst, test_insn;
+  int r = 0;
+  struct recog_data save_recog_data;
+
+  /* For matching constraints, we often get notional input reloads where
+     we want to use the original register as the reload register.  I.e.
+     technically this is a non-optional input-output reload, but IN is
+     already a valid register, and has been chosen as the reload register.
+     Speed this up, since it trivially works.  */
+  if (GET_CODE (in) == REG)
+    return 1;
+
+  /* To test MEMs properly, we'd have to take into account all the reloads
+     that are already scheduled, which can become quite complicated.
+     And since we've already handled address reloads for this MEM, it
+     should always succeed anyway.  */
+  if (GET_CODE (in) == MEM)
+    return 1;
+
+  /* If we can make a simple SET insn that does the job, everything should
+     be fine.  */
+  dst =  gen_rtx_REG (mode, regno);
+  test_insn = make_insn_raw (gen_rtx_SET (VOIDmode, dst, in));
+  save_recog_data = recog_data;
+  if (recog_memoized (test_insn) >= 0)
+    {
+      extract_insn (test_insn);
+      r = constrain_operands (1);
+    }
+  recog_data = save_recog_data;
+  return r;
+}
+
 /* Record one 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.
@@ -1532,7 +1578,11 @@ push_reload (in, out, inloc, outloc, class,
                                          regno + offs))
                break;
 
-           if (offs == nregs)
+           if (offs == nregs
+               && (! (refers_to_regno_for_reload_p
+                      (regno, (regno + HARD_REGNO_NREGS (regno, inmode)),
+                               in, (rtx *)0))
+                   || can_reload_into (in, regno, inmode)))
              {
                rld[i].reg_rtx = gen_rtx_REG (rel_mode, regno);
                break;