diff --git a/gcc/reload1.c b/gcc/reload1.c index 30f97c4e9cbb..ad0f8f805881 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -946,7 +946,7 @@ reload (first, global, dumpfile) for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i]) { - rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX); + rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX, 0); if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]), XEXP (x, 0))) @@ -2759,10 +2759,11 @@ static struct rtvec_def *old_asm_operands_vec, *new_asm_operands_vec; the proper thing. */ rtx -eliminate_regs (x, mem_mode, insn) +eliminate_regs (x, mem_mode, insn, storing) rtx x; enum machine_mode mem_mode; rtx insn; + int storing; { enum rtx_code code = GET_CODE (x); struct elim_table *ep; @@ -2819,7 +2820,7 @@ eliminate_regs (x, mem_mode, insn) reference to the pseudo. Ensure we make a copy of the address in case it is shared. */ new = eliminate_regs (reg_equiv_memory_loc[regno], - mem_mode, insn); + mem_mode, insn, 0); if (new != reg_equiv_memory_loc[regno]) { cannot_omit_stores[regno] = 1; @@ -2881,8 +2882,8 @@ eliminate_regs (x, mem_mode, insn) reload. This is the desired action. */ { - rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn); - rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn); + rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0); + rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0); if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) { @@ -2953,9 +2954,9 @@ eliminate_regs (x, mem_mode, insn) case GE: case GT: case GEU: case GTU: case LE: case LT: case LEU: case LTU: { - rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn); + rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0); rtx new1 - = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn) : 0; + = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn, 0) : 0; if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) return gen_rtx (code, GET_MODE (x), new0, new1); @@ -2966,7 +2967,7 @@ eliminate_regs (x, mem_mode, insn) /* If we have something in XEXP (x, 0), the usual case, eliminate it. */ if (XEXP (x, 0)) { - new = eliminate_regs (XEXP (x, 0), mem_mode, insn); + new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0); if (new != XEXP (x, 0)) x = gen_rtx (EXPR_LIST, REG_NOTE_KIND (x), new, XEXP (x, 1)); } @@ -2979,7 +2980,7 @@ eliminate_regs (x, mem_mode, insn) strictly needed, but it simplifies the code. */ if (XEXP (x, 1)) { - new = eliminate_regs (XEXP (x, 1), mem_mode, insn); + new = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0); if (new != XEXP (x, 1)) return gen_rtx (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new); } @@ -3015,7 +3016,7 @@ eliminate_regs (x, mem_mode, insn) case ABS: case SQRT: case FFS: - new = eliminate_regs (XEXP (x, 0), mem_mode, insn); + new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0); if (new != XEXP (x, 0)) return gen_rtx (code, GET_MODE (x), new); return x; @@ -3034,7 +3035,7 @@ eliminate_regs (x, mem_mode, insn) && reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0) { new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))], - mem_mode, insn); + mem_mode, insn, 0); /* If we didn't change anything, we must retain the pseudo. */ if (new == reg_equiv_memory_loc[REGNO (SUBREG_REG (x))]) @@ -3054,27 +3055,37 @@ eliminate_regs (x, mem_mode, insn) } } else - new = eliminate_regs (SUBREG_REG (x), mem_mode, insn); + new = eliminate_regs (SUBREG_REG (x), mem_mode, insn, 0); if (new != XEXP (x, 0)) { - if (GET_CODE (new) == MEM - && (GET_MODE_SIZE (GET_MODE (x)) - <= GET_MODE_SIZE (GET_MODE (new))) + int x_size = GET_MODE_SIZE (GET_MODE (x)); + int new_size = GET_MODE_SIZE (GET_MODE (new)); + + /* When asked to spill a partial word subreg, we need to go + ahead and spill the whole thing against the possibility + that we reload the whole reg and find garbage at the top. */ + if (storing + && GET_CODE (new) == MEM + && x_size < new_size + && ((x_size + UNITS_PER_WORD-1) / UNITS_PER_WORD + == (new_size + UNITS_PER_WORD-1) / UNITS_PER_WORD)) + return new; + else if (GET_CODE (new) == MEM + && x_size <= new_size #ifdef LOAD_EXTEND_OP - /* On these machines we will be reloading what is - inside the SUBREG if it originally was a pseudo and - the inner and outer modes are both a word or - smaller. So leave the SUBREG then. */ - && ! (GET_CODE (SUBREG_REG (x)) == REG - && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD - && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD - && (GET_MODE_SIZE (GET_MODE (x)) - > GET_MODE_SIZE (GET_MODE (new))) - && INTEGRAL_MODE_P (GET_MODE (new)) - && LOAD_EXTEND_OP (GET_MODE (new)) != NIL) + /* On these machines we will be reloading what is + inside the SUBREG if it originally was a pseudo and + the inner and outer modes are both a word or + smaller. So leave the SUBREG then. */ + && ! (GET_CODE (SUBREG_REG (x)) == REG + && x_size <= UNITS_PER_WORD + && new_size <= UNITS_PER_WORD + && x_size > new_size + && INTEGRAL_MODE_P (GET_MODE (new)) + && LOAD_EXTEND_OP (GET_MODE (new)) != NIL) #endif - ) + ) { int offset = SUBREG_WORD (x) * UNITS_PER_WORD; enum machine_mode mode = GET_MODE (x); @@ -3102,7 +3113,7 @@ eliminate_regs (x, mem_mode, insn) if (ep->from_rtx == XEXP (x, 0)) ep->can_eliminate = 0; - new = eliminate_regs (XEXP (x, 0), mem_mode, insn); + new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0); if (new != XEXP (x, 0)) return gen_rtx (code, GET_MODE (x), new); return x; @@ -3115,7 +3126,7 @@ eliminate_regs (x, mem_mode, insn) if (ep->to_rtx == XEXP (x, 0)) ep->can_eliminate = 0; - new = eliminate_regs (XEXP (x, 0), mem_mode, insn); + new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0); if (new != XEXP (x, 0)) return gen_rtx (code, GET_MODE (x), new); return x; @@ -3133,7 +3144,7 @@ eliminate_regs (x, mem_mode, insn) temp_vec = (rtx *) alloca (XVECLEN (x, 3) * sizeof (rtx)); for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) temp_vec[i] = eliminate_regs (ASM_OPERANDS_INPUT (x, i), - mem_mode, insn); + mem_mode, insn, 0); for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) if (temp_vec[i] != ASM_OPERANDS_INPUT (x, i)) @@ -3204,8 +3215,8 @@ eliminate_regs (x, mem_mode, insn) /* Now avoid the loop below in this common case. */ { - rtx new0 = eliminate_regs (SET_DEST (x), 0, insn); - rtx new1 = eliminate_regs (SET_SRC (x), 0, insn); + rtx new0 = eliminate_regs (SET_DEST (x), 0, insn, 1); + rtx new1 = eliminate_regs (SET_SRC (x), 0, insn, 0); /* If SET_DEST changed from a REG to a MEM and INSN is an insn, write a CLOBBER insn. */ @@ -3224,7 +3235,7 @@ eliminate_regs (x, mem_mode, insn) /* Our only special processing is to pass the mode of the MEM to our recursive call and copy the flags. While we are here, handle this case more efficiently. */ - new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn); + new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn, 0); if (new != XEXP (x, 0)) { new = gen_rtx (MEM, GET_MODE (x), new); @@ -3244,7 +3255,7 @@ eliminate_regs (x, mem_mode, insn) { if (*fmt == 'e') { - new = eliminate_regs (XEXP (x, i), mem_mode, insn); + new = eliminate_regs (XEXP (x, i), mem_mode, insn, 0); if (new != XEXP (x, i) && ! copied) { rtx new_x = rtx_alloc (code); @@ -3261,7 +3272,7 @@ eliminate_regs (x, mem_mode, insn) int copied_vec = 0; for (j = 0; j < XVECLEN (x, i); j++) { - new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn); + new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn, 0); if (new != XVECEXP (x, i, j) && ! copied_vec) { rtvec new_v = gen_rtvec_vv (XVECLEN (x, i), @@ -3439,7 +3450,7 @@ eliminate_regs_in_insn (insn, replace) but now can do this as a load-address. This saves an insn in this common case. */ - new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX); + new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX, 0); if (new_body != old_body) { /* If we aren't replacing things permanently and we changed something, @@ -3528,7 +3539,7 @@ eliminate_regs_in_insn (insn, replace) of spill registers to be needed in the final reload pass than in the pre-passes. */ if (val && REG_NOTES (insn) != 0) - REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn)); + REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn), 0); if (! replace) pop_obstacks (); @@ -4006,7 +4017,8 @@ reload_as_needed (first, live_known) && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM) XEXP (XEXP (PATTERN (insn), 0), 0) = eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0), - GET_MODE (XEXP (PATTERN (insn), 0)), NULL_RTX); + GET_MODE (XEXP (PATTERN (insn), 0)), + NULL_RTX, 0); /* If we need to do register elimination processing, do so. This might delete the insn, in which case we are done. */