This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RELOAD_OTHER bug?


> I see now that this code is in merge_assigned_reloads, so it might
> even be safe there to set the reload type to
> RELOAD_FOR_OTHER_ADDRESS.  You'll have to check if the reload type
> from that point onward is only needed to determine the time of the
> reload insn (rather than also the lifetime of the reload register).

It seems like the very next thing it does is generate and emit the
reload insns via emit_reload_insns().

However, I modified my logic to check to see if the other thing we're
merging with is also an address; if it's not, we stick with
RELOAD_OTHER.  I fiddled with the logic to look for reloads for the
new RELOAD_FOR_OTHER_ADDRESS too, but I suspect if we find any,
something may go wrong anyway.

Patch so far...

Index: reload1.c
===================================================================
--- reload1.c	(revision 108504)
+++ reload1.c	(working copy)
@@ -1830,6 +1830,8 @@
 	  && rld[r].regno == -1)
 	if (! find_reg (chain, i))
 	  {
+	    if (dump_file)
+	      fprintf(dump_file, "reload failure for reload %d\n", i);
 	    spill_failure (chain->insn, rld[r].class);
 	    failure = 1;
 	    return;
@@ -1898,6 +1900,12 @@
     {
       error ("unable to find a register to spill in class %qs",
 	     reg_class_names[class]);
+
+      if (dump_file)
+	{
+	  fprintf (dump_file, "\nReloads for insn # %d\n", INSN_UID (insn));
+	  debug_reload_to_stream (dump_file);
+	}
       fatal_insn ("this is the insn:", insn);
     }
 }
@@ -6051,6 +6059,29 @@
   reload_spill_index[r] = -1;
 }
 
+
+/* Returns true if merging reloads i and j should result in a
+   RELOAD_FOR_OTHER_ADDRESS reload, else false for RELOAD_OTHER.  */
+static int
+merge_becomes_other_address (int i, int j)
+{
+  int wn1 = rld[i].when_needed;
+  int wn2 = rld[j].when_needed;
+
+  if (wn2 == RELOAD_FOR_OTHER_ADDRESS)
+    wn2 = wn1;
+  else if (wn1 != RELOAD_FOR_OTHER_ADDRESS)
+    return 0;
+
+  return (wn2 == RELOAD_FOR_INPUT_ADDRESS
+	  || wn2 == RELOAD_FOR_INPADDR_ADDRESS
+	  || wn2 == RELOAD_FOR_OUTPUT_ADDRESS
+	  || wn2 == RELOAD_FOR_OUTADDR_ADDRESS
+	  || wn2 == RELOAD_FOR_OPERAND_ADDRESS
+	  || wn2 == RELOAD_FOR_OPADDR_ADDR
+	  || wn2 == RELOAD_FOR_OTHER_ADDRESS);
+}
+
 /* If SMALL_REGISTER_CLASSES is nonzero, we may not have merged two
    reloads of the same item for fear that we might not have enough reload
    registers. However, normally they will get the same reload register
@@ -6064,6 +6095,7 @@
    This will not increase the number of spill registers needed and will
    prevent redundant code.  */
 
+extern const char *const reload_when_needed_name[];
 static void
 merge_assigned_reloads (rtx insn)
 {
@@ -6136,23 +6168,28 @@
 		    || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
 		    || rld[j].when_needed == RELOAD_FOR_OTHER_ADDRESS))
 	      {
-		rld[i].when_needed = RELOAD_OTHER;
+		if (merge_becomes_other_address (i, j))
+		  rld[i].when_needed = RELOAD_FOR_OTHER_ADDRESS;
+		else
+		  rld[i].when_needed = RELOAD_OTHER;
 		rld[j].in = 0;
 		reload_spill_index[j] = -1;
 		transfer_replacements (i, j);
 	      }
 
-	  /* If this is now RELOAD_OTHER, look for any reloads that load
-	     parts of this operand and set them to RELOAD_FOR_OTHER_ADDRESS
-	     if they were for inputs, RELOAD_OTHER for outputs.  Note that
-	     this test is equivalent to looking for reloads for this operand
+	  /* If this is now RELOAD_OTHER or RELOAD_FOR_OTHER_ADDRESS,
+	     look for any reloads that load parts of this operand and
+	     set them to RELOAD_FOR_OTHER_ADDRESS if they were for
+	     inputs, RELOAD_OTHER for outputs.  Note that this test is
+	     equivalent to looking for reloads for this operand
 	     number.  */
 	  /* We must take special care with RELOAD_FOR_OUTPUT_ADDRESS; it may
 	     share registers with a RELOAD_FOR_INPUT, so we can not change it
 	     to RELOAD_FOR_OTHER_ADDRESS.  We should never need to, since we
 	     do not modify RELOAD_FOR_OUTPUT.  */
 
-	  if (rld[i].when_needed == RELOAD_OTHER)
+	  if (rld[i].when_needed == RELOAD_OTHER
+	      || rld[i].when_needed == RELOAD_FOR_OTHER_ADDRESS)
 	    for (j = 0; j < n_reloads; j++)
 	      if (rld[j].in != 0
 		  && rld[j].when_needed != RELOAD_OTHER


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]