summaryrefslogtreecommitdiffstats
path: root/gcc/expr.c
diff options
context:
space:
mode:
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1999-09-22 21:37:20 +0000
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1999-09-22 21:37:20 +0000
commit5b5abf88e8a72d8085fb9d77b3c42806cee78fd0 (patch)
tree57b94d994167c688cb82c4a1fe633296abed1717 /gcc/expr.c
parent1b6f11e262a982d4891d938f6f8164e5c8187bd1 (diff)
downloadppe42-gcc-5b5abf88e8a72d8085fb9d77b3c42806cee78fd0.tar.gz
ppe42-gcc-5b5abf88e8a72d8085fb9d77b3c42806cee78fd0.zip
Fix complex-5.c problem
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@29604 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 39bfb4944ed..fc08068e5aa 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2630,6 +2630,55 @@ emit_move_insn_1 (x, y)
}
else
{
+ /* If this is a complex value with each part being smaller than a
+ word, the usual calling sequence will likely pack the pieces into
+ a single register. Unfortunately, SUBREG of hard registers only
+ deals in terms of words, so we have a problem converting input
+ arguments to the CONCAT of two registers that is used elsewhere
+ for complex values. If this is before reload, we can copy it into
+ memory and reload. FIXME, we should see about using extract and
+ insert on integer registers, but complex short and complex char
+ variables should be rarely used. */
+ if (GET_MODE_BITSIZE (mode) < 2*BITS_PER_WORD
+ && (reload_in_progress | reload_completed) == 0)
+ {
+ int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
+ int packed_src_p = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
+
+ if (packed_dest_p || packed_src_p)
+ {
+ enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
+ ? MODE_FLOAT : MODE_INT);
+
+ enum machine_mode reg_mode =
+ mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
+
+ if (reg_mode != BLKmode)
+ {
+ rtx mem = assign_stack_temp (reg_mode,
+ GET_MODE_SIZE (mode), 0);
+
+ rtx cmem = change_address (mem, mode, NULL_RTX);
+
+ current_function->cannot_inline
+ = "function uses short complex types";
+
+ if (packed_dest_p)
+ {
+ rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
+ emit_move_insn_1 (cmem, y);
+ return emit_move_insn_1 (sreg, mem);
+ }
+ else
+ {
+ rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
+ emit_move_insn_1 (mem, sreg);
+ return emit_move_insn_1 (x, cmem);
+ }
+ }
+ }
+ }
+
/* Show the output dies here. This is necessary for pseudos;
hard regs shouldn't appear here except as return values.
We never want to emit such a clobber after reload. */
OpenPOWER on IntegriCloud