Patchwork Fix PR 52199 on power7 (VEC_DUPLICATE)

login
register
mail settings
Submitter Michael Meissner
Date Feb. 15, 2012, 6:32 p.m.
Message ID <20120215183258.GA24438@ibm-tiger.the-meissners.org>
Download mbox | patch
Permalink /patch/141376/
State New
Headers show

Comments

Michael Meissner - Feb. 15, 2012, 6:32 p.m.
This patch fixes PR 52199, which shows up on power7 systems when the compiler
is vectorizing DImode operations, and the vector duplicate code was not
prepared to accept CONST and SYMBOL_REF's.

I have done a bootstrap and make compare, and there were no regressions.  Is
this ok to install?  I will also back port the change to 4.6, since the exact
same code is in that revision as well.
David Edelsohn - Feb. 15, 2012, 7:26 p.m.
On Wed, Feb 15, 2012 at 1:32 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch fixes PR 52199, which shows up on power7 systems when the compiler
> is vectorizing DImode operations, and the vector duplicate code was not
> prepared to accept CONST and SYMBOL_REF's.
>
> I have done a bootstrap and make compare, and there were no regressions.  Is
> this ok to install?  I will also back port the change to 4.6, since the exact
> same code is in that revision as well.

Okay.

Thanks, David

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 184276)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -4701,28 +4701,25 @@  rs6000_expand_vector_init (rtx target, r
   /* 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);
       if (all_same)
 	{
-	  rtx element = XVECEXP (vals, 0, 0);
+	  if (!MEM_P (op0) && !REG_P (op0))
+	    op0 = force_reg (inner_mode, op0);
 	  if (mode == V2DFmode)
-	    emit_insn (gen_vsx_splat_v2df (target, element));
+	    emit_insn (gen_vsx_splat_v2df (target, op0));
 	  else
-	    emit_insn (gen_vsx_splat_v2di (target, element));
+	    emit_insn (gen_vsx_splat_v2di (target, op0));
 	}
       else
 	{
+	  op0 = force_reg (inner_mode, op0);
+	  op1 = force_reg (inner_mode, op1);
 	  if (mode == V2DFmode)
-	    {
-	      rtx op0 = copy_to_mode_reg (DFmode, XVECEXP (vals, 0, 0));
-	      rtx op1 = copy_to_mode_reg (DFmode, XVECEXP (vals, 0, 1));
-	      emit_insn (gen_vsx_concat_v2df (target, op0, op1));
-	    }
+	    emit_insn (gen_vsx_concat_v2df (target, op0, op1));
 	  else
-	    {
-	      rtx op0 = copy_to_mode_reg (DImode, XVECEXP (vals, 0, 0));
-	      rtx op1 = copy_to_mode_reg (DImode, XVECEXP (vals, 0, 1));
-	      emit_insn (gen_vsx_concat_v2di (target, op0, op1));
-	    }
+	    emit_insn (gen_vsx_concat_v2di (target, op0, op1));
 	}
       return;
     }
@@ -4736,7 +4733,7 @@  rs6000_expand_vector_init (rtx target, r
       if (all_same)
 	{
 	  rtx freg = gen_reg_rtx (V4SFmode);
-	  rtx sreg = copy_to_reg (XVECEXP (vals, 0, 0));
+	  rtx sreg = force_reg (SFmode, XVECEXP (vals, 0, 0));
 
 	  emit_insn (gen_vsx_xscvdpsp_scalar (freg, sreg));
 	  emit_insn (gen_vsx_xxspltw_v4sf (target, freg, const0_rtx));
@@ -4747,13 +4744,13 @@  rs6000_expand_vector_init (rtx target, r
 	  rtx dbl_odd  = gen_reg_rtx (V2DFmode);
 	  rtx flt_even = gen_reg_rtx (V4SFmode);
 	  rtx flt_odd  = gen_reg_rtx (V4SFmode);
+	  rtx op0 = force_reg (SFmode, XVECEXP (vals, 0, 0));
+	  rtx op1 = force_reg (SFmode, XVECEXP (vals, 0, 1));
+	  rtx op2 = force_reg (SFmode, XVECEXP (vals, 0, 2));
+	  rtx op3 = force_reg (SFmode, XVECEXP (vals, 0, 3));
 
-	  emit_insn (gen_vsx_concat_v2sf (dbl_even,
-					  copy_to_reg (XVECEXP (vals, 0, 0)),
-					  copy_to_reg (XVECEXP (vals, 0, 1))));
-	  emit_insn (gen_vsx_concat_v2sf (dbl_odd,
-					  copy_to_reg (XVECEXP (vals, 0, 2)),
-					  copy_to_reg (XVECEXP (vals, 0, 3))));
+	  emit_insn (gen_vsx_concat_v2sf (dbl_even, op0, op1));
+	  emit_insn (gen_vsx_concat_v2sf (dbl_odd, op2, op3));
 	  emit_insn (gen_vsx_xvcvdpsp (flt_even, dbl_even));
 	  emit_insn (gen_vsx_xvcvdpsp (flt_odd, dbl_odd));
 	  rs6000_expand_extract_even (target, flt_even, flt_odd);
Index: gcc/testsuite/gcc.target/powerpc/pr52199.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr52199.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr52199.c	(revision 0)
@@ -0,0 +1,24 @@ 
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O3 -mcpu=power7 -fmerge-all-constants" } */
+
+struct locale_time_t
+{
+  const char *abday[7];
+  const unsigned int *wabday[7];
+};
+
+static const unsigned int empty_wstr[1] = { 0 };
+
+void
+time_read (struct locale_time_t *time)
+{
+  int cnt;
+
+  for (cnt=0; cnt < 7; cnt++)
+    {
+      time->abday[cnt] = "";
+      time->wabday[cnt] = empty_wstr;
+    }
+}