diff options
author | Jim Wilson <wilson@gcc.gnu.org> | 2005-01-17 19:51:05 -0800 |
---|---|---|
committer | Jim Wilson <wilson@gcc.gnu.org> | 2005-01-17 19:51:05 -0800 |
commit | 696a2ca15ffb199bf85594121380dc0d7399e0c9 (patch) | |
tree | e5493efa4813b7695d995d6f889ede488ee49aa3 /gcc/config/ia64/ia64.md | |
parent | 115a33c2196266e0462e516fac5bc7ff21276d13 (diff) | |
download | gcc-696a2ca15ffb199bf85594121380dc0d7399e0c9.zip gcc-696a2ca15ffb199bf85594121380dc0d7399e0c9.tar.gz gcc-696a2ca15ffb199bf85594121380dc0d7399e0c9.tar.bz2 |
Fix ICE with long double after float HFA.
PR target/19357
* config/ia64/ia64.md (movxf): Handle general register source. Adjust
comment to document why.
* gcc.c-torture/compile/pr19357.c: New test.
From-SVN: r93809
Diffstat (limited to 'gcc/config/ia64/ia64.md')
-rw-r--r-- | gcc/config/ia64/ia64.md | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index c406a79..b22f49e 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -685,10 +685,12 @@ if (GET_CODE (op0) == SUBREG) op0 = SUBREG_REG (op0); - /* We must support XFmode loads into general registers for stdarg/vararg - and unprototyped calls. We split them into DImode loads for convenience. - We don't need XFmode stores from general regs, because a stdarg/vararg - routine does a block store to memory of unnamed arguments. */ + /* We must support XFmode loads into general registers for stdarg/vararg, + unprototyped calls, and a rare case where a long double is passed as + an argument after a float HFA fills the FP registers. We split them into + DImode loads for convenience. We also need to support XFmode stores + for the last case. This case does not happen for stdarg/vararg routines, + because we do a block store to memory of unnamed arguments. */ if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0))) { @@ -708,7 +710,6 @@ if (GET_CODE (op1) == SUBREG) op1 = SUBREG_REG (op1); else - /* ??? Maybe we should make a SUBREG here? */ op1 = gen_rtx_REG (TImode, REGNO (op1)); emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1); @@ -743,6 +744,40 @@ abort (); } + if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1]))) + { + /* We're hoping to transform everything that deals with XFmode + quantities and GR registers early in the compiler. */ + if (no_new_pseudos) + abort (); + + /* Op0 can't be a GR_REG here, as that case is handled above. + If op0 is a register, then we spill op1, so that we now have a + MEM operand. This requires creating an XFmode subreg of a TImode reg + to force the spill. */ + if (register_operand (operands[0], XFmode)) + { + rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1])); + op1 = gen_rtx_SUBREG (XFmode, op1, 0); + operands[1] = spill_xfmode_operand (op1, 0); + } + + else if (GET_CODE (operands[0]) == MEM) + { + rtx in[2]; + + in[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1])); + in[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1); + + emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]); + emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]); + DONE; + } + + else + abort (); + } + if (! reload_in_progress && ! reload_completed) { operands[1] = spill_xfmode_operand (operands[1], 0); |