This is the mail archive of the gcc-patches@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]

RFA: Make reload merging not clobber RELOAD_FOR_OUTPUT_ADDRESS


This patch is logically a followup to Joern's patch here:

  http://gcc.gnu.org/ml/gcc-patches/2002-06/msg00419.html

In that testcase, there was an instruction with five reloads: one for the
address of the output, one for the address of each input, one for the first
input and the output (RELOAD_OTHER), and one for the second input.  The
two address reloads were for the same value, a register plus offset.
When they were merged, the type of the output address reload (also for the
same value) was changed to RELOAD_FOR_OTHER_ADDRESS, because it appeared to
be related to the merged reloads - by reg_overlap_mentioned_for_reload_p.

Since it was already assigned the same reload register as the
RELOAD_FOR_INPUT, changing it from RELOAD_FOR_OUTPUT_ADDRESS to
RELOAD_FOR_OTHER_ADDRESS made it be issued too early, and the value was
clobbered before the output reload.

Joern fixed this by suppressing the transformation if no conflicting input
was found.  It worked in this case because the values were exactly the same
- thus no conflict.

I have a testcase (no luck reducing it, sorry) with almost exactly the same
reloads, except that the constant in the RELOAD_FOR_OUTPUT_ADDRESS is not
the same as that in the RELOAD_FOR_INPUT_ADDRESS.  So there appear to be
conflicting inputs.  Changing this causes the same problem: the calculation
of the output address is done before an input is loaded into that register,
and then the dead address setup is deleted, and the output is stored to a
bogus location.

I talked this over with Ian Lance Taylor on IRC for a while.  The final loop
is really trying to convert RELOAD_FOR_INPUT_ADDRESS to
RELOAD_FOR_OTHER_ADDRESS when the corresponding RELOAD_FOR_INPUT is
converted to RELOAD_OTHER, et cetera.  And we never convert
RELOAD_FOR_OUTPUT here, only input reloads.  So, there's never a reason to
convert RELOAD_FOR_OUTPUT_ADDRESS.

The lack of explicit chaining between reloads here is a real drag.  I think
there's a couple of other existing ways to make this function misbehave,
thus, my question to Bernd the other day about reload-branch - where all of
this code has been redone.

The attached patch fixes my testcase, and has been regression tested on HEAD
for sh-elf -m4 -ml.  OK?

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-09-29  Daniel Jacobowitz  <dan@codesourcery.com>

	* reload1.c (merge_assigned_reloads): Do not change any
	RELOAD_FOR_OUTPUT_ADDRESS reloads.

Index: reload1.c
===================================================================
RCS file: /scratch/gcc/repos/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.477
diff -u -p -r1.477 reload1.c
--- reload1.c	25 Jun 2005 02:00:54 -0000	1.477
+++ reload1.c	29 Sep 2005 19:13:43 -0000
@@ -6047,6 +6047,8 @@ merge_assigned_reloads (rtx insn)
       if (j == n_reloads
 	  && max_input_address_opnum <= min_conflicting_input_opnum)
 	{
+	  gcc_assert (rld[i].when_needed != RELOAD_FOR_OUTPUT);
+
 	  for (j = 0; j < n_reloads; j++)
 	    if (i != j && rld[j].reg_rtx != 0
 		&& rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx)
@@ -6065,16 +6067,17 @@ merge_assigned_reloads (rtx insn)
 	     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 when there are two or more reloads to
-	     be merged and a RELOAD_FOR_OUTPUT_ADDRESS reload that loads the
-	     same value or a part of it; we must not change its type if there
-	     is a conflicting input.  */
+	  /* 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)
 	    for (j = 0; j < n_reloads; j++)
 	      if (rld[j].in != 0
 		  && rld[j].when_needed != RELOAD_OTHER
 		  && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
+		  && rld[j].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
 		  && (! conflicting_input
 		      || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
 		      || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)


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