Here is one more patch concerning https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61325
The following patch prevents complex address transformation just by checking a change in address validity of subreg memory substitution.
The patch was bootstrapped and tested on x86-64. Committed as rev. 211716 to gcc-4.9-branch and as rev. 211715 to the trunk. 2014-06-16 Vladimir Makarov <vmaka...@redhat.com> PR rtl-optimization/61325 * lra-constraints.c (valid_address_p): Add forward declaration. (simplify_operand_subreg): Check address validity before and after alter_reg of memory subreg.
Index: lra-constraints.c =================================================================== --- lra-constraints.c (revision 211654) +++ lra-constraints.c (working copy) @@ -1231,6 +1231,8 @@ } } +static int valid_address_p (enum machine_mode mode, rtx addr, addr_space_t as); + /* Make reloads for subreg in operand NOP with internal subreg mode REG_MODE, add new reloads for further processing. Return true if any reload was generated. */ @@ -1261,12 +1263,28 @@ equivalences in function lra_constraints) and because for spilled pseudos we allocate stack memory enough for the biggest corresponding paradoxical subreg. */ - if ((MEM_P (reg) - && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (reg)) - || MEM_ALIGN (reg) >= GET_MODE_ALIGNMENT (mode))) - || (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER)) + if (MEM_P (reg) + && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (reg)) + || MEM_ALIGN (reg) >= GET_MODE_ALIGNMENT (mode))) { + rtx subst, old = *curr_id->operand_loc[nop]; + alter_subreg (curr_id->operand_loc[nop], false); + subst = *curr_id->operand_loc[nop]; + lra_assert (MEM_P (subst)); + if (! valid_address_p (GET_MODE (reg), XEXP (reg, 0), + MEM_ADDR_SPACE (reg)) + || valid_address_p (GET_MODE (subst), XEXP (subst, 0), + MEM_ADDR_SPACE (subst))) + return true; + /* If the address was valid and became invalid, prefer to reload + the memory. Typical case is when the index scale should + correspond the memory. */ + *curr_id->operand_loc[nop] = old; + } + else if (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER) + { + alter_subreg (curr_id->operand_loc[nop], false); return true; } /* Put constant into memory when we have mixed modes. It generates