aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey Keating <geoffk@apple.com>2003-12-09 01:57:45 +0000
committerGeoffrey Keating <geoffk@gcc.gnu.org>2003-12-09 01:57:45 +0000
commita9baceb10b8db929dbf87c0670b041aaa9171b42 (patch)
treea42d7b7b99c57a76ad67255b112d715ef171c90e
parent86b40947201d0457c50072eb6443ce09b68d5acc (diff)
downloadgcc-a9baceb10b8db929dbf87c0670b041aaa9171b42.zip
gcc-a9baceb10b8db929dbf87c0670b041aaa9171b42.tar.gz
gcc-a9baceb10b8db929dbf87c0670b041aaa9171b42.tar.bz2
re PR target/11848 ([darwin] [no support for 128 doubles] internal compiler error for -mlong-double-128)
PR target/11848 * rs6000.h (CANNOT_CHANGE_MODE_CLASS): Allow change of mode in floating-point registers between TFmode and DImode. * rs6000.c (rs6000_emit_move): Split moves early. (secondary_reload_class): Random Whitespace Change. (rs6000_split_multireg_move): Support moves involving FP registers. Emit instructions directly. * rs6000-protos.h (rs6000_split_multireg_move): Update prototype. * altivec.md: Update for changes to rs6000_split_multireg_move. * rs6000.md: Update for changes to rs6000_split_multireg_move. (movtf_internal): Support moves to/from GPRs. From-SVN: r74454
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/rs6000/altivec.md88
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000.c181
-rw-r--r--gcc/config/rs6000/rs6000.h11
-rw-r--r--gcc/config/rs6000/rs6000.md158
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20031208-1.c6
7 files changed, 156 insertions, 304 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 984fa45..113bdcb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2003-12-08 Geoffrey Keating <geoffk@apple.com>
+
+ PR target/11848
+ * rs6000.h (CANNOT_CHANGE_MODE_CLASS): Allow change of mode
+ in floating-point registers between TFmode and DImode.
+ * rs6000.c (rs6000_emit_move): Split moves early.
+ (secondary_reload_class): Random Whitespace Change.
+ (rs6000_split_multireg_move): Support moves involving FP registers.
+ Emit instructions directly.
+ * rs6000-protos.h (rs6000_split_multireg_move): Update prototype.
+ * altivec.md: Update for changes to rs6000_split_multireg_move.
+ * rs6000.md: Update for changes to rs6000_split_multireg_move.
+ (movtf_internal): Support moves to/from GPRs.
+
2003-12-08 Stuart Hastings <stuart@apple.com>
* config/i386/i386.md: Typo in split of fp-valued if_then_else.
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 5fccb98..73d0417 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -113,26 +113,10 @@
(define_split
[(set (match_operand:V4SI 0 "nonimmediate_operand" "")
(match_operand:V4SI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
+ "TARGET_ALTIVEC && reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-"{
- rs6000_split_multireg_move (operands);
-}")
-
-(define_split
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
- (match_operand:V4SI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 6))
- (set (match_dup 3) (match_dup 7))
- (set (match_dup 4) (match_dup 8))
- (set (match_dup 5) (match_dup 9))]
-"{
- rs6000_split_multireg_move (operands);
-}")
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_split
[(set (match_operand:V4SI 0 "altivec_register_operand" "")
@@ -175,26 +159,10 @@
(define_split
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
(match_operand:V8HI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
+ "TARGET_ALTIVEC && reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-"{
- rs6000_split_multireg_move (operands);
-}")
-
-(define_split
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
- (match_operand:V8HI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 6))
- (set (match_dup 3) (match_dup 7))
- (set (match_dup 4) (match_dup 8))
- (set (match_dup 5) (match_dup 9))]
-"{
- rs6000_split_multireg_move (operands);
-}")
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_split
[(set (match_operand:V8HI 0 "altivec_register_operand" "")
@@ -237,26 +205,10 @@
(define_split
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
+ "TARGET_ALTIVEC && reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-"{
- rs6000_split_multireg_move (operands);
-}")
-
-(define_split
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
- (match_operand:V16QI 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 6))
- (set (match_dup 3) (match_dup 7))
- (set (match_dup 4) (match_dup 8))
- (set (match_dup 5) (match_dup 9))]
-"{
- rs6000_split_multireg_move (operands);
-}")
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_split
[(set (match_operand:V16QI 0 "altivec_register_operand" "")
@@ -299,26 +251,10 @@
(define_split
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
+ "TARGET_ALTIVEC && reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-"{
- rs6000_split_multireg_move (operands);
-}")
-
-(define_split
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
- (match_operand:V4SF 1 "input_operand" ""))]
- "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 6))
- (set (match_dup 3) (match_dup 7))
- (set (match_dup 4) (match_dup 8))
- (set (match_dup 5) (match_dup 9))]
-"{
- rs6000_split_multireg_move (operands);
-}")
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 57fca19..79679f4 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -125,7 +125,7 @@ extern int mfcr_operation (rtx, enum machine_mode);
extern int mtcrf_operation (rtx, enum machine_mode);
extern int lmw_operation (rtx, enum machine_mode);
extern struct rtx_def *create_TOC_reference (rtx);
-extern void rs6000_split_multireg_move (rtx *);
+extern void rs6000_split_multireg_move (rtx, rtx);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 4f91e80..647469f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3457,7 +3457,26 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
/* Handle the case of CONSTANT_P_RTX. */
if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
goto emit_set;
-
+
+ /* 128-bit constant floating-point values on Darwin should really be
+ loaded as two parts. */
+ if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
+ && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ /* DImode is used, not DFmode, because simplify_gen_subreg doesn't
+ know how to get a DFmode SUBREG of a TFmode. */
+ rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode, 0),
+ simplify_gen_subreg (DImode, operands[1], mode, 0),
+ DImode);
+ rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode,
+ GET_MODE_SIZE (DImode)),
+ simplify_gen_subreg (DImode, operands[1], mode,
+ GET_MODE_SIZE (DImode)),
+ DImode);
+ return;
+ }
+
/* FIXME: In the long term, this switch statement should go away
and be replaced by a sequence of tests based on things like
mode == Pmode. */
@@ -8302,7 +8321,8 @@ addrs_ok_for_quad_peep (rtx addr1, rtx addr2)
enum reg_class
secondary_reload_class (enum reg_class class,
- enum machine_mode mode ATTRIBUTE_UNUSED, rtx in)
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx in)
{
int regno;
@@ -10007,73 +10027,72 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
emit_move_insn (dest, target);
}
-/* Called by splitter for multireg moves.
- Input:
- operands[0] : Destination of move
- operands[1] : Source of move
-
- Output:
- operands[2-n] : Destination slots
- operands[n-m] : Source slots
- where n = 2 + HARD_REGNO_NREGS (reg, GET_MODE (operands[0]))
- m = 2 + 2 * HARD_REGNO_NREGS (reg, GET_MODE (operands[0])) - 1
+/* Emit instructions to move SRC to DST. Called by splitters for
+ multi-register moves. It will emit at most one instruction for
+ each register that is accessed; that is, it won't emit li/lis pairs
+ (or equivalent for 64-bit code). One of SRC or DST must be a hard
+ register. */
- Splits the move of operands[1] to operands[0].
- This is done, if GPRs are one of the operands. In this case
- a sequence of simple move insns has to be issued. The sequence of these
- move insns has to be done in correct order to avoid early clobber of the
- base register or destructive overlap of registers.
-*/
-
void
-rs6000_split_multireg_move (rtx *operands)
+rs6000_split_multireg_move (rtx dst, rtx src)
{
- int nregs, reg, i, j, used_update = 0;
- enum machine_mode mode;
- rtx dst = operands[0];
- rtx src = operands[1];
- rtx insn = 0;
-
- /* Calculate number to move (2/4 for 32/64 bit mode). */
-
- reg = REG_P (operands[0]) ? REGNO (operands[0]) : REGNO (operands[1]);
- mode = GET_MODE (operands[0]);
- nregs = HARD_REGNO_NREGS (reg, mode);
+ /* The register number of the first register being moved. */
+ int reg;
+ /* The mode that is to be moved. */
+ enum machine_mode mode;
+ /* The mode that the move is being done in, and its size. */
+ enum machine_mode reg_mode;
+ int reg_mode_size;
+ /* The number of registers that will be moved. */
+ int nregs;
+
+ reg = REG_P (dst) ? REGNO (dst) : REGNO (src);
+ mode = GET_MODE (dst);
+ nregs = HARD_REGNO_NREGS (reg, mode);
+ if (FP_REGNO_P (reg))
+ reg_mode = DFmode;
+ else if (ALTIVEC_REGNO_P (reg))
+ reg_mode = V16QImode;
+ else
+ reg_mode = word_mode;
+ reg_mode_size = GET_MODE_SIZE (reg_mode);
- if (REG_P (operands[1])
- && REG_P (operands[0])
- && (REGNO (operands[1]) < REGNO (operands[0])))
- {
- /* Move register range backwards, if we have destructive overlap. */
-
- j = nregs;
- for (i = 0; i < nregs; i++)
- {
- j--;
- operands[i+2] = operand_subword (operands[0], j, 0, mode);
- operands[i+2+nregs] =
- operand_subword (operands[1], j, 0, mode);
- }
- }
+ if (reg_mode_size * nregs != GET_MODE_SIZE (mode))
+ abort ();
+
+ if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
+ {
+ /* Move register range backwards, if we might have destructive
+ overlap. */
+ int i;
+ for (i = nregs - 1; i >= 0; i--)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ simplify_gen_subreg (reg_mode, dst, mode,
+ i * reg_mode_size),
+ simplify_gen_subreg (reg_mode, src, mode,
+ i * reg_mode_size)));
+ }
else
{
- j = -1;
+ int i;
+ int j = -1;
+ bool used_update = false;
- if (GET_CODE (operands[1]) == MEM)
+ if (GET_CODE (src) == MEM && INT_REGNO_P (reg))
{
rtx breg;
- if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC
- || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ if (GET_CODE (XEXP (src, 0)) == PRE_INC
+ || GET_CODE (XEXP (src, 0)) == PRE_DEC)
{
rtx delta_rtx;
- breg = XEXP (XEXP (operands[1], 0), 0);
- delta_rtx = GET_CODE (XEXP (operands[1], 0)) == PRE_INC
- ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])))
- : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[1])));
- insn = emit_insn (TARGET_32BIT
- ? gen_addsi3 (breg, breg, delta_rtx)
- : gen_adddi3 (breg, breg, delta_rtx));
+ breg = XEXP (XEXP (src, 0), 0);
+ delta_rtx = GET_CODE (XEXP (src, 0)) == PRE_INC
+ ? GEN_INT (GET_MODE_SIZE (GET_MODE (src)))
+ : GEN_INT (-GET_MODE_SIZE (GET_MODE (src)));
+ emit_insn (TARGET_32BIT
+ ? gen_addsi3 (breg, breg, delta_rtx)
+ : gen_adddi3 (breg, breg, delta_rtx));
src = gen_rtx_MEM (mode, breg);
}
@@ -10093,35 +10112,34 @@ rs6000_split_multireg_move (rtx *operands)
j = REGNO (breg) - REGNO (dst);
}
- if (GET_CODE (operands[0]) == MEM)
+ if (GET_CODE (dst) == MEM && INT_REGNO_P (reg))
{
rtx breg;
- if (GET_CODE (XEXP (operands[0], 0)) == PRE_INC
- || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ if (GET_CODE (XEXP (dst, 0)) == PRE_INC
+ || GET_CODE (XEXP (dst, 0)) == PRE_DEC)
{
rtx delta_rtx;
- breg = XEXP (XEXP (operands[0], 0), 0);
- delta_rtx = GET_CODE (XEXP (operands[0], 0)) == PRE_INC
- ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])))
- : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));
+ breg = XEXP (XEXP (dst, 0), 0);
+ delta_rtx = GET_CODE (XEXP (dst, 0)) == PRE_INC
+ ? GEN_INT (GET_MODE_SIZE (GET_MODE (dst)))
+ : GEN_INT (-GET_MODE_SIZE (GET_MODE (dst)));
/* We have to update the breg before doing the store.
Use store with update, if available. */
if (TARGET_UPDATE)
{
- insn = emit_insn (TARGET_32BIT
- ? gen_movsi_update (breg, breg, delta_rtx,
- operand_subword (src, 0, 0, mode))
- : gen_movdi_update (breg, breg, delta_rtx,
- operand_subword (src, 0, 0, mode)));
- used_update = 1;
+ rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0);
+ emit_insn (TARGET_32BIT
+ ? gen_movsi_update (breg, breg, delta_rtx, nsrc)
+ : gen_movdi_update (breg, breg, delta_rtx, nsrc));
+ used_update = true;
}
else
- insn = emit_insn (TARGET_32BIT
- ? gen_addsi3 (breg, breg, delta_rtx)
- : gen_adddi3 (breg, breg, delta_rtx));
+ emit_insn (TARGET_32BIT
+ ? gen_addsi3 (breg, breg, delta_rtx)
+ : gen_adddi3 (breg, breg, delta_rtx));
dst = gen_rtx_MEM (mode, breg);
}
}
@@ -10133,15 +10151,16 @@ rs6000_split_multireg_move (rtx *operands)
if (j == nregs)
j = 0;
- operands[i+2] = operand_subword (dst, j, 0, mode);
- operands[i+2+nregs] = operand_subword (src, j, 0, mode);
-
+ /* If compiler already emited move of first word by
+ store with update, no need to do anything. */
if (j == 0 && used_update)
- {
- /* Already emited move of first word by
- store with update -> emit dead insn instead (r := r). */
- operands[i+2] = operands[i+2+nregs];
- }
+ continue;
+
+ emit_insn (gen_rtx_SET (VOIDmode,
+ simplify_gen_subreg (reg_mode, dst, mode,
+ j * reg_mode_size),
+ simplify_gen_subreg (reg_mode, src, mode,
+ j * reg_mode_size)));
}
}
}
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index f0f351e..761873d 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1480,11 +1480,14 @@ enum reg_class
/* Return a class of registers that cannot change FROM mode to TO mode. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
- ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) \
+ && GET_MODE_SIZE (FROM) >= 8 && GET_MODE_SIZE (TO) >= 8) \
+ ? 0 \
+ : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
: (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \
- ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
+ ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
: 0)
/* Stack layout; function entry, exit and calling. */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 19b263a..50c3595 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -8206,110 +8206,21 @@
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }")
-(define_insn "*movtf_internal"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=f,f,m,!r,!r,!r")
- (match_operand:TF 1 "input_operand" "f,m,f,G,H,F"))]
+; It's important to list the o->f and f->o moves before f->f because
+; otherwise reload, given m->f, will try to pick f->f and reload it,
+; which doesn't make progress.
+(define_insn_and_split "*movtf_internal"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,f,rm,r")
+ (match_operand:TF 1 "input_operand" "f,o,f,r,mGHF"))]
"(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
&& (gpc_reg_operand (operands[0], TFmode)
|| gpc_reg_operand (operands[1], TFmode))"
- "*
-{
- switch (which_alternative)
- {
- default:
- abort ();
- 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 \"fmr %L0,%L1\;fmr %0,%1\";
- else
- return \"fmr %0,%1\;fmr %L0,%L1\";
- case 1:
- return \"lfd %0,%1\;lfd %L0,%Y1\";
- case 2:
- return \"stfd %1,%0\;stfd %L1,%Y0\";
- case 3:
- case 4:
- case 5:
- return \"#\";
- }
-}"
- [(set_attr "type" "fp,fpload,fpstore,*,*,*")
- (set_attr "length" "8,8,8,12,16,20")])
-
-(define_split
- [(set (match_operand:TF 0 "gpc_reg_operand" "")
- (match_operand:TF 1 "easy_fp_constant" ""))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
- && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_POWERPC64
- && TARGET_LONG_DOUBLE_128 && reload_completed
- && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) <= 31))"
- [(set (match_dup 2) (match_dup 6))
- (set (match_dup 3) (match_dup 7))
- (set (match_dup 4) (match_dup 8))
- (set (match_dup 5) (match_dup 9))]
- "
-{
- long l[4];
- REAL_VALUE_TYPE rv;
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, l);
-
- operands[2] = operand_subword (operands[0], 0, 0, TFmode);
- operands[3] = operand_subword (operands[0], 1, 0, TFmode);
- operands[4] = operand_subword (operands[0], 2, 0, TFmode);
- operands[5] = operand_subword (operands[0], 3, 0, TFmode);
- operands[6] = gen_int_mode (l[0], SImode);
- operands[7] = gen_int_mode (l[1], SImode);
- operands[8] = gen_int_mode (l[2], SImode);
- operands[9] = gen_int_mode (l[3], SImode);
-}")
-
-(define_split
- [(set (match_operand:TF 0 "gpc_reg_operand" "")
- (match_operand:TF 1 "easy_fp_constant" ""))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
- && TARGET_LONG_DOUBLE_128 && reload_completed
- && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) <= 31))"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
- "
-{
- long l[4];
- REAL_VALUE_TYPE rv;
-#if HOST_BITS_PER_WIDE_INT >= 64
- HOST_WIDE_INT val;
-#endif
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, l);
-
- operands[2] = gen_lowpart (DImode, operands[0]);
- operands[3] = gen_highpart (DImode, operands[0]);
-#if HOST_BITS_PER_WIDE_INT >= 64
- val = ((HOST_WIDE_INT)(unsigned long)l[0] << 32
- | ((HOST_WIDE_INT)(unsigned long)l[1]));
- operands[4] = gen_int_mode (val, DImode);
-
- val = ((HOST_WIDE_INT)(unsigned long)l[2] << 32
- | ((HOST_WIDE_INT)(unsigned long)l[3]));
- operands[5] = gen_int_mode (val, DImode);
-#else
- operands[4] = immed_double_const (l[1], l[0], DImode);
- operands[5] = immed_double_const (l[3], l[2], DImode);
-#endif
-}")
+ "#"
+ "reload_completed"
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
+ [(set_attr "length" "8,8,8,20,20")])
(define_insn "extenddftf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
@@ -8527,31 +8438,12 @@
}")
(define_split
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (match_operand:DI 1 "const_double_operand" ""))]
- "HOST_BITS_PER_WIDE_INT == 32 && ! TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
- "
-{
- operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
- DImode);
- operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
- DImode);
- operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
- operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-}")
-
-(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "input_operand" ""))]
"reload_completed && !TARGET_POWERPC64
&& gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-"{
- rs6000_split_multireg_move (operands);
-}")
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_split
[(set (match_operand:TI 0 "gpc_reg_operand" "")
@@ -8780,28 +8672,10 @@
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "input_operand" ""))]
- "reload_completed && TARGET_POWERPC64
- && gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-"{
- rs6000_split_multireg_move (operands);
-}")
-
-(define_split
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "input_operand" ""))]
- "reload_completed && !TARGET_POWERPC64
+ "reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 6))
- (set (match_dup 3) (match_dup 7))
- (set (match_dup 4) (match_dup 8))
- (set (match_dup 5) (match_dup 9))]
-"{
- rs6000_split_multireg_move (operands);
-}")
-
-
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_expand "load_multiple"
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")
diff --git a/gcc/testsuite/gcc.c-torture/compile/20031208-1.c b/gcc/testsuite/gcc.c-torture/compile/20031208-1.c
new file mode 100644
index 0000000..02586df
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20031208-1.c
@@ -0,0 +1,6 @@
+extern int foo(int, ...);
+int bar(void) {
+ long double l = 1.2345E6;
+ foo(0, l);
+ return 0;
+}