alpha.c (alpha_split_tfmode_pair): Rename into alpha_split_tmode_pair.
* config/alpha/alpha.c (alpha_split_tfmode_pair): Rename into alpha_split_tmode_pair. Add 'mode' and 'fixup_overlap' arguments. Test against the appropriate null constant for the mode. If 'fixup_overlap' is true, swap the operands if they overlap. (alpha_split_tfmode_frobsign): Adjust call to alpha_split_tfmode_pair. * config/alpha/alpha-protos.h (alpha_split_tfmode_pair): Rename into alpha_split_tmode_pair and adjust for above change. * config/alpha/alpha.md (movtf_internal): Adjust call to alpha_split_tfmode_pair and rely on it to swap the operands. (movti_internal): New insn and post-reload splitter. (movti): New expander. From-SVN: r109882
This commit is contained in:
parent
17dcd421bb
commit
b2f39494f9
|
@ -1,3 +1,17 @@
|
|||
2006-01-18 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* config/alpha/alpha.c (alpha_split_tfmode_pair): Rename into
|
||||
alpha_split_tmode_pair. Add 'mode' and 'fixup_overlap' arguments.
|
||||
Test against the appropriate null constant for the mode.
|
||||
If 'fixup_overlap' is true, swap the operands if they overlap.
|
||||
(alpha_split_tfmode_frobsign): Adjust call to alpha_split_tfmode_pair.
|
||||
* config/alpha/alpha-protos.h (alpha_split_tfmode_pair): Rename into
|
||||
alpha_split_tmode_pair and adjust for above change.
|
||||
* config/alpha/alpha.md (movtf_internal): Adjust call to
|
||||
alpha_split_tfmode_pair and rely on it to swap the operands.
|
||||
(movti_internal): New insn and post-reload splitter.
|
||||
(movti): New expander.
|
||||
|
||||
2006-01-18 Philippe De Muyter <phdm@macqel.be>
|
||||
|
||||
* config/m68k/m68k.md (*addsi3_5200): Allow addq/subq to memory
|
||||
|
|
|
@ -64,7 +64,7 @@ extern bool alpha_expand_mov_nobwx (enum machine_mode, rtx *);
|
|||
extern void alpha_expand_movmisalign (enum machine_mode, rtx *);
|
||||
extern void alpha_emit_floatuns (rtx[]);
|
||||
extern rtx alpha_emit_conditional_move (rtx, enum machine_mode);
|
||||
extern void alpha_split_tfmode_pair (rtx[]);
|
||||
extern void alpha_split_tmode_pair (rtx[], enum machine_mode, bool);
|
||||
extern void alpha_split_tfmode_frobsign (rtx[], rtx (*)(rtx, rtx, rtx));
|
||||
extern void alpha_expand_unaligned_load (rtx, rtx, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, int);
|
||||
|
|
|
@ -3198,12 +3198,17 @@ alpha_emit_xfloating_cvt (enum rtx_code orig_code, rtx operands[])
|
|||
operands[1]));
|
||||
}
|
||||
|
||||
/* Split a TFmode OP[1] into DImode OP[2,3] and likewise for
|
||||
OP[0] into OP[0,1]. Naturally, output operand ordering is
|
||||
little-endian. */
|
||||
|
||||
/* Split a TImode or TFmode move from OP[1] to OP[0] into a pair of
|
||||
DImode moves from OP[2,3] to OP[0,1]. If FIXUP_OVERLAP is true,
|
||||
guarantee that the sequence
|
||||
set (OP[0] OP[2])
|
||||
set (OP[1] OP[3])
|
||||
is valid. Naturally, output operand ordering is little-endian.
|
||||
This is used by *movtf_internal and *movti_internal. */
|
||||
|
||||
void
|
||||
alpha_split_tfmode_pair (rtx operands[4])
|
||||
alpha_split_tmode_pair (rtx operands[4], enum machine_mode mode,
|
||||
bool fixup_overlap)
|
||||
{
|
||||
switch (GET_CODE (operands[1]))
|
||||
{
|
||||
|
@ -3217,8 +3222,9 @@ alpha_split_tfmode_pair (rtx operands[4])
|
|||
operands[2] = adjust_address (operands[1], DImode, 0);
|
||||
break;
|
||||
|
||||
case CONST_INT:
|
||||
case CONST_DOUBLE:
|
||||
gcc_assert (operands[1] == CONST0_RTX (TFmode));
|
||||
gcc_assert (operands[1] == CONST0_RTX (mode));
|
||||
operands[2] = operands[3] = const0_rtx;
|
||||
break;
|
||||
|
||||
|
@ -3241,6 +3247,13 @@ alpha_split_tfmode_pair (rtx operands[4])
|
|||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (fixup_overlap && reg_overlap_mentioned_p (operands[0], operands[3]))
|
||||
{
|
||||
rtx tmp;
|
||||
tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
|
||||
tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement negtf2 or abstf2. Op0 is destination, op1 is source,
|
||||
|
@ -3254,7 +3267,7 @@ alpha_split_tfmode_frobsign (rtx operands[3], rtx (*operation) (rtx, rtx, rtx))
|
|||
rtx scratch;
|
||||
int move;
|
||||
|
||||
alpha_split_tfmode_pair (operands);
|
||||
alpha_split_tmode_pair (operands, TFmode, false);
|
||||
|
||||
/* Detect three flavors of operand overlap. */
|
||||
move = 1;
|
||||
|
|
|
@ -5176,13 +5176,7 @@
|
|||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 1) (match_dup 3))]
|
||||
{
|
||||
alpha_split_tfmode_pair (operands);
|
||||
if (reg_overlap_mentioned_p (operands[0], operands[3]))
|
||||
{
|
||||
rtx tmp;
|
||||
tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
|
||||
tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
|
||||
}
|
||||
alpha_split_tmode_pair (operands, TFmode, true);
|
||||
})
|
||||
|
||||
(define_expand "movsf"
|
||||
|
@ -5668,6 +5662,80 @@
|
|||
FAIL;
|
||||
})
|
||||
|
||||
;; We need to prevent reload from splitting TImode moves, because it
|
||||
;; might decide to overwrite a pointer with the value it points to.
|
||||
;; In that case we have to do the loads in the appropriate order so
|
||||
;; that the pointer is not destroyed too early.
|
||||
|
||||
(define_insn_and_split "*movti_internal"
|
||||
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
|
||||
(match_operand:TI 1 "input_operand" "roJ,rJ"))]
|
||||
"(register_operand (operands[0], TImode)
|
||||
/* Prevent rematerialization of constants. */
|
||||
&& ! CONSTANT_P (operands[1]))
|
||||
|| reg_or_0_operand (operands[1], TImode)"
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 1) (match_dup 3))]
|
||||
{
|
||||
alpha_split_tmode_pair (operands, TImode, true);
|
||||
})
|
||||
|
||||
(define_expand "movti"
|
||||
[(set (match_operand:TI 0 "nonimmediate_operand" "")
|
||||
(match_operand:TI 1 "general_operand" ""))]
|
||||
""
|
||||
{
|
||||
if (GET_CODE (operands[0]) == MEM
|
||||
&& ! reg_or_0_operand (operands[1], TImode))
|
||||
operands[1] = force_reg (TImode, operands[1]);
|
||||
|
||||
if (operands[1] == const0_rtx)
|
||||
;
|
||||
/* We must put 64-bit constants in memory. We could keep the
|
||||
32-bit constants in TImode and rely on the splitter, but
|
||||
this doesn't seem to be worth the pain. */
|
||||
else if (GET_CODE (operands[1]) == CONST_INT
|
||||
|| GET_CODE (operands[1]) == CONST_DOUBLE)
|
||||
{
|
||||
rtx in[2], out[2], target;
|
||||
|
||||
gcc_assert (!no_new_pseudos);
|
||||
|
||||
split_double (operands[1], &in[0], &in[1]);
|
||||
|
||||
if (in[0] == const0_rtx)
|
||||
out[0] = const0_rtx;
|
||||
else
|
||||
{
|
||||
out[0] = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_movdi (out[0], in[0]));
|
||||
}
|
||||
|
||||
if (in[1] == const0_rtx)
|
||||
out[1] = const0_rtx;
|
||||
else
|
||||
{
|
||||
out[1] = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_movdi (out[1], in[1]));
|
||||
}
|
||||
|
||||
if (GET_CODE (operands[0]) != REG)
|
||||
target = gen_reg_rtx (TImode);
|
||||
else
|
||||
target = operands[0];
|
||||
|
||||
emit_insn (gen_movdi (gen_rtx_SUBREG (DImode, target, 0), out[0]));
|
||||
emit_insn (gen_movdi (gen_rtx_SUBREG (DImode, target, 8), out[1]));
|
||||
|
||||
if (target != operands[0])
|
||||
emit_insn (gen_rtx_SET (VOIDmode, operands[0], target));
|
||||
|
||||
DONE;
|
||||
}
|
||||
})
|
||||
|
||||
;; These are the partial-word cases.
|
||||
;;
|
||||
;; First we have the code to load an aligned word. Operand 0 is the register
|
||||
|
|
Loading…
Reference in New Issue