summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-01-19 20:18:08 -0800
committerRichard Henderson <rth@gcc.gnu.org>2005-01-19 20:18:08 -0800
commit539eaa3aaaf75211773d0861322b0e3bde6f7df9 (patch)
tree57795ca936236a40d7b3f6d2d97ea19ea21faac5 /gcc/expr.c
parent72910a0b3b6c68d3ca4d636b9a06923c07a45df8 (diff)
downloadgcc-539eaa3aaaf75211773d0861322b0e3bde6f7df9.tar.gz
re PR middle-end/19304 (wrong code for spec test from emit_move_change_mode)
PR middle-end/19304 * expr.c (emit_move_change_mode): New argument force; use simplify_gen_subreg if true. (emit_move_via_alt_mode): Merge into ... (emit_move_via_integer): ... here. (emit_move_ccmode): Use emit_move_change_mode directly. From-SVN: r93944
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 1d157a1426f..cc725e4d79e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2707,13 +2707,14 @@ read_complex_part (rtx cplx, bool imag_p)
true, NULL_RTX, imode, imode);
}
-/* A subroutine of emit_move_via_alt_mode. Yet another lowpart generator.
+/* A subroutine of emit_move_insn_1. Yet another lowpart generator.
NEW_MODE and OLD_MODE are the same size. Return NULL if X cannot be
- represented in NEW_MODE. */
+ represented in NEW_MODE. If FORCE is true, this will never happen, as
+ we'll force-create a SUBREG if needed. */
static rtx
emit_move_change_mode (enum machine_mode new_mode,
- enum machine_mode old_mode, rtx x)
+ enum machine_mode old_mode, rtx x, bool force)
{
rtx ret;
@@ -2735,31 +2736,18 @@ emit_move_change_mode (enum machine_mode new_mode,
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);
+ /* Except, of course, when FORCE is true, when this is exactly what
+ we want. Which is needed for CCmodes on some targets. */
+ if (force)
+ ret = simplify_gen_subreg (new_mode, x, old_mode, 0);
+ else
+ 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));
-}
-
-/* A subroutine of emit_move_insn_1. Generate a move from Y into X using
an integer mode of the same size as MODE. Returns the instruction
emitted, or NULL if such a move could not be generated. */
@@ -2779,7 +2767,13 @@ emit_move_via_integer (enum machine_mode mode, rtx x, rtx y)
if (code == CODE_FOR_nothing)
return NULL_RTX;
- return emit_move_via_alt_mode (imode, mode, code, x, y);
+ x = emit_move_change_mode (imode, mode, x, false);
+ if (x == NULL_RTX)
+ return NULL_RTX;
+ y = emit_move_change_mode (imode, mode, y, false);
+ if (y == NULL_RTX)
+ return NULL_RTX;
+ return emit_insn (GEN_FCN (code) (x, y));
}
/* A subroutine of emit_move_insn_1. X is a push_operand in MODE.
@@ -2943,7 +2937,11 @@ emit_move_ccmode (enum machine_mode mode, rtx x, rtx y)
{
enum insn_code code = mov_optab->handlers[CCmode].insn_code;
if (code != CODE_FOR_nothing)
- return emit_move_via_alt_mode (CCmode, mode, code, x, y);
+ {
+ x = emit_move_change_mode (CCmode, mode, x, true);
+ y = emit_move_change_mode (CCmode, mode, y, true);
+ return emit_insn (GEN_FCN (code) (x, y));
+ }
}
/* Otherwise, find the MODE_INT mode of the same width. */