I think it's the long-standing issue with word-mode paradoxical subregs of FP
regs in 64-bit mode, which is present on both PA and SPARC.  We don't have any 
real solution as of this writing, only kludges, so the attached patch makes it 
so that vector_init_fpmerge doesn't create pseudos with long live ranges, to 
lower the pressure on the register allocator.

Tested on SPARC/Solaris, applied on the mainline.


2012-01-30  Eric Botcazou  <ebotca...@adacore.com>

        PR target/51920
        * config/sparc/sparc.c (vector_init_fpmerge): Remove INNER_MODE
        parameter and use short-lived pseudos.
        (vector_init_faligndata): Remove INNER_MODE parameter and use loop.
        (sparc_expand_vector_init): Const-ify local variables and adjust
        calls to above functions.
        

-- 
Eric Botcazou
Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c	(revision 183640)
+++ config/sparc/sparc.c	(working copy)
@@ -11485,49 +11485,47 @@ vector_init_bshuffle (rtx target, rtx el
   emit_insn (final_insn);
 }
 
+/* Subroutine of sparc_expand_vector_init.  Emit code to initialize
+   all fields of TARGET to ELT in V8QI by means of VIS FPMERGE insn.  */
+
 static void
-vector_init_fpmerge (rtx target, rtx elt, enum machine_mode inner_mode)
+vector_init_fpmerge (rtx target, rtx elt)
 {
-  rtx t1, t2, t3, t3_low;
+  rtx t1, t2, t2_low, t3, t3_low;
 
   t1 = gen_reg_rtx (V4QImode);
-  elt = convert_modes (SImode, inner_mode, elt, true);
+  elt = convert_modes (SImode, QImode, elt, true);
   emit_move_insn (gen_lowpart (SImode, t1), elt);
 
-  t2 = gen_reg_rtx (V4QImode);
-  emit_move_insn (t2, t1);
+  t2 = gen_reg_rtx (V8QImode);
+  t2_low = gen_lowpart (V4QImode, t2);
+  emit_insn (gen_fpmerge_vis (t2, t1, t1));
 
   t3 = gen_reg_rtx (V8QImode);
   t3_low = gen_lowpart (V4QImode, t3);
+  emit_insn (gen_fpmerge_vis (t3, t2_low, t2_low));
 
-  emit_insn (gen_fpmerge_vis (t3, t1, t2));
-  emit_move_insn (t1, t3_low);
-  emit_move_insn (t2, t3_low);
-
-  emit_insn (gen_fpmerge_vis (t3, t1, t2));
-  emit_move_insn (t1, t3_low);
-  emit_move_insn (t2, t3_low);
-
-  emit_insn (gen_fpmerge_vis (gen_lowpart (V8QImode, target), t1, t2));
+  emit_insn (gen_fpmerge_vis (target, t3_low, t3_low));
 }
 
+/* Subroutine of sparc_expand_vector_init.  Emit code to initialize
+   all fields of TARGET to ELT in V4HI by means of VIS FALIGNDATA insn.  */
+
 static void
-vector_init_faligndata (rtx target, rtx elt, enum machine_mode inner_mode)
+vector_init_faligndata (rtx target, rtx elt)
 {
   rtx t1 = gen_reg_rtx (V4HImode);
+  int i;
 
-  elt = convert_modes (SImode, inner_mode, elt, true);
-
+  elt = convert_modes (SImode, HImode, elt, true);
   emit_move_insn (gen_lowpart (SImode, t1), elt);
 
   emit_insn (gen_alignaddrsi_vis (gen_reg_rtx (SImode),
 				  force_reg (SImode, GEN_INT (6)),
-				  CONST0_RTX (SImode)));
+				  const0_rtx));
 
-  emit_insn (gen_faligndatav4hi_vis (target, t1, target));
-  emit_insn (gen_faligndatav4hi_vis (target, t1, target));
-  emit_insn (gen_faligndatav4hi_vis (target, t1, target));
-  emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+  for (i = 0; i < 4; i++)
+    emit_insn (gen_faligndatav4hi_vis (target, t1, target));
 }
 
 /* Emit code to initialize TARGET to values for individual fields VALS.  */
@@ -11535,9 +11533,9 @@ vector_init_faligndata (rtx target, rtx
 void
 sparc_expand_vector_init (rtx target, rtx vals)
 {
-  enum machine_mode mode = GET_MODE (target);
-  enum machine_mode inner_mode = GET_MODE_INNER (mode);
-  int n_elts = GET_MODE_NUNITS (mode);
+  const enum machine_mode mode = GET_MODE (target);
+  const enum machine_mode inner_mode = GET_MODE_INNER (mode);
+  const int n_elts = GET_MODE_NUNITS (mode);
   int i, n_var = 0;
   bool all_same;
   rtx mem;
@@ -11593,12 +11591,12 @@ sparc_expand_vector_init (rtx target, rt
 	}
       if (mode == V8QImode)
 	{
-	  vector_init_fpmerge (target, XVECEXP (vals, 0, 0), inner_mode);
+	  vector_init_fpmerge (target, XVECEXP (vals, 0, 0));
 	  return;
 	}
       if (mode == V4HImode)
 	{
-	  vector_init_faligndata (target, XVECEXP (vals, 0, 0), inner_mode);
+	  vector_init_faligndata (target, XVECEXP (vals, 0, 0));
 	  return;
 	}
     }

Reply via email to