From 6b3b345a5d2ebf96ab99012f6e45f51d1b260525 Mon Sep 17 00:00:00 2001 From: vmakarov Date: Fri, 29 Jan 2016 18:47:17 +0000 Subject: [PATCH] 2016-01-29 Vladimir Makarov PR target/69299 * config/i386/constraints.md (Bm): Describe as special memory constraint. * doc/md.texi (DEFINE_SPECIAL_MEMORY_CONSTRAINT): Describe it. * genoutput.c (main): Process DEFINE_SPECIAL_MEMORY_CONSTRAINT. * genpreds.c (struct constraint_data): Add is_special_memory. (have_special_memory_constraints, special_memory_start): New static vars. (special_memory_end): Ditto. (add_constraint): Add new arg is_special_memory. Add code to process its true value. Update have_special_memory_constraints. (process_define_constraint): Pass the new arg. (process_define_register_constraint): Ditto. (choose_enum_order): Process special memory. (write_tm_preds_h): Generate enum const CT_SPECIAL_MEMORY and function insn_extra_special_memory_constraint. (main): Process DEFINE_SPECIAL_MEMORY_CONSTRAINT. * gensupport.c (process_rtx): Process DEFINE_SPECIAL_MEMORY_CONSTRAINT. * ira-costs.c (record_reg_classes): Process CT_SPECIAL_MEMORY. * ira-lives.c (single_reg_class): Use insn_extra_special_memory_constraint. * ira.c (ira_setup_alts): Process CT_SPECIAL_MEMORY. * lra-constraints.c (process_alt_operands): Ditto. (curr_insn_transform): Use insn_extra_special_memory_constraint. * recog.c (asm_operand_ok, preprocess_constraints): Process CT_SPECIAL_MEMORY. * reload.c (find_reloads): Ditto. * rtl.def (DEFINE_SPECIFAL_MEMORY_CONSTRAINT): New. * stmt.c (parse_input_constraint): Use insn_extra_special_memory_constraint. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232993 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 34 +++++++++++++++++++ gcc/config/i386/constraints.md | 2 +- gcc/doc/md.texi | 14 ++++++++ gcc/genoutput.c | 1 + gcc/genpreds.c | 74 +++++++++++++++++++++++++++++++----------- gcc/gensupport.c | 1 + gcc/ira-costs.c | 6 ++++ gcc/ira-lives.c | 1 + gcc/ira.c | 1 + gcc/lra-constraints.c | 13 ++++++-- gcc/recog.c | 2 ++ gcc/reload.c | 17 ++++++++++ gcc/rtl.def | 1 + gcc/stmt.c | 3 +- 14 files changed, 147 insertions(+), 23 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 48fdab6..2919b81 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2016-01-29 Vladimir Makarov + + PR target/69299 + * config/i386/constraints.md (Bm): Describe as special memory + constraint. + * doc/md.texi (DEFINE_SPECIAL_MEMORY_CONSTRAINT): Describe it. + * genoutput.c (main): Process DEFINE_SPECIAL_MEMORY_CONSTRAINT. + * genpreds.c (struct constraint_data): Add is_special_memory. + (have_special_memory_constraints, special_memory_start): New + static vars. + (special_memory_end): Ditto. + (add_constraint): Add new arg is_special_memory. Add code to + process its true value. Update have_special_memory_constraints. + (process_define_constraint): Pass the new arg. + (process_define_register_constraint): Ditto. + (choose_enum_order): Process special memory. + (write_tm_preds_h): Generate enum const CT_SPECIAL_MEMORY and + function insn_extra_special_memory_constraint. + (main): Process DEFINE_SPECIAL_MEMORY_CONSTRAINT. + * gensupport.c (process_rtx): Process + DEFINE_SPECIAL_MEMORY_CONSTRAINT. + * ira-costs.c (record_reg_classes): Process CT_SPECIAL_MEMORY. + * ira-lives.c (single_reg_class): Use + insn_extra_special_memory_constraint. + * ira.c (ira_setup_alts): Process CT_SPECIAL_MEMORY. + * lra-constraints.c (process_alt_operands): Ditto. + (curr_insn_transform): Use insn_extra_special_memory_constraint. + * recog.c (asm_operand_ok, preprocess_constraints): Process + CT_SPECIAL_MEMORY. + * reload.c (find_reloads): Ditto. + * rtl.def (DEFINE_SPECIFAL_MEMORY_CONSTRAINT): New. + * stmt.c (parse_input_constraint): Use + insn_extra_special_memory_constraint. + 2016-01-29 H.J. Lu PR target/69530 diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 3b0b7c7..afdc546 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -162,7 +162,7 @@ "@internal GOT memory operand." (match_operand 0 "GOT_memory_operand")) -(define_constraint "Bm" +(define_special_memory_constraint "Bm" "@internal Vector memory operand." (match_operand 0 "vector_memory_operand")) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 3c11d19..864824f 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -4424,6 +4424,20 @@ The syntax and semantics are otherwise identical to @code{define_constraint}. @end deffn +@deffn {MD Expression} define_special_memory_constraint name docstring exp +Use this expression for constraints that match a subset of all memory +operands: that is, @code{reload} can not make them match by reloading +the address as it is described for @code{define_memory_constraint} or +such address reload is undesirable with the performance point of view. + +For example, @code{define_special_memory_constraint} can be useful if +specifically aligned memory is necessary or desirable for some insn +operand. + +The syntax and semantics are otherwise identical to +@code{define_constraint}. +@end deffn + @deffn {MD Expression} define_address_constraint name docstring exp Use this expression for constraints that match a subset of all address operands: that is, @code{reload} can make the constraint match by diff --git a/gcc/genoutput.c b/gcc/genoutput.c index 1c620c3..6ca1bb8 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -1019,6 +1019,7 @@ main (int argc, char **argv) case DEFINE_REGISTER_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: + case DEFINE_SPECIAL_MEMORY_CONSTRAINT: note_constraint (&info); break; diff --git a/gcc/genpreds.c b/gcc/genpreds.c index 84c41a1..c0d7ce4 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -659,11 +659,11 @@ 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_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. */ + 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 + verify that there are no duplicate names. */ /* All data from one constraint definition. */ struct constraint_data @@ -681,6 +681,7 @@ struct constraint_data unsigned int is_const_dbl : 1; unsigned int is_extra : 1; unsigned int is_memory : 1; + unsigned int is_special_memory: 1; unsigned int is_address : 1; unsigned int maybe_allows_reg : 1; unsigned int maybe_allows_mem : 1; @@ -718,6 +719,7 @@ static const char const_dbl_constraints[] = "GH"; 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_address_constraints; static bool have_extra_constraints; static bool have_const_int_constraints; @@ -728,6 +730,7 @@ static unsigned int register_start, register_end; 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 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; @@ -754,20 +757,22 @@ mangle (const char *name) /* 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 and IS_ADDRESS indicate memory and address - constraints, respectively; LOC is the .md file location. + 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. - Not all combinations of arguments are valid; most importantly, REGCLASS - is mutually exclusive with EXP, and IS_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_ADDRESS are only meaningful for + constraints with EXP. This function enforces all syntactic and semantic rules about what constraints can be defined. */ static void add_constraint (const char *name, const char *regclass, - rtx exp, bool is_memory, bool is_address, - file_location loc) + rtx exp, bool is_memory, bool is_special_memory, + bool is_address, file_location loc) { struct constraint_data *c, **iter, **slot; const char *p; @@ -878,6 +883,17 @@ 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') @@ -904,6 +920,7 @@ add_constraint (const char *name, const char *regclass, c->is_const_dbl = is_const_dbl; c->is_extra = !(regclass || is_const_int || is_const_dbl); c->is_memory = is_memory; + c->is_special_memory = is_special_memory; c->is_address = is_address; c->maybe_allows_reg = true; c->maybe_allows_mem = true; @@ -930,17 +947,20 @@ add_constraint (const char *name, const char *regclass, have_const_int_constraints |= c->is_const_int; have_extra_constraints |= c->is_extra; have_memory_constraints |= c->is_memory; + have_special_memory_constraints |= c->is_special_memory; have_address_constraints |= c->is_address; num_constraints += 1; } -/* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, or - DEFINE_ADDRESS_CONSTRAINT expression, C. */ +/* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, + DEFINE_SPECIAL_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_ADDRESS_CONSTRAINT, info->loc); } @@ -950,7 +970,7 @@ static void process_define_register_constraint (md_rtx_info *info) { add_constraint (XSTR (info->def, 0), XSTR (info->def, 1), - 0, false, false, info->loc); + 0, false, false, false, info->loc); } /* Put the constraints into enum order. We want to keep constraints @@ -984,6 +1004,12 @@ choose_enum_order (void) enum_order[next++] = c; memory_end = next; + special_memory_start = next; + FOR_ALL_CONSTRAINTS (c) + if (c->is_special_memory) + enum_order[next++] = c; + special_memory_end = next; + address_start = next; FOR_ALL_CONSTRAINTS (c) if (c->is_address) @@ -992,27 +1018,31 @@ 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_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_memory && !c->is_address && !c->maybe_allows_reg && !c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_none_end = next; maybe_allows_reg_start = next; FOR_ALL_CONSTRAINTS (c) - if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_memory && !c->is_address && c->maybe_allows_reg && !c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_reg_end = next; maybe_allows_mem_start = next; FOR_ALL_CONSTRAINTS (c) - if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_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_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_memory && !c->is_address && c->maybe_allows_reg && c->maybe_allows_mem) enum_order[next++] = c; gcc_assert (next == num_constraints); @@ -1431,6 +1461,8 @@ write_tm_preds_h (void) register_start, register_end); write_range_function ("insn_extra_memory_constraint", memory_start, memory_end); + write_range_function ("insn_extra_special_memory_constraint", + special_memory_start, special_memory_end); write_range_function ("insn_extra_address_constraint", address_start, address_end); write_allows_reg_mem_function (); @@ -1479,6 +1511,7 @@ write_tm_preds_h (void) " CT_REGISTER,\n" " CT_CONST_INT,\n" " CT_MEMORY,\n" + " CT_SPECIAL_MEMORY,\n" " CT_ADDRESS,\n" " CT_FIXED_FORM\n" "};\n" @@ -1491,6 +1524,8 @@ write_tm_preds_h (void) values.safe_push (std::make_pair (const_int_start, "CT_CONST_INT")); 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")); if (address_start != address_end) values.safe_push (std::make_pair (address_start, "CT_ADDRESS")); if (address_end != num_constraints) @@ -1602,6 +1637,7 @@ main (int argc, char **argv) case DEFINE_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: + case DEFINE_SPECIAL_MEMORY_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT: process_define_constraint (&info); break; diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 596b885..8c5a1ab 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -521,6 +521,7 @@ process_rtx (rtx desc, file_location loc) case DEFINE_CONSTRAINT: case DEFINE_REGISTER_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: + case DEFINE_SPECIAL_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 ea5e8b1..2b736c1 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -783,6 +783,12 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, win = 1; break; + case CT_SPECIAL_MEMORY: + insn_allows_mem[i] = allows_mem[i] = 1; + if (MEM_P (op) && constraint_satisfied_p (op, cn)) + win = 1; + break; + case CT_ADDRESS: /* Every address can be reloaded to fit. */ allows_addr = 1; diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 30ef982..6950ffb 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -774,6 +774,7 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const) /* ??? Is this the best way to handle memory constraints? */ cn = lookup_constraint (constraints); if (insn_extra_memory_constraint (cn) + || insn_extra_special_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 5259617..249e2ff 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -1868,6 +1868,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts) case CT_ADDRESS: case CT_MEMORY: + case CT_SPECIAL_MEMORY: goto op_success; case CT_FIXED_FORM: diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index fb19416..9a7121f 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -400,7 +400,7 @@ valid_address_p (struct address_info *ad) } /* Return true if the eliminated form of memory reference OP satisfies - extra memory constraint CONSTRAINT. */ + extra (special) memory constraint CONSTRAINT. */ static bool satisfies_memory_constraint_p (rtx op, enum constraint_num constraint) { @@ -2038,6 +2038,14 @@ process_alt_operands (int only_alternative) if (constraint_satisfied_p (op, cn)) win = true; break; + + case CT_SPECIAL_MEMORY: + if (MEM_P (op) + && satisfies_memory_constraint_p (op, cn)) + win = true; + else if (spilled_pseudo_p (op)) + win = true; + break; } break; @@ -3701,7 +3709,8 @@ curr_insn_transform (bool check_only_p) constraint += CONSTRAINT_LEN (c, constraint)) { enum constraint_num cn = lookup_constraint (constraint); - if (insn_extra_memory_constraint (cn) + if ((insn_extra_memory_constraint (cn) + || insn_extra_special_memory_constraint (cn)) && satisfies_memory_constraint_p (tem, cn)) break; } diff --git a/gcc/recog.c b/gcc/recog.c index 3dddbbd..92b2aa3 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1791,6 +1791,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints) break; case CT_MEMORY: + case CT_SPECIAL_MEMORY: /* Every memory operand can be reloaded to fit. */ result = result || memory_operand (op, VOIDmode); break; @@ -2403,6 +2404,7 @@ preprocess_constraints (int n_operands, int n_alternatives, break; case CT_MEMORY: + case CT_SPECIAL_MEMORY: op_alt[i].memory_ok = 1; break; diff --git a/gcc/reload.c b/gcc/reload.c index 4646545..6196e63 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -3471,6 +3471,23 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known, offmemok = 1; break; + case CT_SPECIAL_MEMORY: + if (force_reload) + break; + if (constraint_satisfied_p (operand, cn)) + win = 1; + /* Likewise if the address will be reloaded because + reg_equiv_address is nonzero. For reg_equiv_mem + we have to check. */ + else if (REG_P (operand) + && REGNO (operand) >= FIRST_PSEUDO_REGISTER + && reg_renumber[REGNO (operand)] < 0 + && reg_equiv_mem (REGNO (operand)) != 0 + && (constraint_satisfied_p + (reg_equiv_mem (REGNO (operand)), cn))) + win = 1; + break; + case CT_ADDRESS: if (constraint_satisfied_p (operand, cn)) win = 1; diff --git a/gcc/rtl.def b/gcc/rtl.def index aef5036..0b7f894 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -1035,6 +1035,7 @@ DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sss", RT RTL object. */ 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_ADDRESS_CONSTRAINT, "define_address_constraint", "sse", RTX_EXTRA) diff --git a/gcc/stmt.c b/gcc/stmt.c index f9a694e..2e9072f 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -434,7 +434,8 @@ parse_input_constraint (const char **constraint_p, int input_num, if (reg_class_for_constraint (cn) != NO_REGS || insn_extra_address_constraint (cn)) *allows_reg = true; - else if (insn_extra_memory_constraint (cn)) + else if (insn_extra_memory_constraint (cn) + || insn_extra_special_memory_constraint (cn)) *allows_mem = true; else insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem); -- 2.7.4