aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2007-03-01 08:30:38 -0800
committerRichard Henderson <rth@gcc.gnu.org>2007-03-01 08:30:38 -0800
commitceca734e8f8b368ab4087ce3970118775735f593 (patch)
treeb6d11fc471a5238e81dafa6b6bd684ff01ef7366
parent5f81370d9f02d82b58964b104eb60197b7e773ef (diff)
downloadgcc-ceca734e8f8b368ab4087ce3970118775735f593.zip
gcc-ceca734e8f8b368ab4087ce3970118775735f593.tar.gz
gcc-ceca734e8f8b368ab4087ce3970118775735f593.tar.bz2
expr.c (emit_move_complex_push): Export.
* 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. From-SVN: r122432
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386.md16
-rw-r--r--gcc/expr.c32
-rw-r--r--gcc/expr.h3
4 files changed, 48 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1a6be7b..b0e26a9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+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
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index bb3dd21..409ce0c 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -2266,6 +2266,22 @@
[(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" ""))]
diff --git a/gcc/expr.c b/gcc/expr.c
index f624d95..1dc437c 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2987,7 +2987,7 @@ emit_move_resolve_push (enum machine_mode mode, rtx x)
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);
@@ -3027,6 +3027,25 @@ emit_move_complex_push (enum machine_mode mode, rtx x, rtx y)
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. */
@@ -3081,16 +3100,7 @@ emit_move_complex (enum machine_mode mode, rtx x, rtx y)
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.
diff --git a/gcc/expr.h b/gcc/expr.h
index 32a0a51..bc3feee 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -465,6 +465,9 @@ extern rtx emit_move_insn (rtx, rtx);
/* 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);