The problem is rs6000_expand_vector_extract did not check for SFmode being
allowed in the Altivec (upper) registers, but the insn implementing the
variable extract had it as a condition.

In looking at the variable extract code, it currently does not require SFmode
to go in the Altivec registers, but it does require DImode to go into the
Altivec registers (vec_extract of V2DFmode will require DFmode to go in Altivec
registers instead of DImode).

I have tested this patch on a little endian power8 system and there were no
regressions with either bootstrap or make check.

[gcc]
2017-04-12  Michael Meissner  <meiss...@linux.vnet.ibm.com>

        PR target/80099
        * config/rs6000/rs6000.c (rs6000_expand_vector_extract): Make sure
        that DFmode or DImode as appropriate can go in Altivec registers
        before generating the faster sequences for variable vec_extracts.
        * config/rs6000/vsx.md (vsx_extract_v4sf): Remove unneeded
        TARGET_UPPER_REGS_SF condition.

[gcc/testsuite]
2017-04-12  Michael Meissner  <meiss...@linux.vnet.ibm.com>

        PR target/80099
        * gcc.target/powerpc/pr80099.c: New test.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 246852)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -7586,15 +7586,23 @@ rs6000_expand_vector_extract (rtx target
       switch (mode)
        {
        case V2DFmode:
-         emit_insn (gen_vsx_extract_v2df_var (target, vec, elt));
-         return;
+         if (TARGET_UPPER_REGS_DF)
+           {
+             emit_insn (gen_vsx_extract_v2df_var (target, vec, elt));
+             return;
+           }
+         break;
 
        case V2DImode:
-         emit_insn (gen_vsx_extract_v2di_var (target, vec, elt));
-         return;
+         if (TARGET_UPPER_REGS_DI)
+           {
+             emit_insn (gen_vsx_extract_v2di_var (target, vec, elt));
+             return;
+           }
+         break;
 
        case V4SFmode:
-         if (TARGET_UPPER_REGS_SF)
+         if (TARGET_UPPER_REGS_DI)
            {
              emit_insn (gen_vsx_extract_v4sf_var (target, vec, elt));
              return;
@@ -7602,16 +7610,28 @@ rs6000_expand_vector_extract (rtx target
          break;
 
        case V4SImode:
-         emit_insn (gen_vsx_extract_v4si_var (target, vec, elt));
-         return;
+         if (TARGET_UPPER_REGS_DI)
+           {
+             emit_insn (gen_vsx_extract_v4si_var (target, vec, elt));
+             return;
+           }
+         break;
 
        case V8HImode:
-         emit_insn (gen_vsx_extract_v8hi_var (target, vec, elt));
-         return;
+         if (TARGET_UPPER_REGS_DI)
+           {
+             emit_insn (gen_vsx_extract_v8hi_var (target, vec, elt));
+             return;
+           }
+         break;
 
        case V16QImode:
-         emit_insn (gen_vsx_extract_v16qi_var (target, vec, elt));
-         return;
+         if (TARGET_UPPER_REGS_DI)
+           {
+             emit_insn (gen_vsx_extract_v16qi_var (target, vec, elt));
+             return;
+           }
+         break;
 
        default:
          gcc_unreachable ();
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md    (revision 246852)
+++ gcc/config/rs6000/vsx.md    (working copy)
@@ -2419,8 +2419,7 @@ (define_insn_and_split "vsx_extract_v4sf
                   UNSPEC_VSX_EXTRACT))
    (clobber (match_scratch:DI 3 "=r,&b,&b"))
    (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
-  "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT
-   && TARGET_UPPER_REGS_SF"
+  "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT"
   "#"
   "&& reload_completed"
   [(const_int 0)]
Index: gcc/testsuite/gcc.target/powerpc/pr80099.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr80099.c  (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr80099.c  (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { 
"-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O2 -mno-upper-regs-di" } */
+
+/* PR target/80099: compiler internal error if -mno-upper-regs-di used.  */
+
+int a;
+int int_from_mem (vector float *c)
+{
+  return __builtin_vec_extract (*c, a);
+}

Reply via email to