OSDN Git Service

PR inline-asm/39543
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 18:56:14 +0000 (18:56 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 18:56:14 +0000 (18:56 +0000)
* fwprop.c (forward_propagate_asm): New function.
(forward_propagate_and_simplify): Propagate also into __asm, if it
doesn't increase the number of referenced registers.

* gcc.target/i386/pr39543-1.c: New test.
* gcc.target/i386/pr39543-2.c: New test.
* gcc.target/i386/pr39543-3.c: New test.

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

gcc/ChangeLog
gcc/fwprop.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr39543-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr39543-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr39543-3.c [new file with mode: 0644]

index 6770f23..ee80aa0 100644 (file)
@@ -1,5 +1,10 @@
 2009-04-26  Jakub Jelinek  <jakub@redhat.com>
 
 2009-04-26  Jakub Jelinek  <jakub@redhat.com>
 
+       PR inline-asm/39543
+       * fwprop.c (forward_propagate_asm): New function.
+       (forward_propagate_and_simplify): Propagate also into __asm, if it
+       doesn't increase the number of referenced registers.
+
        PR c/39889
        * stmt.c (warn_if_unused_value): Look through NON_LVALUE_EXPR.
 
        PR c/39889
        * stmt.c (warn_if_unused_value): Look through NON_LVALUE_EXPR.
 
index 2f78cd4..a01de13 100644 (file)
@@ -1,5 +1,5 @@
 /* RTL-based forward propagation pass for GNU compiler.
 /* RTL-based forward propagation pass for GNU compiler.
-   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Paolo Bonzini and Steven Bosscher.
 
 This file is part of GCC.
    Contributed by Paolo Bonzini and Steven Bosscher.
 
 This file is part of GCC.
@@ -852,6 +852,80 @@ forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set)
     return false;
 }
 
     return false;
 }
 
+/* Try to replace USE with SRC (defined in DEF_INSN) in __asm.  */
+
+static bool
+forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg)
+{
+  rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc;
+  int speed_p, i;
+  df_ref *use_vec;
+
+  gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0);
+
+  src = SET_SRC (def_set);
+  use_pat = PATTERN (use_insn);
+
+  /* In __asm don't replace if src might need more registers than
+     reg, as that could increase register pressure on the __asm.  */
+  use_vec = DF_INSN_USES (def_insn);
+  if (use_vec[0] && use_vec[1])
+    return false;
+
+  speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
+  asm_operands = NULL_RTX;
+  switch (GET_CODE (use_pat))
+    {
+    case ASM_OPERANDS:
+      asm_operands = use_pat;
+      break;
+    case SET:
+      if (MEM_P (SET_DEST (use_pat)))
+       {
+         loc = &SET_DEST (use_pat);
+         new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
+         if (new_rtx)
+           validate_unshare_change (use_insn, loc, new_rtx, true);
+       }
+      asm_operands = SET_SRC (use_pat);
+      break;
+    case PARALLEL:
+      for (i = 0; i < XVECLEN (use_pat, 0); i++)
+       if (GET_CODE (XVECEXP (use_pat, 0, i)) == SET)
+         {
+           if (MEM_P (SET_DEST (XVECEXP (use_pat, 0, i))))
+             {
+               loc = &SET_DEST (XVECEXP (use_pat, 0, i));
+               new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg,
+                                        src, speed_p);
+               if (new_rtx)
+                 validate_unshare_change (use_insn, loc, new_rtx, true);
+             }
+           asm_operands = SET_SRC (XVECEXP (use_pat, 0, i));
+         }
+       else if (GET_CODE (XVECEXP (use_pat, 0, i)) == ASM_OPERANDS)
+         asm_operands = XVECEXP (use_pat, 0, i);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  gcc_assert (asm_operands && GET_CODE (asm_operands) == ASM_OPERANDS);
+  for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (asm_operands); i++)
+    {
+      loc = &ASM_OPERANDS_INPUT (asm_operands, i);
+      new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
+      if (new_rtx)
+       validate_unshare_change (use_insn, loc, new_rtx, true);
+    }
+
+  if (num_changes_pending () == 0 || !apply_change_group ())
+    return false;
+
+  num_changes++;
+  return true;
+}
+
 /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the
    result.  */
 
 /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the
    result.  */
 
@@ -863,12 +937,16 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set)
   rtx src, reg, new_rtx, *loc;
   bool set_reg_equal;
   enum machine_mode mode;
   rtx src, reg, new_rtx, *loc;
   bool set_reg_equal;
   enum machine_mode mode;
+  int asm_use = -1;
+
+  if (INSN_CODE (use_insn) < 0)
+    asm_use = asm_noperands (PATTERN (use_insn));
 
 
-  if (!use_set)
+  if (!use_set && asm_use < 0)
     return false;
 
   /* Do not propagate into PC, CC0, etc.  */
     return false;
 
   /* Do not propagate into PC, CC0, etc.  */
-  if (GET_MODE (SET_DEST (use_set)) == VOIDmode)
+  if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode)
     return false;
 
   /* If def and use are subreg, check if they match.  */
     return false;
 
   /* If def and use are subreg, check if they match.  */
@@ -900,7 +978,7 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set)
   if (MEM_P (src) && MEM_READONLY_P (src))
     {
       rtx x = avoid_constant_pool_reference (src);
   if (MEM_P (src) && MEM_READONLY_P (src))
     {
       rtx x = avoid_constant_pool_reference (src);
-      if (x != src)
+      if (x != src && use_set)
        {
           rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
          rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set);
        {
           rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
          rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set);
@@ -911,6 +989,9 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set)
       return false;
     }
 
       return false;
     }
 
+  if (asm_use >= 0)
+    return forward_propagate_asm (use, def_insn, def_set, reg);
+
   /* Else try simplifying.  */
 
   if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE)
   /* Else try simplifying.  */
 
   if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE)
index 7acde8d..c9f21cf 100644 (file)
@@ -1,5 +1,10 @@
 2009-04-26  Jakub Jelinek  <jakub@redhat.com>
 
 2009-04-26  Jakub Jelinek  <jakub@redhat.com>
 
+       PR inline-asm/39543
+       * gcc.target/i386/pr39543-1.c: New test.
+       * gcc.target/i386/pr39543-2.c: New test.
+       * gcc.target/i386/pr39543-3.c: New test.
+
        PR c/39889
        * gcc.dg/Wunused-value-3.c: New test.
 
        PR c/39889
        * gcc.dg/Wunused-value-3.c: New test.
 
diff --git a/gcc/testsuite/gcc.target/i386/pr39543-1.c b/gcc/testsuite/gcc.target/i386/pr39543-1.c
new file mode 100644 (file)
index 0000000..a8442b2
--- /dev/null
@@ -0,0 +1,52 @@
+/* PR inline-asm/39543 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fomit-frame-pointer" } */
+
+float __attribute__ ((aligned (16))) s0[128];
+const float s1 = 0.707;
+float s2[8] __attribute__ ((aligned (16)));
+float s3[8] __attribute__ ((aligned (16)));
+float s4[16] __attribute__ ((aligned (16)));
+float s5[16] __attribute__ ((aligned (16)));
+
+void
+foo (int k, float *x, float *y, const float *d, const float *z)
+{
+  float *a, *b, *c, *e;
+
+  a = x + 2 * k;
+  b = a + 2 * k;
+  c = b + 2 * k;
+  e = y + 2 * k;
+  __asm__ volatile (""
+                   : "=m" (x[0]), "=m" (b[0]), "=m" (a[0]), "=m" (c[0])
+                   : "m" (y[0]), "m" (y[k * 2]), "m" (x[0]), "m" (a[0])
+                   : "memory");
+  for (;;)
+    {
+      __asm__ volatile (""
+                       :
+                       : "m" (y[2]), "m" (d[2]), "m" (e[2]), "m" (z[2])
+                       : "memory");
+      if (!--k)
+       break;
+    }
+  __asm__ volatile (""
+                   : "=m" (x[2]), "=m" (x[10]), "=m" (x[6]), "=m" (x[14])
+                   : "m" (y[2]), "m" (y[6]), "m" (x[2]), "m" (x[6]),
+                     "m" (y[18]), "m" (s1)
+                   : "memory");
+}
+
+void
+bar (float *a)
+{
+  foo (4, a, a + 16, s2, s3);
+  foo (8, a, a + 32, s4, s5);
+}
+
+void
+baz (void)
+{
+  bar (s0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr39543-2.c b/gcc/testsuite/gcc.target/i386/pr39543-2.c
new file mode 100644 (file)
index 0000000..c292041
--- /dev/null
@@ -0,0 +1,51 @@
+/* PR inline-asm/39543 */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+float __attribute__ ((aligned (16))) s0[128];
+const float s1 = 0.707;
+float s2[8] __attribute__ ((aligned (16)));
+float s3[8] __attribute__ ((aligned (16)));
+float s4[16] __attribute__ ((aligned (16)));
+float s5[16] __attribute__ ((aligned (16)));
+
+void
+foo (int k, float *x, float *y, const float *d, const float *z)
+{
+  float *a, *b, *c, *e;
+
+  a = x + 2 * k;
+  b = a + 2 * k;
+  c = b + 2 * k;
+  e = y + 2 * k;
+  __asm__ volatile (""
+                   : "=m" (x[0]), "=m" (b[0]), "=m" (a[0]), "=m" (c[0])
+                   : "m" (y[0]), "m" (y[k * 2]), "m" (x[0]), "m" (a[0])
+                   : "memory");
+  for (;;)
+    {
+      __asm__ volatile (""
+                       :
+                       : "m" (y[2]), "m" (d[2]), "m" (e[2]), "m" (z[2])
+                       : "memory");
+      if (!--k)
+       break;
+    }
+  __asm__ volatile (""
+                   : "=m" (x[2]), "=m" (x[10]), "=m" (x[6]), "=m" (x[14])
+                   : "m" (y[2]), "m" (y[6]), "m" (x[2]), "m" (x[6]), "m" (s1)
+                   : "memory");
+}
+
+void
+bar (float *a)
+{
+  foo (4, a, a + 16, s2, s3);
+  foo (8, a, a + 32, s4, s5);
+}
+
+void
+baz (void)
+{
+  bar (s0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr39543-3.c b/gcc/testsuite/gcc.target/i386/pr39543-3.c
new file mode 100644 (file)
index 0000000..4e103e6
--- /dev/null
@@ -0,0 +1,42 @@
+/* PR inline-asm/39543 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int s[128];
+
+void
+f1 (void)
+{
+  int i;
+  asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+               : "=r" (i)
+               : "m" (s[0]), "m" (s[2]), "m" (s[4]), "m" (s[6]), "m" (s[8]),
+                 "m" (s[10]), "m" (s[12]), "m" (s[14]), "m" (s[16]), "m" (s[18]),
+                 "m" (s[20]), "m" (s[22]), "m" (s[24]), "m" (s[26]), "m" (s[28]),
+                 "m" (s[30]), "m" (s[32]));
+  asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+               : "=r" (i)
+               : "m" (s[0]), "m" (s[2]), "m" (s[4]), "m" (s[6]), "m" (s[8]),
+                 "m" (s[10]), "m" (s[12]), "m" (s[14]), "m" (s[16]), "m" (s[18]),
+                 "m" (s[20]), "m" (s[22]), "m" (s[24]), "m" (s[26]), "m" (s[28]),
+                 "m" (s[30]), "m" (s[32]));
+}
+
+void
+f2 (int *q)
+{
+  int i;
+  int *p = q + 32;
+  asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+               : "=r" (i)
+               : "m" (p[0]), "m" (p[2]), "m" (p[4]), "m" (p[6]), "m" (p[8]),
+                 "m" (p[10]), "m" (p[12]), "m" (p[14]), "m" (p[16]), "m" (p[18]),
+                 "m" (p[20]), "m" (p[22]), "m" (p[24]), "m" (p[26]), "m" (p[28]),
+                 "m" (p[30]), "m" (p[32]));
+  asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17"
+               : "=r" (i)
+               : "m" (p[0]), "m" (p[2]), "m" (p[4]), "m" (p[6]), "m" (p[8]),
+                 "m" (p[10]), "m" (p[12]), "m" (p[14]), "m" (p[16]), "m" (p[18]),
+                 "m" (p[20]), "m" (p[22]), "m" (p[24]), "m" (p[26]), "m" (p[28]),
+                 "m" (p[30]), "m" (p[32]));
+}