[PING][PATCH, rs6000] Fix PR target/42427

Peter Bergner bergner@vnet.ibm.com
Wed Mar 17 15:53:00 GMT 2010


On Tue, 2010-03-16 at 20:49 -0400, David Edelsohn wrote:
> The ChangeLog entry for the rs6000.c rs6000_split_multireg_move change is empty.
> 
> Also, please remove "&& optimize_size".  There should be an
> abstraction separating the policy from the optimization.  We want the
> policy centralized, not scattered around the machine description to
> avoid future maintenance problems and apply the appropriate
> granularity.  If we want to conditionally set MASK_NO_UPDATE in
> target_flags for recent POWER processors when not optimizing for size,
> we should enable that separately and uniformly in
> rs6000_override_options.

Sorry, that was an oversite on the ChangeLog entry.  Fixed and optimize_size
has been removed.  Ok for mainline once bootstrapping and regtesting are
complete?

I'll leave trying to conditionally set MASK_NO_UPDATE as an optimization
for 4.6.  We can also try and tackle combining the movdf and movdd
patterns for then too.

Peter


gcc/
	PR target/42427
	* config/rs6000/rs6000.c (rs6000_split_multireg_move): Add support for
	non-offsettable and pre_modify update addressing.
	* config/rs6000/dfp.md (*movdd_hardfloat32): Make the "0", "1"
	and "2" alternatives "#".
	(*movdd_softfloat32): Make all alternatives "#";
	* config/rs6000/rs6000.md (DIFD): New define_mode_iterator.
	(*movdf_hardfloat32): Make the "0", "1" and "2" alternatives "#".
	(*movdf_softfloat32): Make all alternatives "#";
	(movdi): Use the new DIFD mode iterator to create a common splitter
	for movdi, movdf and movdd patterns.

gcc/testsuite/
	PR target/42427
	* gcc.dg/pr42427.c: New test.


Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c	(revision 155844)
+++ config/rs6000/rs6000.c	(working copy)
@@ -16700,6 +16700,7 @@ rs6000_split_multireg_move (rtx dst, rtx
       int i;
       int j = -1;
       bool used_update = false;
+      rtx restore_basereg = NULL_RTX;
 
       if (MEM_P (src) && INT_REGNO_P (reg))
 	{
@@ -16718,10 +16719,27 @@ rs6000_split_multireg_move (rtx dst, rtx
 	    }
 	  else if (! rs6000_offsettable_memref_p (src))
 	    {
-	      rtx basereg;
-	      basereg = gen_rtx_REG (Pmode, reg);
-	      emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
-	      src = replace_equiv_address (src, basereg);
+	      if (GET_CODE (XEXP (src, 0)) == PRE_MODIFY)
+		{
+		  rtx basereg = XEXP (XEXP (src, 0), 0);
+		  if (TARGET_UPDATE)
+		    {
+		      rtx ndst = simplify_gen_subreg (reg_mode, dst, mode, 0);
+		      emit_insn (gen_rtx_SET (VOIDmode, ndst,
+				 gen_rtx_MEM (reg_mode, XEXP (src, 0))));
+		      used_update = true;
+		    }
+		  else
+		    emit_insn (gen_rtx_SET (VOIDmode, basereg,
+			       XEXP (XEXP (src, 0), 1)));
+		  src = replace_equiv_address (src, basereg);
+		}
+	      else
+		{
+		  rtx basereg = gen_rtx_REG (Pmode, reg);
+		  emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
+		  src = replace_equiv_address (src, basereg);
+		}
 	    }
 
 	  breg = XEXP (src, 0);
@@ -16735,8 +16753,7 @@ rs6000_split_multireg_move (rtx dst, rtx
 	      && REGNO (breg) < REGNO (dst) + nregs)
 	    j = REGNO (breg) - REGNO (dst);
 	}
-
-      if (GET_CODE (dst) == MEM && INT_REGNO_P (reg))
+      else if (MEM_P (dst) && INT_REGNO_P (reg))
 	{
 	  rtx breg;
 
@@ -16766,7 +16783,34 @@ rs6000_split_multireg_move (rtx dst, rtx
 		emit_insn (gen_add3_insn (breg, breg, delta_rtx));
 	      dst = replace_equiv_address (dst, breg);
 	    }
-	  else
+	  else if (!rs6000_offsettable_memref_p (dst)
+		   && GET_CODE (XEXP (dst, 0)) != LO_SUM)
+	    {
+	      if (GET_CODE (XEXP (dst, 0)) == PRE_MODIFY)
+		{
+		  rtx basereg = XEXP (XEXP (dst, 0), 0);
+		  if (TARGET_UPDATE)
+		    {
+		      rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0);
+		      emit_insn (gen_rtx_SET (VOIDmode,
+				 gen_rtx_MEM (reg_mode, XEXP (dst, 0)), nsrc));
+		      used_update = true;
+		    }
+		  else
+		    emit_insn (gen_rtx_SET (VOIDmode, basereg,
+			       XEXP (XEXP (dst, 0), 1)));
+		  dst = replace_equiv_address (dst, basereg);
+		}
+	      else
+		{
+		  rtx basereg = XEXP (XEXP (dst, 0), 0);
+		  rtx offsetreg = XEXP (XEXP (dst, 0), 1);
+		  emit_insn (gen_add3_insn (basereg, basereg, offsetreg));
+		  restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg);
+		  dst = replace_equiv_address (dst, basereg);
+		}
+	    }
+	  else if (GET_CODE (XEXP (dst, 0)) != LO_SUM)
 	    gcc_assert (rs6000_offsettable_memref_p (dst));
 	}
 
@@ -16788,6 +16832,8 @@ rs6000_split_multireg_move (rtx dst, rtx
 				  simplify_gen_subreg (reg_mode, src, mode,
 						       j * reg_mode_size)));
 	}
+      if (restore_basereg != NULL_RTX)
+	emit_insn (restore_basereg);
     }
 }
 
Index: config/rs6000/dfp.md
===================================================================
--- config/rs6000/dfp.md	(revision 155844)
+++ config/rs6000/dfp.md	(working copy)
@@ -293,71 +293,9 @@ (define_insn "*movdd_hardfloat32"
     default:
       gcc_unreachable ();
     case 0:
-      /* We normally copy the low-numbered register first.  However, if
-	 the first register operand 0 is the same as the second register
-	 of operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-	return \"mr %L0,%L1\;mr %0,%1\";
-      else
-	return \"mr %0,%1\;mr %L0,%L1\";
     case 1:
-      if (rs6000_offsettable_memref_p (operands[1])
-	  || (GET_CODE (operands[1]) == MEM
-	      && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
-		  || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
-		  || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)))
-	{
-	  /* If the low-address word is used in the address, we must load
-	     it last.  Otherwise, load it first.  Note that we cannot have
-	     auto-increment in that case since the address register is
-	     known to be dead.  */
-	  if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-				 operands[1], 0))
-	    return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-	  else
-	    return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
-	}
-      else
-	{
-	  rtx addreg;
-
-	  addreg = find_addr_reg (XEXP (operands[1], 0));
-	  if (refers_to_regno_p (REGNO (operands[0]),
-				 REGNO (operands[0]) + 1,
-				 operands[1], 0))
-	    {
-	      output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-	      output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
-	      output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-	      return \"{lx|lwzx} %0,%1\";
-	    }
-	  else
-	    {
-	      output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
-	      output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-	      output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
-	      output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-	      return \"\";
-	    }
-	}
     case 2:
-      if (rs6000_offsettable_memref_p (operands[0])
-	  || (GET_CODE (operands[0]) == MEM
-	      && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
-		  || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
-		  || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)))
-	return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
-      else
-	{
-	  rtx addreg;
-
-	  addreg = find_addr_reg (XEXP (operands[0], 0));
-	  output_asm_insn (\"{stx|stwx} %1,%0\", operands);
-	  output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-	  output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
-	  output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-	  return \"\";
-	}
+      return \"#\";
     case 3:
       return \"fmr %0,%1\";
     case 4:
@@ -379,38 +317,7 @@ (define_insn "*movdd_softfloat32"
   "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
    && (gpc_reg_operand (operands[0], DDmode)
        || gpc_reg_operand (operands[1], DDmode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    default:
-      gcc_unreachable ();
-    case 0:
-      /* We normally copy the low-numbered register first.  However, if
-	 the first register operand 0 is the same as the second register of
-	 operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-	return \"mr %L0,%L1\;mr %0,%1\";
-      else
-	return \"mr %0,%1\;mr %L0,%L1\";
-    case 1:
-      /* If the low-address word is used in the address, we must load
-	 it last.  Otherwise, load it first.  Note that we cannot have
-	 auto-increment in that case since the address register is
-	 known to be dead.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-			     operands[1], 0))
-	return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-      else
-	return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
-    case 2:
-      return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
-    case 3:
-    case 4:
-    case 5:
-      return \"#\";
-    }
-}"
+  "#"
   [(set_attr "type" "two,load,store,*,*,*")
    (set_attr "length" "8,8,8,8,12,16")])
 
Index: config/rs6000/rs6000.md
===================================================================
--- config/rs6000/rs6000.md	(revision 155844)
+++ config/rs6000/rs6000.md	(working copy)
@@ -217,6 +217,9 @@ (define_mode_iterator FP [
   (DD "TARGET_DFP")
   (TD "TARGET_DFP")])
 
+; These modes do not fit in integer registers in 32-bit mode.
+(define_mode_iterator DIFD [DI DF DD])
+
 ; Various instructions that come in SI and DI forms.
 ; A generic w/d attribute, for things like cmpw/cmpd.
 (define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")])
@@ -9141,73 +9144,9 @@ (define_insn "*movdf_hardfloat32"
     default:
       gcc_unreachable ();
     case 0:
-      /* We normally copy the low-numbered register first.  However, if
-	 the first register operand 0 is the same as the second register
-	 of operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-	return \"mr %L0,%L1\;mr %0,%1\";
-      else
-	return \"mr %0,%1\;mr %L0,%L1\";
     case 1:
-      if (rs6000_offsettable_memref_p (operands[1])
-	  || (GET_CODE (operands[1]) == MEM
-	      && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
-		  || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
-		  || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC
-		  || GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY)))
-	{
-	  /* If the low-address word is used in the address, we must load
-	     it last.  Otherwise, load it first.  Note that we cannot have
-	     auto-increment in that case since the address register is
-	     known to be dead.  */
-	  if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-				 operands[1], 0))
-	    return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-	  else
-	    return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
-	}
-      else
-	{
-	  rtx addreg;
-
-	  addreg = find_addr_reg (XEXP (operands[1], 0));
-	  if (refers_to_regno_p (REGNO (operands[0]),
-				 REGNO (operands[0]) + 1,
-				 operands[1], 0))
-	    {
-	      output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-	      output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
-	      output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-	      return \"{l%X1|lwz%X1} %0,%1\";
-	    }
-	  else
-	    {
-	      output_asm_insn (\"{l%X1|lwz%X1} %0,%1\", operands);
-	      output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-	      output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
-	      output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-	      return \"\";
-	    }
-	}
     case 2:
-      if (rs6000_offsettable_memref_p (operands[0])
-	  || (GET_CODE (operands[0]) == MEM
-	      && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
-		  || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
-		  || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-		  || GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)))
-	return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
-      else
-	{
-	  rtx addreg;
-
-	  addreg = find_addr_reg (XEXP (operands[0], 0));
-	  output_asm_insn (\"{st%X0|stw%X0} %1,%0\", operands);
-	  output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-	  output_asm_insn (\"{st%X0|stw%X0} %L1,%0\", operands);
-	  output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-	  return \"\";
-	}
+      return \"#\";
     case 3:
     case 4:
       return \"xxlor %x0,%x1,%x1\";
@@ -9242,38 +9181,7 @@ (define_insn "*movdf_softfloat32"
        || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
    && (gpc_reg_operand (operands[0], DFmode)
        || gpc_reg_operand (operands[1], DFmode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    default:
-      gcc_unreachable ();
-    case 0:
-      /* We normally copy the low-numbered register first.  However, if
-	 the first register operand 0 is the same as the second register of
-	 operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-	return \"mr %L0,%L1\;mr %0,%1\";
-      else
-	return \"mr %0,%1\;mr %L0,%L1\";
-    case 1:
-      /* If the low-address word is used in the address, we must load
-	 it last.  Otherwise, load it first.  Note that we cannot have
-	 auto-increment in that case since the address register is
-	 known to be dead.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-			     operands[1], 0))
-	return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-      else
-	return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
-    case 2:
-      return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
-    case 3:
-    case 4:
-    case 5:
-      return \"#\";
-    }
-}"
+  "#"
   [(set_attr "type" "two,load,store,*,*,*")
    (set_attr "length" "8,8,8,8,12,16")])
 
@@ -9722,8 +9630,8 @@ (define_split
 }")
 
 (define_split
-  [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "")
-        (match_operand:DI 1 "input_operand" ""))]
+  [(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "")
+        (match_operand:DIFD 1 "input_operand" ""))]
   "reload_completed && !TARGET_POWERPC64
    && gpr_or_gpr_p (operands[0], operands[1])"
   [(pc)]
Index: gcc.dg/pr42427.c
===================================================================
--- gcc.dg/pr42427.c	(revision 0)
+++ gcc.dg/pr42427.c	(revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -fexceptions -fnon-call-exceptions -fpeel-loops" } */
+/* { dg-require-effective-target ilp32 } */
+
+#include <complex.h>
+
+extern double myabs (complex double);
+
+void
+test (double *help, complex double *wm, long nz)
+{
+  long k;
+  double znew;
+  double zold;
+  for (k = 0; k < nz; k++)
+    {
+      znew = myabs (wm[k]);
+      zold = help[k];
+      help[k] = znew;
+    }
+}




More information about the Gcc-patches mailing list