diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/lra-constraints.c | 99 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 |
3 files changed, 82 insertions, 29 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ebb2cb7..491f62d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-08-11 Alan Modra <amodra@gmail.com> + + PR target/71680 + * lra-constraints.c (simplify_operand_subreg): Allow subreg + mode for mem when SLOW_UNALIGNED_ACCESS if inner mode is also + slow. Emit two reloads for slow mem case, first loading in + fast innermode, then converting to required mode. + 2016-08-10 Kelvin Nilsen <kelvin@gcc.gnu.org> * config/rs6000/altivec.h (vec_extract_exp): New macro. diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 880eee0..213e408 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1462,19 +1462,9 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) reg = SUBREG_REG (operand); innermode = GET_MODE (reg); type = curr_static_id->operand[nop].type; - /* If we change address for paradoxical subreg of memory, the - address might violate the necessary alignment or the access might - be slow. So take this into consideration. We should not worry - about access beyond allocated memory for paradoxical memory - subregs as we don't substitute such equiv memory (see processing - 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))) + if (MEM_P (reg)) { - rtx subst, old = *curr_id->operand_loc[nop]; + rtx subst; alter_subreg (curr_id->operand_loc[nop], false); subst = *curr_id->operand_loc[nop]; @@ -1482,27 +1472,78 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) if (! valid_address_p (innermode, XEXP (reg, 0), MEM_ADDR_SPACE (reg)) || valid_address_p (GET_MODE (subst), XEXP (subst, 0), - MEM_ADDR_SPACE (subst))) - return true; - else if ((get_constraint_type (lookup_constraint - (curr_static_id->operand[nop].constraint)) - != CT_SPECIAL_MEMORY) - /* We still can reload address and if the address is - valid, we can remove subreg without reloading its - inner memory. */ - && valid_address_p (GET_MODE (subst), - regno_reg_rtx - [ira_class_hard_regs - [base_reg_class (GET_MODE (subst), - MEM_ADDR_SPACE (subst), - ADDRESS, SCRATCH)][0]], - MEM_ADDR_SPACE (subst))) - return true; + MEM_ADDR_SPACE (subst)) + || ((get_constraint_type (lookup_constraint + (curr_static_id->operand[nop].constraint)) + != CT_SPECIAL_MEMORY) + /* We still can reload address and if the address is + valid, we can remove subreg without reloading its + inner memory. */ + && valid_address_p (GET_MODE (subst), + regno_reg_rtx + [ira_class_hard_regs + [base_reg_class (GET_MODE (subst), + MEM_ADDR_SPACE (subst), + ADDRESS, SCRATCH)][0]], + MEM_ADDR_SPACE (subst)))) + { + /* If we change address for paradoxical subreg of memory, the + address might violate the necessary alignment or the access might + be slow. So take this into consideration. We should not worry + about access beyond allocated memory for paradoxical memory + subregs as we don't substitute such equiv memory (see processing + equivalences in function lra_constraints) and because for spilled + pseudos we allocate stack memory enough for the biggest + corresponding paradoxical subreg. */ + if (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (reg)) + || SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN (reg)) + || MEM_ALIGN (reg) >= GET_MODE_ALIGNMENT (mode)) + return true; + + /* INNERMODE is fast, MODE slow. Reload the mem in INNERMODE. */ + enum reg_class rclass + = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); + if (get_reload_reg (curr_static_id->operand[nop].type, innermode, reg, + rclass, TRUE, "slow mem", &new_reg)) + { + bool insert_before, insert_after; + bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); + + insert_before = (type != OP_OUT + || GET_MODE_SIZE (innermode) > GET_MODE_SIZE (mode)); + insert_after = type != OP_IN; + insert_move_for_subreg (insert_before ? &before : NULL, + insert_after ? &after : NULL, + reg, new_reg); + } + *curr_id->operand_loc[nop] = operand; + SUBREG_REG (operand) = new_reg; + + /* Convert to MODE. */ + reg = operand; + rclass = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); + if (get_reload_reg (curr_static_id->operand[nop].type, mode, reg, + rclass, TRUE, "slow mem", &new_reg)) + { + bool insert_before, insert_after; + bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); + + insert_before = type != OP_OUT; + insert_after = type != OP_IN; + insert_move_for_subreg (insert_before ? &before : NULL, + insert_after ? &after : NULL, + reg, new_reg); + } + *curr_id->operand_loc[nop] = new_reg; + lra_process_new_insns (curr_insn, before, after, + "Inserting slow mem reload"); + 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; + *curr_id->operand_loc[nop] = operand; } else if (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d9c6907..b77940b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-08-11 Alan Modra <amodra@gmail.com> + + * gcc.target/powerpc/pr71680.c: New. + 2016-08-10 Kelvin Nilsen <kelvin@gcc.gnu.org> * gcc.target/powerpc/bfp/bfp.exp: New file. |