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:
parent
316fc112ae
commit
60936b2231
6 changed files with 102 additions and 201 deletions
|
@ -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.
|
||||
|
|
|
@ -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")])
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
|
|
21
gcc/testsuite/gcc.dg/pr42427.c
Normal file
21
gcc/testsuite/gcc.dg/pr42427.c
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue