aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index b593a51..6442b3d 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4026,6 +4026,7 @@ rtx
store_expr (tree exp, rtx target, int want_value)
{
rtx temp;
+ rtx alt_rtl = NULL_RTX;
int dont_return_target = 0;
int dont_store_target = 0;
@@ -4207,8 +4208,10 @@ store_expr (tree exp, rtx target, int want_value)
}
else
{
- temp = expand_expr (exp, target, GET_MODE (target),
- want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
+ temp = expand_expr_real (exp, target, GET_MODE (target),
+ (want_value & 2
+ ? EXPAND_STACK_PARM : EXPAND_NORMAL),
+ &alt_rtl);
/* Return TARGET if it's a specified hardware register.
If TARGET is a volatile mem ref, either return TARGET
or return a reg copied *from* TARGET; ANSI requires this.
@@ -4256,10 +4259,7 @@ store_expr (tree exp, rtx target, int want_value)
/* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
but TARGET is not valid memory reference, TEMP will differ
from TARGET although it is really the same location. */
- && !(GET_CODE (target) == MEM
- && GET_CODE (XEXP (target, 0)) != QUEUED
- && (!memory_address_p (GET_MODE (target), XEXP (target, 0))
- || (flag_force_addr && !REG_P (XEXP (target, 0)))))
+ && !(alt_rtl && rtx_equal_p (alt_rtl, target))
/* If there's nothing to copy, don't bother. Don't call expr_size
unless necessary, because some front-ends (C++) expr_size-hook
aborts on objects that are not supposed to be bit-copied or
@@ -6200,11 +6200,17 @@ expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
marked TARGET so that it's safe from being trashed by libcalls. We
don't want to use TARGET for anything but the final result;
Intermediate values must go elsewhere. Additionally, calls to
- emit_block_move will be flagged with BLOCK_OP_CALL_PARM. */
+ emit_block_move will be flagged with BLOCK_OP_CALL_PARM.
+
+ If EXP is a VAR_DECL whose DECL_RTL was a MEM with an invalid
+ address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the
+ DECL_RTL of the VAR_DECL. *ALT_RTL is also set if EXP is a
+ COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on
+ recursively. */
rtx
-expand_expr (tree exp, rtx target, enum machine_mode tmode,
- enum expand_modifier modifier)
+expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
+ enum expand_modifier modifier, rtx *alt_rtl)
{
rtx op0, op1, temp;
tree type = TREE_TYPE (exp);
@@ -6413,8 +6419,12 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode,
XEXP (DECL_RTL (exp), 0))
|| (flag_force_addr
&& GET_CODE (XEXP (DECL_RTL (exp), 0)) != REG)))
- temp = replace_equiv_address (DECL_RTL (exp),
- copy_rtx (XEXP (DECL_RTL (exp), 0)));
+ {
+ if (alt_rtl)
+ *alt_rtl = DECL_RTL (exp);
+ temp = replace_equiv_address (DECL_RTL (exp),
+ copy_rtx (XEXP (DECL_RTL (exp), 0)));
+ }
/* If we got something, return it. But first, set the alignment
if the address is a register. */
@@ -6741,6 +6751,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode,
}
preserve_rtl_expr_result (RTL_EXPR_RTL (exp));
free_temps_for_rtl_expr (exp);
+ if (alt_rtl)
+ *alt_rtl = RTL_EXPR_ALT_RTL (exp);
return RTL_EXPR_RTL (exp);
case CONSTRUCTOR:
@@ -7465,7 +7477,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode,
if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
== BUILT_IN_FRONTEND)
return (*lang_hooks.expand_expr) (exp, original_target,
- tmode, modifier);
+ tmode, modifier,
+ alt_rtl);
else
return expand_builtin (exp, target, subtarget, tmode, ignore);
}
@@ -8228,9 +8241,9 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode,
case COMPOUND_EXPR:
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
emit_queue ();
- return expand_expr (TREE_OPERAND (exp, 1),
- (ignore ? const0_rtx : target),
- VOIDmode, modifier);
+ return expand_expr_real (TREE_OPERAND (exp, 1),
+ (ignore ? const0_rtx : target),
+ VOIDmode, modifier, alt_rtl);
case COND_EXPR:
/* If we would have a "singleton" (see below) were it not for a
@@ -9043,7 +9056,8 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode,
abort ();
default:
- return (*lang_hooks.expand_expr) (exp, original_target, tmode, modifier);
+ return (*lang_hooks.expand_expr) (exp, original_target, tmode, modifier,
+ alt_rtl);
}
/* Here to do an ordinary binary operator, generating an instruction