diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 66 |
1 files changed, 40 insertions, 26 deletions
@@ -3081,7 +3081,7 @@ emit_move_multi_word (enum machine_mode mode, rtx x, rtx y) be able to get a part of Y. */ if (ypart == 0 && CONSTANT_P (y)) { - y = force_const_mem (mode, y); + y = use_anchored_address (force_const_mem (mode, y)); ypart = operand_subword (y, i, 1, mode); } else if (ypart == 0) @@ -3194,6 +3194,8 @@ emit_move_insn (rtx x, rtx y) of the non-legitimate constant. */ if (!y) y = y_cst; + else + y = use_anchored_address (y); } } @@ -6280,6 +6282,20 @@ expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1, } +/* Return a MEM that constains constant EXP. DEFER is as for + output_constant_def and MODIFIER is as for expand_expr. */ + +static rtx +expand_expr_constant (tree exp, int defer, enum expand_modifier modifier) +{ + rtx mem; + + mem = output_constant_def (exp, defer); + if (modifier != EXPAND_INITIALIZER) + mem = use_anchored_address (mem); + return mem; +} + /* A subroutine of expand_expr_addr_expr. Evaluate the address of EXP. The TARGET, TMODE and MODIFIER arguments are as for expand_expr. */ @@ -6301,14 +6317,14 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode, exception here is STRING_CST. */ if (TREE_CODE (exp) == CONSTRUCTOR || CONSTANT_CLASS_P (exp)) - return XEXP (output_constant_def (exp, 0), 0); + return XEXP (expand_expr_constant (exp, 0, modifier), 0); /* Everything must be something allowed by is_gimple_addressable. */ switch (TREE_CODE (exp)) { case INDIRECT_REF: /* This case will happen via recursion for &a->b. */ - return expand_expr (TREE_OPERAND (exp, 0), target, tmode, EXPAND_NORMAL); + return expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); case CONST_DECL: /* Recurse and make the output_constant_def clause above handle this. */ @@ -6579,7 +6595,7 @@ static rtx expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier modifier, rtx *alt_rtl) { - rtx op0, op1, temp; + rtx op0, op1, temp, decl_rtl; tree type = TREE_TYPE (exp); int unsignedp; enum machine_mode mode; @@ -6701,7 +6717,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, case FUNCTION_DECL: case RESULT_DECL: - gcc_assert (DECL_RTL (exp)); + decl_rtl = DECL_RTL (exp); + gcc_assert (decl_rtl); /* Ensure variable marked as used even if it doesn't go through a parser. If it hasn't be used yet, write out an external @@ -6728,27 +6745,24 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, from its initializer, while the initializer is still being parsed. See expand_decl. */ - if (MEM_P (DECL_RTL (exp)) - && REG_P (XEXP (DECL_RTL (exp), 0))) - temp = validize_mem (DECL_RTL (exp)); + if (MEM_P (decl_rtl) && REG_P (XEXP (decl_rtl, 0))) + temp = validize_mem (decl_rtl); /* If DECL_RTL is memory, we are in the normal case and either the address is not valid or it is not a register and -fforce-addr is specified, get the address into a register. */ - else if (MEM_P (DECL_RTL (exp)) - && modifier != EXPAND_CONST_ADDRESS - && modifier != EXPAND_SUM - && modifier != EXPAND_INITIALIZER - && (! memory_address_p (DECL_MODE (exp), - XEXP (DECL_RTL (exp), 0)) - || (flag_force_addr - && !REG_P (XEXP (DECL_RTL (exp), 0))))) + else if (MEM_P (decl_rtl) && modifier != EXPAND_INITIALIZER) { if (alt_rtl) - *alt_rtl = DECL_RTL (exp); - temp = replace_equiv_address (DECL_RTL (exp), - copy_rtx (XEXP (DECL_RTL (exp), 0))); + *alt_rtl = decl_rtl; + decl_rtl = use_anchored_address (decl_rtl); + if (modifier != EXPAND_CONST_ADDRESS + && modifier != EXPAND_SUM + && (!memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0)) + || (flag_force_addr && !REG_P (XEXP (decl_rtl, 0))))) + temp = replace_equiv_address (decl_rtl, + copy_rtx (XEXP (decl_rtl, 0))); } /* If we got something, return it. But first, set the alignment @@ -6765,8 +6779,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, must be a promoted value. We return a SUBREG of the wanted mode, but mark it so that we know that it was already extended. */ - if (REG_P (DECL_RTL (exp)) - && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp)) + if (REG_P (decl_rtl) + && GET_MODE (decl_rtl) != DECL_MODE (exp)) { enum machine_mode pmode; @@ -6775,15 +6789,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, pmode = promote_mode (type, DECL_MODE (exp), &unsignedp, (TREE_CODE (exp) == RESULT_DECL || TREE_CODE (exp) == PARM_DECL) ? 1 : 0); - gcc_assert (GET_MODE (DECL_RTL (exp)) == pmode); + gcc_assert (GET_MODE (decl_rtl) == pmode); - temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp)); + temp = gen_lowpart_SUBREG (mode, decl_rtl); SUBREG_PROMOTED_VAR_P (temp) = 1; SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); return temp; } - return DECL_RTL (exp); + return decl_rtl; case INTEGER_CST: temp = immed_double_const (TREE_INT_CST_LOW (exp), @@ -6852,7 +6866,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, /* ... fall through ... */ case STRING_CST: - temp = output_constant_def (exp, 1); + temp = expand_expr_constant (exp, 1, modifier); /* temp contains a constant address. On RISC machines where a constant address isn't valid, @@ -6953,7 +6967,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, || modifier == EXPAND_CONST_ADDRESS) && TREE_CONSTANT (exp))) { - rtx constructor = output_constant_def (exp, 1); + rtx constructor = expand_expr_constant (exp, 1, modifier); if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER |