diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 09c2b7283e3..f08eea8bcae 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -330,7 +330,7 @@ (match_test "aarch64_legitimate_address_p (V2DImode, XEXP (op, 0), 1)"))) -(define_memory_constraint "UtQ" +(define_relaxed_memory_constraint "UtQ" "@internal An address valid for SVE LD1RQs." (and (match_code "mem") diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index e3686dbfe61..d166a0debed 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -4564,7 +4564,33 @@ specifically aligned memory is necessary or desirable for some insn operand. The syntax and semantics are otherwise identical to -@code{define_constraint}. +@code{define_memory_constraint}. +@end deffn + +@deffn {MD Expression} define_relaxed_memory_constraint name docstring exp +The test expression in a @code{define_memory_constraint} can assume +that @code{TARGET_LEGITIMATE_ADDRESS_P} holds for the address inside +a @code{mem} rtx and so it does not need to test this condition itself. +In other words, a @code{define_memory_constraint} test of the form: + +@smallexample +(match_test "mem") +@end smallexample + +is enough to test whether an rtx is a @code{mem} @emph{and} whether +its address satisfies @code{TARGET_MEM_CONSTRAINT} (which is usually +@samp{'m'}). Thus the conditions imposed by a @code{define_memory_constraint} +always apply on top of the conditions imposed by @code{TARGET_MEM_CONSTRAINT}. + +However, it is sometimes useful to define memory constraints that allow +addresses beyond those accepted by @code{TARGET_LEGITIMATE_ADDRESS_P}. +@code{define_relaxed_memory_constraint} exists for this case. +The test expression in a @code{define_relaxed_memory_constraint} is +applied with no preconditions, so that the expression can determine +``from scratch'' exactly which addresses are valid and which are not. + +The syntax and semantics are otherwise identical to +@code{define_memory_constraint}. @end deffn @deffn {MD Expression} define_address_constraint name docstring exp diff --git a/gcc/genoutput.c b/gcc/genoutput.c index b88e13b90b6..25af4375d9c 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -1024,6 +1024,7 @@ main (int argc, const char **argv) case DEFINE_ADDRESS_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: case DEFINE_SPECIAL_MEMORY_CONSTRAINT: + case DEFINE_RELAXED_MEMORY_CONSTRAINT: note_constraint (&info); break; diff --git a/gcc/genpreds.c b/gcc/genpreds.c index 8499a2a2383..63fac0c7d34 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -660,9 +660,9 @@ write_one_predicate_function (struct pred_data *p) /* Constraints fall into two categories: register constraints (define_register_constraint), and others (define_constraint, define_memory_constraint, define_special_memory_constraint, - define_address_constraint). We work out automatically which of the - various old-style macros they correspond to, and produce - appropriate code. They all go in the same hash table so we can + define_relaxed_memory_constraint, define_address_constraint). We work out + automatically which of the various old-style macros they correspond to, and + produce appropriate code. They all go in the same hash table so we can verify that there are no duplicate names. */ /* All data from one constraint definition. */ @@ -683,6 +683,7 @@ public: unsigned int is_extra : 1; unsigned int is_memory : 1; unsigned int is_special_memory: 1; + unsigned int is_relaxed_memory: 1; unsigned int is_address : 1; unsigned int maybe_allows_reg : 1; unsigned int maybe_allows_mem : 1; @@ -721,6 +722,7 @@ static unsigned int constraint_max_namelen; static bool have_register_constraints; static bool have_memory_constraints; static bool have_special_memory_constraints; +static bool have_relaxed_memory_constraints; static bool have_address_constraints; static bool have_extra_constraints; static bool have_const_int_constraints; @@ -732,6 +734,7 @@ static unsigned int satisfied_start; static unsigned int const_int_start, const_int_end; static unsigned int memory_start, memory_end; static unsigned int special_memory_start, special_memory_end; +static unsigned int relaxed_memory_start, relaxed_memory_end; static unsigned int address_start, address_end; static unsigned int maybe_allows_none_start, maybe_allows_none_end; static unsigned int maybe_allows_reg_start, maybe_allows_reg_end; @@ -756,16 +759,16 @@ mangle (const char *name) return XOBFINISH (rtl_obstack, const char *); } -/* Add one constraint, of any sort, to the tables. NAME is its name; - REGCLASS is the register class, if any; EXP is the expression to - test, if any; IS_MEMORY, IS_SPECIAL_MEMORY and IS_ADDRESS indicate - memory, special memory, and address constraints, respectively; LOC - is the .md file location. +/* Add one constraint, of any sort, to the tables. NAME is its name; REGCLASS + is the register class, if any; EXP is the expression to test, if any; + IS_MEMORY, IS_SPECIAL_MEMORY, IS_RELAXED_MEMORY and IS_ADDRESS indicate + memory, special memory, and address constraints, respectively; LOC is the .md + file location. - Not all combinations of arguments are valid; most importantly, - REGCLASS is mutually exclusive with EXP, and - IS_MEMORY/IS_SPECIAL_MEMORY/IS_ADDRESS are only meaningful for - constraints with EXP. + Not all combinations of arguments are valid; most importantly, REGCLASS is + mutually exclusive with EXP, and + IS_MEMORY/IS_SPECIAL_MEMORY/IS_RELAXED_MEMORY/IS_ADDRESS are only meaningful + for constraints with EXP. This function enforces all syntactic and semantic rules about what constraints can be defined. */ @@ -773,7 +776,7 @@ mangle (const char *name) static void add_constraint (const char *name, const char *regclass, rtx exp, bool is_memory, bool is_special_memory, - bool is_address, file_location loc) + bool is_relaxed_memory, bool is_address, file_location loc) { class constraint_data *c, **iter, **slot; const char *p; @@ -873,7 +876,7 @@ add_constraint (const char *name, const char *regclass, return; } - if (is_memory) + if (is_memory || is_special_memory || is_relaxed_memory) { if (name[1] == '\0') error_at (loc, "constraint letter '%c' cannot be a " @@ -884,17 +887,6 @@ add_constraint (const char *name, const char *regclass, name, name[0]); return; } - else if (is_special_memory) - { - if (name[1] == '\0') - error_at (loc, "constraint letter '%c' cannot be a " - "special memory constraint", name[0]); - else - error_at (loc, "constraint name '%s' begins with '%c', " - "and therefore cannot be a special memory constraint", - name, name[0]); - return; - } else if (is_address) { if (name[1] == '\0') @@ -922,6 +914,7 @@ add_constraint (const char *name, const char *regclass, c->is_extra = !(regclass || is_const_int || is_const_dbl); c->is_memory = is_memory; c->is_special_memory = is_special_memory; + c->is_relaxed_memory = is_relaxed_memory; c->is_address = is_address; c->maybe_allows_reg = true; c->maybe_allows_mem = true; @@ -949,19 +942,21 @@ add_constraint (const char *name, const char *regclass, have_extra_constraints |= c->is_extra; have_memory_constraints |= c->is_memory; have_special_memory_constraints |= c->is_special_memory; + have_relaxed_memory_constraints |= c->is_relaxed_memory; have_address_constraints |= c->is_address; num_constraints += 1; } /* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, - DEFINE_SPECIAL_MEMORY_CONSTRAINT, or DEFINE_ADDRESS_CONSTRAINT - expression, C. */ + DEFINE_SPECIAL_MEMORY_CONSTRAINT, DEFINE_RELAXED_MEMORY_CONSTRAINT, or + DEFINE_ADDRESS_CONSTRAINT expression, C. */ static void process_define_constraint (md_rtx_info *info) { add_constraint (XSTR (info->def, 0), 0, XEXP (info->def, 2), GET_CODE (info->def) == DEFINE_MEMORY_CONSTRAINT, GET_CODE (info->def) == DEFINE_SPECIAL_MEMORY_CONSTRAINT, + GET_CODE (info->def) == DEFINE_RELAXED_MEMORY_CONSTRAINT, GET_CODE (info->def) == DEFINE_ADDRESS_CONSTRAINT, info->loc); } @@ -971,7 +966,7 @@ static void process_define_register_constraint (md_rtx_info *info) { add_constraint (XSTR (info->def, 0), XSTR (info->def, 1), - 0, false, false, false, info->loc); + 0, false, false, false, false, info->loc); } /* Put the constraints into enum order. We want to keep constraints @@ -1011,6 +1006,12 @@ choose_enum_order (void) enum_order[next++] = c; special_memory_end = next; + relaxed_memory_start = next; + FOR_ALL_CONSTRAINTS (c) + if (c->is_relaxed_memory) + enum_order[next++] = c; + relaxed_memory_end = next; + address_start = next; FOR_ALL_CONSTRAINTS (c) if (c->is_address) @@ -1020,7 +1021,7 @@ choose_enum_order (void) maybe_allows_none_start = next; FOR_ALL_CONSTRAINTS (c) if (!c->is_register && !c->is_const_int && !c->is_memory - && !c->is_special_memory && !c->is_address + && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address && !c->maybe_allows_reg && !c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_none_end = next; @@ -1028,7 +1029,7 @@ choose_enum_order (void) maybe_allows_reg_start = next; FOR_ALL_CONSTRAINTS (c) if (!c->is_register && !c->is_const_int && !c->is_memory - && !c->is_special_memory && !c->is_address + && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address && c->maybe_allows_reg && !c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_reg_end = next; @@ -1036,14 +1037,14 @@ choose_enum_order (void) maybe_allows_mem_start = next; FOR_ALL_CONSTRAINTS (c) if (!c->is_register && !c->is_const_int && !c->is_memory - && !c->is_special_memory && !c->is_address + && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address && !c->maybe_allows_reg && c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_mem_end = next; FOR_ALL_CONSTRAINTS (c) if (!c->is_register && !c->is_const_int && !c->is_memory - && !c->is_special_memory && !c->is_address + && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address && c->maybe_allows_reg && c->maybe_allows_mem) enum_order[next++] = c; gcc_assert (next == num_constraints); @@ -1466,6 +1467,8 @@ write_tm_preds_h (void) memory_start, memory_end); write_range_function ("insn_extra_special_memory_constraint", special_memory_start, special_memory_end); + write_range_function ("insn_extra_relaxed_memory_constraint", + relaxed_memory_start, relaxed_memory_end); write_range_function ("insn_extra_address_constraint", address_start, address_end); write_allows_reg_mem_function (); @@ -1515,6 +1518,7 @@ write_tm_preds_h (void) " CT_CONST_INT,\n" " CT_MEMORY,\n" " CT_SPECIAL_MEMORY,\n" + " CT_RELAXED_MEMORY,\n" " CT_ADDRESS,\n" " CT_FIXED_FORM\n" "};\n" @@ -1528,7 +1532,11 @@ write_tm_preds_h (void) if (memory_start != memory_end) values.safe_push (std::make_pair (memory_start, "CT_MEMORY")); if (special_memory_start != special_memory_end) - values.safe_push (std::make_pair (special_memory_start, "CT_SPECIAL_MEMORY")); + values.safe_push (std::make_pair (special_memory_start, + "CT_SPECIAL_MEMORY")); + if (relaxed_memory_start != relaxed_memory_end) + values.safe_push (std::make_pair (relaxed_memory_start, + "CT_RELAXED_MEMORY")); if (address_start != address_end) values.safe_push (std::make_pair (address_start, "CT_ADDRESS")); if (address_end != num_constraints) @@ -1645,6 +1653,7 @@ main (int argc, const char **argv) case DEFINE_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: case DEFINE_SPECIAL_MEMORY_CONSTRAINT: + case DEFINE_RELAXED_MEMORY_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT: process_define_constraint (&info); break; diff --git a/gcc/gensupport.c b/gcc/gensupport.c index fdf4a9fdc1f..0f19bd70664 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -582,6 +582,7 @@ process_rtx (rtx desc, file_location loc) case DEFINE_REGISTER_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: case DEFINE_SPECIAL_MEMORY_CONSTRAINT: + case DEFINE_RELAXED_MEMORY_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT: queue_pattern (desc, &define_pred_tail, loc); break; diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index cf1d4992927..7547f3e0f53 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -780,6 +780,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, break; case CT_SPECIAL_MEMORY: + case CT_RELAXED_MEMORY: insn_allows_mem[i] = allows_mem[i] = 1; if (MEM_P (extract_mem_from_operand (op)) && constraint_satisfied_p (op, cn)) diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index f3341313bd1..bd1818bb255 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -872,6 +872,7 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const) cn = lookup_constraint (constraints); if (insn_extra_memory_constraint (cn) || insn_extra_special_memory_constraint (cn) + || insn_extra_relaxed_memory_constraint (cn) || insn_extra_address_constraint (cn)) return NO_REGS; if (constraint_satisfied_p (op, cn) diff --git a/gcc/ira.c b/gcc/ira.c index fc77131491d..7e903289e79 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -1874,6 +1874,7 @@ ira_setup_alts (rtx_insn *insn) mem = op; /* Fall through. */ case CT_SPECIAL_MEMORY: + case CT_RELAXED_MEMORY: if (!mem) mem = extract_mem_from_operand (op); if (MEM_P (mem)) diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index fdfe953bcf5..861b5aad40b 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -410,8 +410,7 @@ valid_address_p (rtx op, struct address_info *ad, Need to extract memory from op for special memory constraint, i.e. bcst_mem_operand in i386 backend. */ if (MEM_P (extract_mem_from_operand (op)) - && (insn_extra_memory_constraint (constraint) - || insn_extra_special_memory_constraint (constraint)) + && insn_extra_relaxed_memory_constraint (constraint) && constraint_satisfied_p (op, constraint)) return true; @@ -2460,6 +2459,7 @@ process_alt_operands (int only_alternative) break; case CT_SPECIAL_MEMORY: + case CT_RELAXED_MEMORY: if (satisfies_memory_constraint_p (op, cn)) win = true; else if (spilled_pseudo_p (op)) @@ -4370,7 +4370,8 @@ curr_insn_transform (bool check_only_p) { enum constraint_num cn = lookup_constraint (constraint); if ((insn_extra_memory_constraint (cn) - || insn_extra_special_memory_constraint (cn)) + || insn_extra_special_memory_constraint (cn) + || insn_extra_relaxed_memory_constraint (cn)) && satisfies_memory_constraint_p (tem, cn)) break; } diff --git a/gcc/recog.c b/gcc/recog.c index abbc49f3f9b..ee143bc761e 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -2270,6 +2270,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints) mem = op; /* Fall through. */ case CT_SPECIAL_MEMORY: + case CT_RELAXED_MEMORY: /* Every memory operand can be reloaded to fit. */ if (!mem) mem = extract_mem_from_operand (op); @@ -2892,6 +2893,7 @@ preprocess_constraints (int n_operands, int n_alternatives, case CT_MEMORY: case CT_SPECIAL_MEMORY: + case CT_RELAXED_MEMORY: op_alt[i].memory_ok = 1; break; diff --git a/gcc/reload.c b/gcc/reload.c index c88f928392b..7340125c441 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -3504,6 +3504,7 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known, break; case CT_SPECIAL_MEMORY: + case CT_RELAXED_MEMORY: if (force_reload) break; if (constraint_satisfied_p (operand, cn)) diff --git a/gcc/rtl.def b/gcc/rtl.def index 92b3de822be..b85eb5c0055 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -1055,6 +1055,7 @@ DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sss", RT DEF_RTL_EXPR(DEFINE_CONSTRAINT, "define_constraint", "sse", RTX_EXTRA) DEF_RTL_EXPR(DEFINE_MEMORY_CONSTRAINT, "define_memory_constraint", "sse", RTX_EXTRA) DEF_RTL_EXPR(DEFINE_SPECIAL_MEMORY_CONSTRAINT, "define_special_memory_constraint", "sse", RTX_EXTRA) +DEF_RTL_EXPR(DEFINE_RELAXED_MEMORY_CONSTRAINT, "define_relaxed_memory_constraint", "sse", RTX_EXTRA) DEF_RTL_EXPR(DEFINE_ADDRESS_CONSTRAINT, "define_address_constraint", "sse", RTX_EXTRA) diff --git a/gcc/stmt.c b/gcc/stmt.c index f52ffaf8e75..297e0d0ff5d 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -419,7 +419,8 @@ parse_input_constraint (const char **constraint_p, int input_num, || insn_extra_address_constraint (cn)) *allows_reg = true; else if (insn_extra_memory_constraint (cn) - || insn_extra_special_memory_constraint (cn)) + || insn_extra_special_memory_constraint (cn) + || insn_extra_relaxed_memory_constraint (cn)) *allows_mem = true; else insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem); diff --git a/gcc/testsuite/gcc.target/powerpc/pr99581.c b/gcc/testsuite/gcc.target/powerpc/pr99581.c new file mode 100644 index 00000000000..525f2762773 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr99581.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +char e[37540]; +struct A { int c; } d; + +void +bar (int n) +{ + __asm__("" : : "r" (e)); +} + +void +foo (void) +{ + __asm__("stw %1, %0" : "=o" (d.c) : "r" (0)); +}