summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-12-12 21:12:43 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-12-12 21:12:43 +0000
commitdf2975206a849aa543bf5bd560a40b31a9db4c54 (patch)
treee9963f8e60cf011e1d03417f864235eb33ad2a54 /gcc/expr.c
parent3f18ef378b0e57ce5a30f2710b79f8035b5f1346 (diff)
downloadgcc-df2975206a849aa543bf5bd560a40b31a9db4c54.tar.gz
* expr.c (emit_move_change_mode): New.
(emit_move_via_alt_mode): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@92065 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 8505d8f676f..fffb60d003b 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2652,46 +2652,55 @@ read_complex_part (rtx cplx, bool imag_p)
true, NULL_RTX, imode, imode);
}
-/* A subroutine of emit_move_insn_1. Generate a move from Y into X using
- ALT_MODE instead of the operand's natural mode, MODE. CODE is the insn
- code for the move in ALT_MODE, and is known to be valid. Returns the
- instruction emitted. */
+/* A subroutine of emit_move_via_alt_mode. Yet another lowpart generator.
+ NEW_MODE and OLD_MODE are the same size. Return NULL if X cannot be
+ represented in NEW_MODE. */
static rtx
-emit_move_via_alt_mode (enum machine_mode alt_mode, enum machine_mode mode,
- enum insn_code code, rtx x, rtx y)
+emit_move_change_mode (enum machine_mode new_mode,
+ enum machine_mode old_mode, rtx x)
{
- /* Get X and Y in ALT_MODE. We can't use gen_lowpart here because it
- may call change_address which is not appropriate if we were
- called when a reload was in progress. We don't have to worry
- about changing the address since the size in bytes is supposed to
- be the same. Copy the MEM to change the mode and move any
- substitutions from the old MEM to the new one. */
+ rtx ret;
- if (reload_in_progress)
+ if (reload_in_progress && MEM_P (x))
{
- rtx x1 = x, y1 = y;
+ /* We can't use gen_lowpart here because it may call change_address
+ which is not appropriate if we were called when a reload was in
+ progress. We don't have to worry about changing the address since
+ the size in bytes is supposed to be the same. Copy the MEM to
+ change the mode and move any substitutions from the old MEM to
+ the new one. */
- x = gen_lowpart_common (alt_mode, x1);
- if (x == 0 && MEM_P (x1))
- {
- x = adjust_address_nv (x1, alt_mode, 0);
- copy_replacements (x1, x);
- }
-
- y = gen_lowpart_common (alt_mode, y1);
- if (y == 0 && MEM_P (y1))
- {
- y = adjust_address_nv (y1, alt_mode, 0);
- copy_replacements (y1, y);
- }
+ ret = adjust_address_nv (x, new_mode, 0);
+ copy_replacements (x, ret);
}
else
{
- x = simplify_gen_subreg (alt_mode, x, mode, 0);
- y = simplify_gen_subreg (alt_mode, y, mode, 0);
+ /* Note that we do want simplify_subreg's behaviour of validating
+ that the new mode is ok for a hard register. If we were to use
+ simplify_gen_subreg, we would create the subreg, but would
+ probably run into the target not being able to implement it. */
+ ret = simplify_subreg (new_mode, x, old_mode, 0);
}
+ return ret;
+}
+
+/* A subroutine of emit_move_insn_1. Generate a move from Y into X using
+ ALT_MODE instead of the operand's natural mode, MODE. CODE is the insn
+ code for the move in ALT_MODE, and is known to be valid. Returns the
+ instruction emitted, or NULL if X or Y cannot be represented in ALT_MODE. */
+
+static rtx
+emit_move_via_alt_mode (enum machine_mode alt_mode, enum machine_mode mode,
+ enum insn_code code, rtx x, rtx y)
+{
+ x = emit_move_change_mode (alt_mode, mode, x);
+ if (x == NULL_RTX)
+ return NULL_RTX;
+ y = emit_move_change_mode (alt_mode, mode, y);
+ if (y == NULL_RTX)
+ return NULL_RTX;
return emit_insn (GEN_FCN (code) (x, y));
}