Fix PR 52199 on power7 (VEC_DUPLICATE)

Submitted by Michael Meissner on Feb. 15, 2012, 6:32 p.m.

Details

Message ID 20120215183258.GA24438@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

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.

Comments

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 hide | download patch | download mbox

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