diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9d860de0124463354e0ecc03915c761e401188b2..003f8cdadaa748bd8791d3643d9fea57eafbf676 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2012-02-15  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+	PR target/52199
+	* config/rs6000/rs6000.c (rs6000_expand_vector_init): Use
+	force_reg instead of copy_to_reg for better optimization.  Force
+	non-register or memory operands into a register.
+
 2012-02-15  Andrew MacLeod  <amacleod@redhat.com>
 
 	* extend.texi: Reserve upper bits of memory model for future use.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 97a3b81b08d5933f7ddbccb82a262726d755a25d..3ffc48c7e31c98036a8368747527100ae4ddab48 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4701,28 +4701,25 @@ rs6000_expand_vector_init (rtx target, rtx vals)
   /* 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, rtx vals)
       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, rtx vals)
 	  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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 870867f84e93f2d60d474e9c1334be57b059c8d9..cba5c940c3c502688b78c9af0f3f2accabf25c66 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-02-15  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+	PR target/52199
+	* gcc.target/powerpc/pr52199.c: New file.
+
 2012-02-15  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
 	PR target/52152
diff --git a/gcc/testsuite/gcc.target/powerpc/pr52199.c b/gcc/testsuite/gcc.target/powerpc/pr52199.c
new file mode 100644
index 0000000000000000000000000000000000000000..e2231938839206fea6630b6589553ca27a66a059
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr52199.c
@@ -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;
+    }
+}