+2007-03-01 Richard Henderson <rth@redhat.com>
+
+ * expr.c (emit_move_complex_push): Export.
+ (emit_move_complex_parts): Split out from ...
+ (emit_move_complex): ... here.
+ * expr.h (emit_move_complex_push, emit_move_complex_parts): Declare.
+ * config/i386/i386.md (movcdi): New.
+
2007-03-01 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.c (ix86_modes_tieable_p): Fix typo, use also
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
+;; This expands to what emit_move_complex would generate if we didn't
+;; have a movti pattern. Having this avoids problems with reload on
+;; 32-bit targets when SSE is present, but doesn't seem to be harmful
+;; to have around all the time.
+(define_expand "movcdi"
+ [(set (match_operand:CDI 0 "nonimmediate_operand" "")
+ (match_operand:CDI 1 "general_operand" ""))]
+ ""
+{
+ if (push_operand (operands[0], CDImode))
+ emit_move_complex_push (CDImode, operands[0], operands[1]);
+ else
+ emit_move_complex_parts (operands[0], operands[1]);
+ DONE;
+})
+
(define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "")
(match_operand:SF 1 "general_operand" ""))]
X is known to satisfy push_operand, and MODE is known to be complex.
Returns the last instruction emitted. */
-static rtx
+rtx
emit_move_complex_push (enum machine_mode mode, rtx x, rtx y)
{
enum machine_mode submode = GET_MODE_INNER (mode);
read_complex_part (y, !imag_first));
}
+/* A subroutine of emit_move_complex. Perform the move from Y to X
+ via two moves of the parts. Returns the last instruction emitted. */
+
+rtx
+emit_move_complex_parts (rtx x, rtx y)
+{
+ /* Show the output dies here. This is necessary for SUBREGs
+ of pseudos since we cannot track their lifetimes correctly;
+ hard regs shouldn't appear here except as return values. */
+ if (!reload_completed && !reload_in_progress
+ && REG_P (x) && !reg_overlap_mentioned_p (x, y))
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+
+ write_complex_part (x, read_complex_part (y, false), false);
+ write_complex_part (x, read_complex_part (y, true), true);
+
+ return get_last_insn ();
+}
+
/* A subroutine of emit_move_insn_1. Generate a move from Y into X.
MODE is known to be complex. Returns the last instruction emitted. */
return ret;
}
- /* Show the output dies here. This is necessary for SUBREGs
- of pseudos since we cannot track their lifetimes correctly;
- hard regs shouldn't appear here except as return values. */
- if (!reload_completed && !reload_in_progress
- && REG_P (x) && !reg_overlap_mentioned_p (x, y))
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
-
- write_complex_part (x, read_complex_part (y, false), false);
- write_complex_part (x, read_complex_part (y, true), true);
- return get_last_insn ();
+ return emit_move_complex_parts (x, y);
}
/* A subroutine of emit_move_insn_1. Generate a move from Y into X.
/* Emit insns to set X from Y, with no frills. */
extern rtx emit_move_insn_1 (rtx, rtx);
+extern rtx emit_move_complex_push (enum machine_mode, rtx, rtx);
+extern rtx emit_move_complex_parts (rtx, rtx);
+
/* Push a block of length SIZE (perhaps variable)
and return an rtx to address the beginning of the block. */
extern rtx push_block (rtx, int, int);