OSDN Git Service

PR target/50493
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 19 Nov 2011 13:47:35 +0000 (13:47 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 19 Nov 2011 13:47:35 +0000 (13:47 +0000)
* arm.c (neon_disambiguate_copy): Correctly handle partial overlap
of src and dest operands.

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

gcc/ChangeLog
gcc/config/arm/arm.c

index 27dace6..43de112 100644 (file)
@@ -1,3 +1,9 @@
+2011-11-19  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/50493
+       * arm.c (neon_disambiguate_copy): Correctly handle partial overlap
+       of src and dest operands.
+
 2011-11-19  Iain Sandoe  <iains@gcc.gnu.org>
 
        * config/darwin.h (ASM_DEBUG_SPEC): New.
index 4846d72..e3b0b88 100644 (file)
@@ -20728,39 +20728,34 @@ neon_emit_pair_result_insn (enum machine_mode mode,
   emit_move_insn (mem, tmp2);
 }
 
-/* Set up operands for a register copy from src to dest, taking care not to
-   clobber registers in the process.
-   FIXME: This has rather high polynomial complexity (O(n^3)?) but shouldn't
-   be called with a large N, so that should be OK.  */
+/* Set up OPERANDS for a register copy from SRC to DEST, taking care
+   not to early-clobber SRC registers in the process.
 
+   We assume that the operands described by SRC and DEST represent a
+   decomposed copy of OPERANDS[1] into OPERANDS[0].  COUNT is the
+   number of components into which the copy has been decomposed.  */
 void
 neon_disambiguate_copy (rtx *operands, rtx *dest, rtx *src, unsigned int count)
 {
-  unsigned int copied = 0, opctr = 0;
-  unsigned int done = (1 << count) - 1;
-  unsigned int i, j;
+  unsigned int i;
 
-  while (copied != done)
+  if (!reg_overlap_mentioned_p (operands[0], operands[1])
+      || REGNO (operands[0]) < REGNO (operands[1]))
     {
       for (i = 0; i < count; i++)
-        {
-          int good = 1;
-
-          for (j = 0; good && j < count; j++)
-            if (i != j && (copied & (1 << j)) == 0
-                && reg_overlap_mentioned_p (src[j], dest[i]))
-              good = 0;
-
-          if (good)
-            {
-              operands[opctr++] = dest[i];
-              operands[opctr++] = src[i];
-              copied |= 1 << i;
-            }
-        }
+       {
+         operands[2 * i] = dest[i];
+         operands[2 * i + 1] = src[i];
+       }
+    }
+  else
+    {
+      for (i = 0; i < count; i++)
+       {
+         operands[2 * i] = dest[count - i - 1];
+         operands[2 * i + 1] = src[count - i - 1];
+       }
     }
-
-  gcc_assert (opctr == count * 2);
 }
 
 /* Expand an expression EXP that calls a built-in function,