[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