re PR target/42427 (invalid assembly code for 301.apsi for -fnon-call-exceptions)

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.

From-SVN: r157530
This commit is contained in:
Peter Bergner 2010-03-17 22:10:04 -05:00 committed by Peter Bergner
parent 316fc112ae
commit 60936b2231
6 changed files with 102 additions and 201 deletions

View file

@ -1,3 +1,17 @@
2010-03-17 Peter Bergner <bergner@vnet.ibm.com>
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.
2010-03-18 Shujing Zhao <pearly.zhao@oracle.com>
* common.opt (dumpdir): Remove redundant tab.

View file

@ -293,71 +293,9 @@
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 @@
"! 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")])

View file

@ -16724,6 +16724,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
int i;
int j = -1;
bool used_update = false;
rtx restore_basereg = NULL_RTX;
if (MEM_P (src) && INT_REGNO_P (reg))
{
@ -16742,10 +16743,27 @@ rs6000_split_multireg_move (rtx dst, rtx src)
}
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);
@ -16759,8 +16777,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
&& 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;
@ -16790,7 +16807,34 @@ rs6000_split_multireg_move (rtx dst, rtx src)
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));
}
@ -16812,6 +16856,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
simplify_gen_subreg (reg_mode, src, mode,
j * reg_mode_size)));
}
if (restore_basereg != NULL_RTX)
emit_insn (restore_basereg);
}
}

View file

@ -217,6 +217,9 @@
(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")])
@ -9148,73 +9151,9 @@
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\";
@ -9249,38 +9188,7 @@
|| 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")])
@ -9729,8 +9637,8 @@
}")
(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)]

View file

@ -1,3 +1,8 @@
2010-03-17 Peter Bergner <bergner@vnet.ibm.com>
PR target/42427
* gcc.dg/pr42427.c: New test.
2010-03-17 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/43265

View file

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