PR inline-asm/35160
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Feb 2008 18:31:53 +0000 (18:31 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Feb 2008 18:31:53 +0000 (18:31 +0000)
* function.c (match_asm_constraints_1): Don't replace the same input
multiple times.

* gcc.target/i386/pr35160.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@132263 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr35160.c [new file with mode: 0644]

index e7eca81..553f349 100644 (file)
@@ -1,3 +1,9 @@
+2008-02-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR inline-asm/35160
+       * function.c (match_asm_constraints_1): Don't replace the same input
+       multiple times.
+
 2008-02-12  Anatoly Sokolov <aesok@post.ru>
 
        * config/avr/avr.h (AVR_HAVE_RAMPZ): Define.
index 401bb21..514d1a6 100644 (file)
@@ -1,6 +1,6 @@
 /* Expands front end tree to back end RTL for GCC.
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -5683,7 +5683,9 @@ match_asm_constraints_1 (rtx insn, rtx *p_sets, int noutputs)
   rtx op = SET_SRC (p_sets[0]);
   int ninputs = ASM_OPERANDS_INPUT_LENGTH (op);
   rtvec inputs = ASM_OPERANDS_INPUT_VEC (op);
+  bool *output_matched = alloca (noutputs * sizeof (bool));
 
+  memset (output_matched, 0, noutputs * sizeof (bool));
   for (i = 0; i < ninputs; i++)
     {
       rtx input, output, insns;
@@ -5713,6 +5715,20 @@ match_asm_constraints_1 (rtx insn, rtx *p_sets, int noutputs)
       if (j != ninputs)
        continue;
 
+      /* Avoid changing the same input several times.  For
+        asm ("" : "=mr" (out1), "=mr" (out2) : "0" (in), "1" (in));
+        only change in once (to out1), rather than changing it
+        first to out1 and afterwards to out2.  */
+      if (i > 0)
+       {
+         for (j = 0; j < noutputs; j++)
+           if (output_matched[j] && input == SET_DEST (p_sets[j]))
+             break;
+         if (j != noutputs)
+           continue;
+       }
+      output_matched[match] = true;
+
       start_sequence ();
       emit_move_insn (output, input);
       insns = get_insns ();
index 091bb28..40c0ba2 100644 (file)
@@ -1,5 +1,8 @@
 2008-02-12  Jakub Jelinek  <jakub@redhat.com>
 
+       PR inline-asm/35160
+       * gcc.target/i386/pr35160.c: New test.
+
        PR c++/34862
        * g++.dg/init/new27.C: New test.
 
diff --git a/gcc/testsuite/gcc.target/i386/pr35160.c b/gcc/testsuite/gcc.target/i386/pr35160.c
new file mode 100644 (file)
index 0000000..587b846
--- /dev/null
@@ -0,0 +1,31 @@
+/* PR inline-asm/35160 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+
+void
+__attribute__((noinline))
+foo (unsigned int *y)
+{
+   unsigned int c0, c1, c2, d0, d1, d2;
+   d0 = 0; d1 = 0; d2 = 0; c0 = c1 = c2 = 0;
+
+   __asm__ ("movl $7, %k0; movl $8, %k1; movl $9, %k2"
+           : "+r" (d0), "+r" (d1), "+r" (d2));
+   __asm__ ("movl %3, %0; movl %4, %1; movl %5, %2"
+           : "+r" (c0), "+r" (c1), "+r" (c2), "+r" (d0), "+r" (d1), "+r" (d2));
+   y[0] = c0;
+   y[1] = c1;
+   y[2] = c2;
+}
+
+int
+main (void)
+{
+  unsigned int y[3];
+  foo (y);
+  if (y[0] != 7 || y[1] != 8 || y[2] != 9)
+    abort ();
+  return 0;
+}