OSDN Git Service

* reload.c (can_reload_into): New function.
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Jun 2003 20:07:23 +0000 (20:07 +0000)
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Jun 2003 20:07:23 +0000 (20:07 +0000)
(push_reload): Use it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68542 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/reload.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/multi-ix.c [new file with mode: 0644]

index aea1239..7354944 100644 (file)
@@ -1,3 +1,8 @@
+2003-06-26  J"orn Rennecke <joern.rennecke@superh.com>
+
+       * reload.c (can_reload_into): New function.
+       (push_reload): Use it.
+
 2003-06-26  Kazu Hirata  <kazu@cs.umass.edu>
 
        * config/h8300/h8300.c (compute_a_rotate_length): Fix the
index 7ab823d..7a2efa3 100644 (file)
@@ -840,6 +840,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 +1582,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;
index 93e3094..df08e07 100644 (file)
@@ -1,5 +1,7 @@
 2003-06-26  J"orn Rennecke <joern.rennecke@superh.com>
 
+       * gcc.c-torture/execute/multi-ix.c: New test.
+
        * gcc.c-torture/execute/simd-4.c (main):
        Added missing semicolon at end of union.
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/multi-ix.c b/gcc/testsuite/gcc.c-torture/execute/multi-ix.c
new file mode 100644 (file)
index 0000000..71cdcb1
--- /dev/null
@@ -0,0 +1,181 @@
+/* Test for a reload bug:
+   if you have a memory reference using the indexed addressing
+   mode, and the base address is a pseudo containing an address in the frame
+   and this pseudo fails to get a hard register, we end up with a double PLUS,
+   so the frame address gets reloaded.  Now, when the index got a hard register,
+   and it dies in this insn, push_reload will consider that hard register as
+   a reload register, and disregrad overlaps with rld[n_reloads].in .  That is
+   fine as long as the add can be done with a single insn, but when the
+   constant is so large that it has to be reloaded into a register first,
+   that clobbers the index.  */
+
+#include <stdarg.h>
+
+#ifdef STACK_SIZE
+#define CHUNK ((STACK_SIZE-100)/40/sizeof(int))
+#else
+#define CHUNK 500
+#endif
+
+void s(int, ...);
+void z(int, ...);
+void c(int, ...);
+
+typedef int l[CHUNK];
+
+void
+f (int n)
+{
+  int i;
+  l a0, a1, a2, a3, a4, a5, a6, a7, a8, a9;
+  l a10, a11, a12, a13, a14, a15, a16, a17, a18, a19;
+  l a20, a21, a22, a23, a24, a25, a26, a27, a28, a29;
+  l a30, a31, a32, a33, a34, a35, a36, a37, a38, a39;
+  int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+  int i10, i11, i12, i13, i14, i15, i16, i17, i18, i19;
+  int i20, i21, i22, i23, i24, i25, i26, i27, i28, i29;
+  int i30, i31, i32, i33, i34, i35, i36, i37, i38, i39;
+
+  for (i = 0; i < n; i++)
+    {
+      s (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+        a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
+         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
+         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
+      i0 = a0[0];
+      i1 = a1[0];
+      i2 = a2[0];
+      i3 = a3[0];
+      i4 = a4[0];
+      i5 = a5[0];
+      i6 = a6[0];
+      i7 = a7[0];
+      i8 = a8[0];
+      i9 = a9[0];
+      i10 = a10[0];
+      i11 = a11[0];
+      i12 = a12[0];
+      i13 = a13[0];
+      i14 = a14[0];
+      i15 = a15[0];
+      i16 = a16[0];
+      i17 = a17[0];
+      i18 = a18[0];
+      i19 = a19[0];
+      i20 = a20[0];
+      i21 = a21[0];
+      i22 = a22[0];
+      i23 = a23[0];
+      i24 = a24[0];
+      i25 = a25[0];
+      i26 = a26[0];
+      i27 = a27[0];
+      i28 = a28[0];
+      i29 = a29[0];
+      i30 = a30[0];
+      i31 = a31[0];
+      i32 = a32[0];
+      i33 = a33[0];
+      i34 = a34[0];
+      i35 = a35[0];
+      i36 = a36[0];
+      i37 = a37[0];
+      i38 = a38[0];
+      i39 = a39[0];
+      z (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+        a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
+         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
+         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
+      a0[i0] = i0;
+      a1[i1] = i1;
+      a2[i2] = i2;
+      a3[i3] = i3;
+      a4[i4] = i4;
+      a5[i5] = i5;
+      a6[i6] = i6;
+      a7[i7] = i7;
+      a8[i8] = i8;
+      a9[i9] = i9;
+      a10[i10] = i10;
+      a11[i11] = i11;
+      a12[i12] = i12;
+      a13[i13] = i13;
+      a14[i14] = i14;
+      a15[i15] = i15;
+      a16[i16] = i16;
+      a17[i17] = i17;
+      a18[i18] = i18;
+      a19[i19] = i19;
+      a20[i20] = i20;
+      a21[i21] = i21;
+      a22[i22] = i22;
+      a23[i23] = i23;
+      a24[i24] = i24;
+      a25[i25] = i25;
+      a26[i26] = i26;
+      a27[i27] = i27;
+      a28[i28] = i28;
+      a29[i29] = i29;
+      a30[i30] = i30;
+      a31[i31] = i31;
+      a32[i32] = i32;
+      a33[i33] = i33;
+      a34[i34] = i34;
+      a35[i35] = i35;
+      a36[i36] = i36;
+      a37[i37] = i37;
+      a38[i38] = i38;
+      a39[i39] = i39;
+      c (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+        a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
+         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
+         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
+    }
+}
+
+int
+main ()
+{
+  f (1);
+  exit (0);
+}
+
+void s(int n, ...)
+{
+  va_list list;
+
+  va_start (list, n);
+  while (--n)
+    {
+      int *a = va_arg (list, int *);
+      a[0] = n;
+    }
+  va_end (list);
+}
+
+void z(int n, ...)
+{
+  va_list list;
+
+  va_start (list, n);
+  while (--n)
+    {
+      int *a = va_arg (list, int *);
+      bzero (a, sizeof (l));
+    }
+  va_end (list);
+}
+
+void c(int n, ...)
+{
+  va_list list;
+
+  va_start (list, n);
+  while (--n)
+    {
+      int *a = va_arg (list, int *);
+      if (a[n] != n)
+       abort ();
+    }
+  va_end (list);
+}