diff options
Diffstat (limited to 'gcc48-pr72717.patch')
-rw-r--r-- | gcc48-pr72717.patch | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/gcc48-pr72717.patch b/gcc48-pr72717.patch new file mode 100644 index 0000000..0aa4d2e --- /dev/null +++ b/gcc48-pr72717.patch @@ -0,0 +1,87 @@ +2016-12-13 Michael Meissner <meissner@linux.vnet.ibm.com> + + Backport from mainline + 2016-12-07 Michael Meissner <meissner@linux.vnet.ibm.com> + + PR target/72717 + * config/rs6000/rs6000.c (rs6000_expand_vector_init): If the + V2DImode elements are SUBREG's convert the result into DImode + rather than failing in emit_move_insn. + +--- gcc/testsuite/gcc.target/powerpc/pr72717.c (nonexistent) ++++ gcc/testsuite/gcc.target/powerpc/pr72717.c (revision 243626) +@@ -0,0 +1,18 @@ ++/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ ++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ ++/* { dg-require-effective-target powerpc_p8vector_ok } */ ++/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ ++/* { dg-options "-mcpu=power8 -O2" } */ ++ ++typedef long V __attribute__((__vector_size__(32))); ++ ++extern void foo (V *, V*); ++ ++/* This test generated an failure in emit_move_insn. */ ++ ++void ++foo(V *p, V *q) ++{ ++ V v = *q; ++ *p = v << v[0]; ++} +--- gcc/config/rs6000/rs6000.c (revision 243625) ++++ gcc/config/rs6000/rs6000.c (revision 243626) +@@ -6667,25 +6667,43 @@ + /* Double word values on VSX can use xxpermdi or lxvdsx. */ + if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode)) + { +- rtx op0 = XVECEXP (vals, 0, 0); +- rtx op1 = XVECEXP (vals, 0, 1); ++ rtx op[2]; ++ size_t i; ++ size_t num_elements = (all_same) ? 1 : 2; ++ for (i = 0; i < num_elements; i++) ++ { ++ op[i] = XVECEXP (vals, 0, i); ++ /* Just in case there is a SUBREG with a smaller mode, do a ++ conversion. */ ++ if (GET_MODE (op[i]) != inner_mode) ++ { ++ rtx tmp = gen_reg_rtx (inner_mode); ++ convert_move (tmp, op[i], 0); ++ op[i] = tmp; ++ } ++ /* Allow load with splat double word. */ ++ else if (MEM_P (op[i])) ++ { ++ if (!all_same) ++ op[i] = force_reg (inner_mode, op[i]); ++ } ++ else if (!REG_P (op[i])) ++ op[i] = force_reg (inner_mode, op[i]); ++ } ++ + if (all_same) + { +- if (!MEM_P (op0) && !REG_P (op0)) +- op0 = force_reg (inner_mode, op0); + if (mode == V2DFmode) +- emit_insn (gen_vsx_splat_v2df (target, op0)); ++ emit_insn (gen_vsx_splat_v2df (target, op[0])); + else +- emit_insn (gen_vsx_splat_v2di (target, op0)); ++ emit_insn (gen_vsx_splat_v2di (target, op[0])); + } + else + { +- op0 = force_reg (inner_mode, op0); +- op1 = force_reg (inner_mode, op1); + if (mode == V2DFmode) +- emit_insn (gen_vsx_concat_v2df (target, op0, op1)); ++ emit_insn (gen_vsx_concat_v2df (target, op[0], op[1])); + else +- emit_insn (gen_vsx_concat_v2di (target, op0, op1)); ++ emit_insn (gen_vsx_concat_v2di (target, op[0], op[1])); + } + return; + } |