This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[committed] PR16176: Fix invalid lwl/lwr pairs
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 25 Jun 2004 19:30:08 +0100
- Subject: [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);
+}