aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index ab7cf930d8b..136019432b3 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -155,7 +155,8 @@ static void expand_operands (tree, tree, rtx, rtx*, rtx*,
static rtx reduce_to_bit_field_precision (rtx, rtx, tree);
static rtx do_store_flag (tree, rtx, enum machine_mode, int);
#ifdef PUSH_ROUNDING
-static void emit_single_push_insn (enum machine_mode, rtx, tree);
+/* APPLE LOCAL radar 4087332 */
+static void emit_single_push_insn (enum machine_mode, rtx, tree, rtx);
#endif
static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
static rtx const_vector_from_tree (tree);
@@ -1084,7 +1085,8 @@ move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
else
{
#ifdef PUSH_ROUNDING
- emit_single_push_insn (mode, from1, NULL);
+ /* APPLE LOCAL radar 4087332 */
+ emit_single_push_insn (mode, from1, NULL, NULL_RTX);
#else
gcc_unreachable ();
#endif
@@ -2877,19 +2879,14 @@ emit_move_complex (enum machine_mode mode, rtx x, rtx y)
if (push_operand (x, mode))
return emit_move_complex_push (mode, x, y);
- /* For memory to memory moves, optimal behavior can be had with the
- existing block move logic. */
- if (MEM_P (x) && MEM_P (y))
- {
- emit_block_move (x, y, GEN_INT (GET_MODE_SIZE (mode)),
- BLOCK_OP_NO_LIBCALL);
- return get_last_insn ();
- }
-
/* See if we can coerce the target into moving both values at once. */
+ /* Move floating point as parts. */
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+ && mov_optab->handlers[GET_MODE_INNER (mode)].insn_code != CODE_FOR_nothing)
+ try_int = false;
/* Not possible if the values are inherently not adjacent. */
- if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
+ else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
try_int = false;
/* Is possible if both are registers (or subregs of registers). */
else if (register_operand (x, mode) && register_operand (y, mode))
@@ -2907,7 +2904,18 @@ emit_move_complex (enum machine_mode mode, rtx x, rtx y)
if (try_int)
{
- rtx ret = emit_move_via_integer (mode, x, y);
+ rtx ret;
+
+ /* For memory to memory moves, optimal behavior can be had with the
+ existing block move logic. */
+ if (MEM_P (x) && MEM_P (y))
+ {
+ emit_block_move (x, y, GEN_INT (GET_MODE_SIZE (mode)),
+ BLOCK_OP_NO_LIBCALL);
+ return get_last_insn ();
+ }
+
+ ret = emit_move_via_integer (mode, x, y);
if (ret)
return ret;
}
@@ -3243,7 +3251,8 @@ push_block (rtx size, int extra, int below)
/* Emit single push insn. */
static void
-emit_single_push_insn (enum machine_mode mode, rtx x, tree type)
+/* APPLE LOCAL radar 4087332 */
+emit_single_push_insn (enum machine_mode mode, rtx x, tree type, rtx args_so_far)
{
rtx dest_addr;
unsigned rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
@@ -3252,6 +3261,22 @@ emit_single_push_insn (enum machine_mode mode, rtx x, tree type)
insn_operand_predicate_fn pred;
stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
+ /* APPLE LOCAL begin radar 4087332 */
+ if (args_so_far != NULL_RTX && GET_CODE (args_so_far) == CONST_INT)
+ {
+ int offset = INTVAL (args_so_far);
+ unsigned int unit_stack_boundary = cfun->preferred_stack_boundary / BITS_PER_UNIT;
+ if (!(offset % unit_stack_boundary) && (stack_pointer_delta % unit_stack_boundary))
+ {
+ /* argument must be aligned on stack boundary, but it is not.
+ align 'sp' before the push. */
+ int delta = unit_stack_boundary - (stack_pointer_delta % unit_stack_boundary);
+ expand_simple_binop (Pmode, PLUS, stack_pointer_rtx,
+ GEN_INT (-delta), stack_pointer_rtx, 1, OPTAB_DIRECT);
+ stack_pointer_delta += delta;
+ }
+ }
+ /* APPLE LOCAL end radar 4087332 */
/* If there is push pattern, use it. Otherwise try old way of throwing
MEM representing push operation to move expander. */
icode = push_optab->handlers[(int) mode].insn_code;
@@ -3514,7 +3539,8 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
int not_stack;
/* # bytes of start of argument
that we must make space for but need not store. */
- int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
+ /* APPLE LOCAL mainline 2005-04-21 */
+ int offset = partial % (PARM_BOUNDARY / BITS_PER_UNIT);
int args_offset = INTVAL (args_so_far);
int skip;
@@ -3531,9 +3557,12 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
if (args_addr == 0)
offset = 0;
+ /* APPLE LOCAL begin mainline 2005-04-21 */
/* Now NOT_STACK gets the number of words that we don't need to
- allocate on the stack. */
+ allocate on the stack. Convert OFFSET to words too. */
not_stack = (partial - offset) / UNITS_PER_WORD;
+ offset /= UNITS_PER_WORD;
+ /* APPLE LOCAL end mainline 2005-04-21 */
/* If the partial register-part of the arg counts in its stack size,
skip the part of stack space corresponding to the registers.
@@ -3580,7 +3609,8 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
#ifdef PUSH_ROUNDING
if (args_addr == 0 && PUSH_ARGS)
- emit_single_push_insn (mode, x, type);
+ /* APPLE LOCAL radar 4087332 */
+ emit_single_push_insn (mode, x, type, args_so_far);
else
#endif
{