summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-18 11:20:51 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-18 11:20:51 +0000
commit10c77d2b4d6c2244dd7fba02f80733c03c6c4b20 (patch)
tree3fabbd2d1f832606564c35679ccae185098d100c
parent7ec3178a3fc06b6bb7acccfc457f3cccdb5cb670 (diff)
downloadppe42-gcc-10c77d2b4d6c2244dd7fba02f80733c03c6c4b20.tar.gz
ppe42-gcc-10c77d2b4d6c2244dd7fba02f80733c03c6c4b20.zip
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109882 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/alpha/alpha-protos.h2
-rw-r--r--gcc/config/alpha/alpha.c27
-rw-r--r--gcc/config/alpha/alpha.md82
4 files changed, 110 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3513cc2ab05..8bb03f70cc8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 00fc52530b0..f099b4d15e7 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -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);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 244aa271204..c684a4cb1e2 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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;
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index d9f9e09e808..2838499fa86 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -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
OpenPOWER on IntegriCloud