diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 46 |
1 files changed, 30 insertions, 16 deletions
@@ -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 |