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]

SH movdf: clobbering output register too early


Some functions in newlib would miscompile because the insn:

(set (reg:DF r1) (mem:DF (plus:SI (reg:SI r0) (reg:SI r1))))

would be split to:

(set (reg:SI r1) (mem:SI (plus:SI (reg:SI r0) (reg:SI r1))))
(set (reg:SI r0) (plus:SI (reg:SI r0) (const_int 4)))
(set (reg:SI r2) (mem:SI (plus:SI (reg:SI r0) (reg:SI r1))))
(set (reg:SI r0) (plus:SI (reg:SI r0) (const_int -4)))

But, by the time r2 would be set, r1 had already been clobbered.  This
patch fixes this problem.  I'm checking it in.

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* config/sh/sh.md (movdf): When splitting load into pair of
	registers, don't clobber the register used in the address too
	early.

Index: gcc/config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.md,v
retrieving revision 1.71
diff -u -p -r1.71 sh.md
--- gcc/config/sh/sh.md 2001/01/05 03:46:12 1.71
+++ gcc/config/sh/sh.md 2001/01/05 20:06:03
@@ -2745,15 +2745,29 @@
 	    offset = 4;
 	  mem = copy_rtx (mem);
 	  PUT_MODE (mem, SImode);
-	  word0 = gen_rtx(SUBREG, SImode, regop, 0);
-	  emit_insn (store_p
-		     ? gen_movsi_ie (mem, word0) : gen_movsi_ie (word0, mem));
-	  emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
-	  mem = copy_rtx (mem);
-	  word1 = gen_rtx(SUBREG, SImode, regop, 1);
-	  emit_insn (store_p
-		     ? gen_movsi_ie (mem, word1) : gen_movsi_ie (word1, mem));
-	  emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
+	  word0 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 0));
+	  word1 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 1));
+	  if (store_p || ! refers_to_regno_p (REGNO (word0),
+					      REGNO (word0) + 1, addr, 0))
+	    {
+	      emit_insn (store_p
+			 ? gen_movsi_ie (mem, word0)
+			 : gen_movsi_ie (word0, mem));
+	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
+	      mem = copy_rtx (mem);
+	      emit_insn (store_p
+			 ? gen_movsi_ie (mem, word1)
+			 : gen_movsi_ie (word1, mem));
+	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
+	    }
+	  else
+	    {
+	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (offset)));
+	      emit_insn (gen_movsi_ie (word1, mem));
+	      emit_insn (gen_addsi3 (reg0, reg0, GEN_INT (-offset)));
+	      mem = copy_rtx (mem);
+	      emit_insn (gen_movsi_ie (word0, mem));
+	    }
 	  DONE;
 	}
     }

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
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]