diff options
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 314 |
1 files changed, 89 insertions, 225 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 08716fe698a..b1904e1bf65 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -394,40 +394,38 @@ valid_address_p (struct address_info *ad) return valid_address_p (ad->mode, *ad->outer, ad->as); } -#ifdef EXTRA_CONSTRAINT_STR /* Return true if the eliminated form of memory reference OP satisfies extra memory constraint CONSTRAINT. */ static bool -satisfies_memory_constraint_p (rtx op, const char *constraint) +satisfies_memory_constraint_p (rtx op, enum constraint_num constraint) { struct address_info ad; decompose_mem_address (&ad, op); address_eliminator eliminator (&ad); - return EXTRA_CONSTRAINT_STR (op, *constraint, constraint); + return constraint_satisfied_p (op, constraint); } /* Return true if the eliminated form of address AD satisfies extra address constraint CONSTRAINT. */ static bool satisfies_address_constraint_p (struct address_info *ad, - const char *constraint) + enum constraint_num constraint) { address_eliminator eliminator (ad); - return EXTRA_CONSTRAINT_STR (*ad->outer, *constraint, constraint); + return constraint_satisfied_p (*ad->outer, constraint); } /* Return true if the eliminated form of address OP satisfies extra address constraint CONSTRAINT. */ static bool -satisfies_address_constraint_p (rtx op, const char *constraint) +satisfies_address_constraint_p (rtx op, enum constraint_num constraint) { struct address_info ad; decompose_lea_address (&ad, &op); return satisfies_address_constraint_p (&ad, constraint); } -#endif /* Initiate equivalences for LRA. As we keep original equivalences before any elimination, we need to make copies otherwise any change @@ -970,33 +968,25 @@ reg_class_from_constraints (const char *p) case ',': return op_class; - case 'p': - op_class = (reg_class_subunion - [op_class][base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH)]); - break; - case 'g': - case 'r': op_class = reg_class_subunion[op_class][GENERAL_REGS]; break; default: - if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS) + enum constraint_num cn = lookup_constraint (p); + enum reg_class cl = reg_class_for_constraint (cn); + if (cl == NO_REGS) { -#ifdef EXTRA_CONSTRAINT_STR - if (EXTRA_ADDRESS_CONSTRAINT (c, p)) + if (insn_extra_address_constraint (cn)) op_class = (reg_class_subunion [op_class][base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH)]); -#endif break; } - op_class - = reg_class_subunion[op_class][REG_CLASS_FROM_CONSTRAINT (c, p)]; - break; + op_class = reg_class_subunion[op_class][cl]; + break; } while ((p += len), c); return op_class; @@ -1343,6 +1333,8 @@ insert_move_for_subreg (rtx *before, rtx *after, rtx origreg, rtx newreg) } } +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. */ @@ -1373,10 +1365,26 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode) 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; @@ -1712,6 +1720,7 @@ process_alt_operands (int only_alternative) bool this_alternative_offmemok; bool scratch_p; enum machine_mode mode; + enum constraint_num cn; opalt_num = nalt * n_operands + nop; if (curr_static_id->operand_alternative[opalt_num].anything_ok) @@ -1770,15 +1779,6 @@ process_alt_operands (int only_alternative) c = '\0'; break; - case '=': case '+': case '?': case '*': case '!': - case ' ': case '\t': - break; - - case '%': - /* We only support one commutative marker, the first - one. We already set commutative above. */ - break; - case '&': early_clobber_p = true; break; @@ -1911,195 +1911,66 @@ process_alt_operands (int only_alternative) break; } - case 'p': - cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH); - this_alternative = reg_class_subunion[this_alternative][cl]; - IOR_HARD_REG_SET (this_alternative_set, - reg_class_contents[cl]); - if (costly_p) - { - this_costly_alternative - = reg_class_subunion[this_costly_alternative][cl]; - IOR_HARD_REG_SET (this_costly_alternative_set, - reg_class_contents[cl]); - } - win = true; - badop = false; - break; - - case TARGET_MEM_CONSTRAINT: - if (MEM_P (op) || spilled_pseudo_p (op)) - win = true; - /* We can put constant or pseudo value into memory - to satisfy the constraint. */ - if (CONST_POOL_OK_P (mode, op) || REG_P (op)) - badop = false; - constmemok = true; - break; - - case '<': - if (MEM_P (op) - && (GET_CODE (XEXP (op, 0)) == PRE_DEC - || GET_CODE (XEXP (op, 0)) == POST_DEC)) - win = true; - break; - - case '>': - if (MEM_P (op) - && (GET_CODE (XEXP (op, 0)) == PRE_INC - || GET_CODE (XEXP (op, 0)) == POST_INC)) - win = true; - break; - - /* Memory op whose address is not offsettable. */ - case 'V': - if (MEM_P (op) - && ! offsettable_nonstrict_memref_p (op)) - win = true; - break; - - /* Memory operand whose address is offsettable. */ - case 'o': - if ((MEM_P (op) - && offsettable_nonstrict_memref_p (op)) - || spilled_pseudo_p (op)) - win = true; - /* We can put constant or pseudo value into memory - or make memory address offsetable to satisfy the - constraint. */ - if (CONST_POOL_OK_P (mode, op) || MEM_P (op) || REG_P (op)) - badop = false; - constmemok = true; - offmemok = true; - break; - - case 'E': - case 'F': - if (GET_CODE (op) == CONST_DOUBLE - || (GET_CODE (op) == CONST_VECTOR - && (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT))) - win = true; - break; - - case 'G': - case 'H': - if (CONST_DOUBLE_AS_FLOAT_P (op) - && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p)) - win = true; - break; - - case 's': - if (CONST_SCALAR_INT_P (op)) - break; - - case 'i': - if (general_constant_p (op)) - win = true; - break; - - case 'n': - if (CONST_SCALAR_INT_P (op)) - win = true; - break; - - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - if (CONST_INT_P (op) - && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p)) - win = true; - break; - - case 'X': - /* This constraint should be excluded by the fast - track. */ - gcc_unreachable (); - break; - case 'g': if (MEM_P (op) || general_constant_p (op) || spilled_pseudo_p (op)) win = true; - /* Drop through into 'r' case. */ - - case 'r': - this_alternative - = reg_class_subunion[this_alternative][GENERAL_REGS]; - IOR_HARD_REG_SET (this_alternative_set, - reg_class_contents[GENERAL_REGS]); - if (costly_p) - { - this_costly_alternative - = (reg_class_subunion - [this_costly_alternative][GENERAL_REGS]); - IOR_HARD_REG_SET (this_costly_alternative_set, - reg_class_contents[GENERAL_REGS]); - } + cl = GENERAL_REGS; goto reg; default: - if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS) + cn = lookup_constraint (p); + switch (get_constraint_type (cn)) { -#ifdef EXTRA_CONSTRAINT_STR - if (EXTRA_MEMORY_CONSTRAINT (c, p)) - { - if (MEM_P (op) - && satisfies_memory_constraint_p (op, p)) - win = true; - else if (spilled_pseudo_p (op)) - win = true; - - /* If we didn't already win, we can reload - constants via force_const_mem or put the - pseudo value into memory, or make other - memory by reloading the address like for - 'o'. */ - if (CONST_POOL_OK_P (mode, op) - || MEM_P (op) || REG_P (op)) - badop = false; - constmemok = true; - offmemok = true; - break; - } - if (EXTRA_ADDRESS_CONSTRAINT (c, p)) - { - if (satisfies_address_constraint_p (op, p)) - win = true; - - /* If we didn't already win, we can reload - the address into a base register. */ - cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH); - this_alternative - = reg_class_subunion[this_alternative][cl]; - IOR_HARD_REG_SET (this_alternative_set, - reg_class_contents[cl]); - if (costly_p) - { - this_costly_alternative - = (reg_class_subunion - [this_costly_alternative][cl]); - IOR_HARD_REG_SET (this_costly_alternative_set, - reg_class_contents[cl]); - } - badop = false; - break; - } + case CT_REGISTER: + cl = reg_class_for_constraint (cn); + if (cl != NO_REGS) + goto reg; + break; - if (EXTRA_CONSTRAINT_STR (op, c, p)) + case CT_CONST_INT: + if (CONST_INT_P (op) + && insn_const_int_ok_for_constraint (INTVAL (op), cn)) + win = true; + break; + + case CT_MEMORY: + if (MEM_P (op) + && satisfies_memory_constraint_p (op, cn)) + win = true; + else if (spilled_pseudo_p (op)) + win = true; + + /* If we didn't already win, we can reload constants + via force_const_mem or put the pseudo value into + memory, or make other memory by reloading the + address like for 'o'. */ + if (CONST_POOL_OK_P (mode, op) + || MEM_P (op) || REG_P (op)) + badop = false; + constmemok = true; + offmemok = true; + break; + + case CT_ADDRESS: + /* If we didn't already win, we can reload the address + into a base register. */ + if (satisfies_address_constraint_p (op, cn)) + win = true; + cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, + ADDRESS, SCRATCH); + badop = false; + goto reg; + + case CT_FIXED_FORM: + if (constraint_satisfied_p (op, cn)) win = true; -#endif break; } + break; - cl = REG_CLASS_FROM_CONSTRAINT (c, p); + reg: this_alternative = reg_class_subunion[this_alternative][cl]; IOR_HARD_REG_SET (this_alternative_set, reg_class_contents[cl]); @@ -2110,7 +1981,6 @@ process_alt_operands (int only_alternative) IOR_HARD_REG_SET (this_costly_alternative_set, reg_class_contents[cl]); } - reg: if (mode == BLKmode) break; winreg = true; @@ -2856,10 +2726,10 @@ process_address_1 (int nop, rtx *before, rtx *after) rtx new_reg; rtx op = *curr_id->operand_loc[nop]; const char *constraint = curr_static_id->operand[nop].constraint; + enum constraint_num cn = lookup_constraint (constraint); bool change_p; - if (constraint[0] == 'p' - || EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)) + if (insn_extra_address_constraint (cn)) decompose_lea_address (&ad, curr_id->operand_loc[nop]); else if (MEM_P (op)) decompose_mem_address (&ad, op); @@ -2888,14 +2758,11 @@ process_address_1 (int nop, rtx *before, rtx *after) && process_addr_reg (ad.index_term, before, NULL, INDEX_REG_CLASS)) change_p = true; -#ifdef EXTRA_CONSTRAINT_STR - /* Target hooks sometimes reject extra constraint addresses -- use - EXTRA_CONSTRAINT_STR for the validation. */ - if (constraint[0] != 'p' - && EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint) - && satisfies_address_constraint_p (&ad, constraint)) + /* Target hooks sometimes don't treat extra-constraint addresses as + legitimate address_operands, so handle them specially. */ + if (insn_extra_address_constraint (cn) + && satisfies_address_constraint_p (&ad, cn)) return change_p; -#endif /* There are three cases where the shape of *AD.INNER may now be invalid: @@ -3615,13 +3482,10 @@ curr_insn_transform (void) (c = *constraint) && c != ',' && c != '#'; constraint += CONSTRAINT_LEN (c, constraint)) { - if (c == TARGET_MEM_CONSTRAINT || c == 'o') - break; -#ifdef EXTRA_CONSTRAINT_STR - if (EXTRA_MEMORY_CONSTRAINT (c, constraint) - && satisfies_memory_constraint_p (tem, constraint)) + enum constraint_num cn = lookup_constraint (constraint); + if (insn_extra_memory_constraint (cn) + && satisfies_memory_constraint_p (tem, cn)) break; -#endif } if (c == '\0' || c == ',' || c == '#') continue; |