Hi,

The analyze_swaps pass performs special handling on certain non-swapping
loads and stores so that computations involving them can still be
optimized.  However, the intent was to avoid this for lvx, stvx, lve*,
and stve*.  The existing logic excludes these by looking for a PARALLEL
as the rtx code for the insn body.  It turns out this works for lvx,
stvx, and lve*, but stve* was implemented slightly differently, so this
check doesn't catch it.  This patch fixes the problem by looking for the
pattern that matches stve* as well; we now exclude any store with an
UNSPEC as its SET_SRC.

I've added a new compile-time test case to verify the fix.  The test
ICEs on existing trunk but passes with the new changes.

Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
regressions.  Is this ok for trunk?

Thanks,
Bill


[gcc]

2014-09-24  Bill Schmidt  <wschm...@linux.vnet.ibm.com>

        * config/rs6000/rs6000.c (insn_is_swappable_p): Don't provide
        special handling for stores whose SET_SRC is an UNSPEC (such as
        UNSPEC_STVE).


[gcc/testsuite]

2014-09-24  Bill Schmidt  <wschm...@linux.vnet.ibm.com>

        * gcc.target/powerpc/swaps-p8-17.c: New test.


Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 215486)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -33793,9 +33793,10 @@ insn_is_swappable_p (swap_web_entry *insn_entry, r
     return 0;
 
   /* Loads and stores seen here are not permuting, but we can still
-     fix them up by converting them to permuting ones.  Exception:
-     UNSPEC_LVX and UNSPEC_STVX, which have a PARALLEL body instead
-     of a SET.  */
+     fix them up by converting them to permuting ones.  Exceptions:
+     UNSPEC_LVE, UNSPEC_LVX, and UNSPEC_STVX, which have a PARALLEL
+     body instead of a SET; and UNSPEC_STVE, which has an UNSPEC
+     for the SET source.  */
   rtx body = PATTERN (insn);
   int i = INSN_UID (insn);
 
@@ -33812,7 +33813,7 @@ insn_is_swappable_p (swap_web_entry *insn_entry, r
 
   if (insn_entry[i].is_store)
     {
-      if (GET_CODE (body) == SET)
+      if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) != UNSPEC)
        {
          *special = SH_NOSWAP_ST;
          return 1;
Index: gcc/testsuite/gcc.target/powerpc/swaps-p8-17.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/swaps-p8-17.c      (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/swaps-p8-17.c      (working copy)
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-options "-mcpu=power8 -O1" } */
+/* { dg-final { scan-assembler "lxvd2x" } } */
+/* { dg-final { scan-assembler "xxpermdi" } } */
+
+/* Verify that we don't try to do permute removal in the presence of
+   vec_ste.  This used to ICE.  */
+#include <altivec.h>
+
+void f (void *p)
+{
+  vector unsigned int u32 = vec_vsx_ld (1, (const unsigned int *)p);
+  vec_ste (u32, 1, (unsigned int *)p);
+}


Reply via email to