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]

[committed] PR16176: Fix invalid lwl/lwr pairs


In the PR, reduced to the testcase below, we were expanding an lwl/lwr
pair in which the destination register was also mentioned in the source
operand.  We ended up something like:

        lwl r1,(r1)
        lwr r1,3(r1)

in which the lwr address was wrongly clobbered.

Fixed by using a temporary register for lwl and lwr.  Bootstrapped &
regression tested on mips64{,el}-linux-gnu.  I also compared c-torture
assembly output at -O2 before and after the patch (excluding the testcase
added here).  There were no differences.  Applied to mainline.

Richard


	PR target/16176
	* config/mips/mips.c (mips_expand_unaligned_load): Use a temporary
	register for the destination of the lwl or ldl.

testsuite/
	* gcc.c-torture/execute/20040625-1.c: New test.

Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.362.4.12
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.362.4.12 mips.c
--- config/mips/mips.c	17 Mar 2004 07:03:38 -0000	1.362.4.12
+++ config/mips/mips.c	24 Jun 2004 22:16:09 -0000
@@ -4482,7 +4469,7 @@ mips_get_unaligned_mem (rtx *op, unsigne
 bool
 mips_expand_unaligned_load (rtx dest, rtx src, unsigned int width, int bitpos)
 {
-  rtx left, right;
+  rtx left, right, temp;
 
   /* If TARGET_64BIT, the destination of a 32-bit load will be a
      paradoxical word_mode subreg.  This is the only case in which
@@ -4501,17 +4488,16 @@ mips_expand_unaligned_load (rtx dest, rt
   if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right))
     return false;
 
+  temp = gen_reg_rtx (GET_MODE (dest));
   if (GET_MODE (dest) == DImode)
     {
-      emit_insn (gen_mov_ldl (dest, src, left));
-      emit_insn (gen_mov_ldr (copy_rtx (dest), copy_rtx (src),
-			      right, copy_rtx (dest)));
+      emit_insn (gen_mov_ldl (temp, src, left));
+      emit_insn (gen_mov_ldr (dest, copy_rtx (src), right, temp));
     }
   else
     {
-      emit_insn (gen_mov_lwl (dest, src, left));
-      emit_insn (gen_mov_lwr (copy_rtx (dest), copy_rtx (src),
-			      right, copy_rtx (dest)));
+      emit_insn (gen_mov_lwl (temp, src, left));
+      emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
     }
   return true;
 }
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ testsuite/gcc.c-torture/execute/20040625-1.c	Thu Jun 24 23:15:42 2004
@@ -0,0 +1,20 @@
+/* From PR target/16176 */
+struct __attribute__ ((packed)) s { struct s *next; };
+
+struct s * __attribute__ ((noinline))
+maybe_next (struct s *s, int t)
+{
+  if (t)
+    s = s->next;
+  return s;
+}
+
+int main ()
+{
+  struct s s1, s2;
+
+  s1.next = &s2;
+  if (maybe_next (&s1, 1) != &s2)
+    abort ();
+  exit (0);
+}


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