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); +}