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

Reload shouldn't share in-operands with base of out-operands

A commercial testsuite exposed a bug in reload on sh-elf.  After lreg,
we had:

(set (reg:SI A) (plus:SI (reg:SI r14) (const_int 124)))
(set (reg:SI B) (plus:SI (reg:SI A) (const_int 12)))

where A and B were pseudos.

B was assigned to (mem:SI (plus:SI (reg:SI r14) (const_int 148))).

A was replaced into the second insn, so the first insn was deleted.
LEGITIMIZE_ADDRESS modified B, and we ended up with:

(set (mem:SI (plus:SI (plus:SI (reg:SI r14) (const_int 124))
                      (const_int 24))) ;; operand 0
     (plus:SI (plus:SI (reg:SI r14) (const_int 124)) ;; operand 1
              (const_int 12) ;; operand 2

Reload first push_reload()ed (plus:SI (reg:SI r14) (const_int 124)) as
a RELOAD_FOR_OUTPUT_ADDRESS.  Then, because operand 1 had a `0'
constraint, it would push a RELOAD_OTHER for operands 0 and 1.  But
then, it found the IN operand was identical to the first reload, so it
decided to reuse it.

The result was that reload generated the following sequence of insns:

(set (reg:SI r2) (const_int 124))
(set (reg:SI r2) (plus:SI (reg:SI r2) (reg:SI r14)))
(set (reg:SI r2) (plus:SI (reg:SI r2) (const_int 12))) ;; orig insn
(set (mem:SI (plus:SI (reg:SI r2) (const_int 24))) (reg:SI r2)) ;;oops

This patch arranges for operand1 to not be shared in case it appears
as the base address of operand0, fixing the problem.  Ok to install?

Index: gcc/ChangeLog
from  Alexandre Oliva  <>

	* reload.c (refers_to_base_addr_p): New fn.
	(push_reload): Call it.

Index: gcc/reload.c
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.142
diff -u -p -r1.142 reload.c
--- gcc/reload.c 2001/01/24 23:50:56 1.142
+++ gcc/reload.c 2001/02/12 06:21:06
@@ -271,6 +271,7 @@ static void find_reloads_address_part PA
 					     enum reload_type, int));
 static rtx find_reloads_subreg_address PARAMS ((rtx, int, int, enum reload_type,
 					      int, rtx));
+static int refers_to_base_addr_p PARAMS ((rtx, rtx));
 static int find_inc_amount	PARAMS ((rtx, rtx));
@@ -1137,8 +1138,10 @@ push_reload (in, out, inloc, outloc, cla
   /* 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_for_reload_p (in, XEXP (out, 0)))
+      && (((GET_CODE (in) == REG || GET_CODE (in) == MEM)
+	   && reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
+	  || (GET_CODE (in) == PLUS
+	      && refers_to_base_addr_p (XEXP (out, 0), in))))
     dont_share = 1;
   /* If IN is a SUBREG of a hard register, make a new REG.  This
@@ -6079,6 +6082,22 @@ refers_to_mem_for_reload_p (x)
   return 0;
+/* Return nonzero if IN is a base of OUT, i.e., either OUT is equal to
+   IN or OUT is a PLUS and IN is a base of the PLUS's first operand.  */
+static int refers_to_base_addr_p (out, in)
+     rtx out, in;
+  if (rtx_equal_p (out, in))
+    return 1;
+  if (GET_CODE (out) == PLUS)
+    return refers_to_base_addr_p (XEXP (out, 0), in);
+  return 0;
 /* Check the insns before INSN to see if there is a suitable register
    containing the same value as GOAL.

Alexandre Oliva   Enjoy Guarana', see
Red Hat GCC Developer                  aoliva@{,}
CS PhD student at IC-Unicamp        oliva@{,}
Free Software Evangelist    *Please* write to mailing lists, not to me

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