The following patch fixes PR69299.
The details of the problem is described on
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69299
The patch was successfully bootstrapped and tested on x86/x86-64.
The patch introduces a new type of constraints
define_special_memory_constraint for memory constraints whose address
reload can not make memory to satisfy the constraint. It is useful when
specifically aligned memory is necessary or desirable. I don't know what
is the best name for this constraint. I use special_memory_constraint
but it could be more specific, e.g. aligned_memory_constraint. Please
let me know what is the best name for you.
Is the patch ok to commit?
Index: ChangeLog
===================================================================
--- ChangeLog (revision 232903)
+++ ChangeLog (working copy)
@@ -1,3 +1,37 @@
+2016-01-27 Vladimir Makarov <vmaka...@redhat.com>
+
+ PR target/68990
+ * 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-27 H.J. Lu <hongjiu...@intel.com>
PR target/68986
Index: config/i386/constraints.md
===================================================================
--- config/i386/constraints.md (revision 232571)
+++ config/i386/constraints.md (working copy)
@@ -161,7 +161,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"))
Index: doc/md.texi
===================================================================
--- doc/md.texi (revision 232571)
+++ doc/md.texi (working copy)
@@ -4424,6 +4424,20 @@ The syntax and semantics are otherwise i
@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
Index: genoutput.c
===================================================================
--- genoutput.c (revision 232571)
+++ genoutput.c (working copy)
@@ -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;
Index: genpreds.c
===================================================================
--- genpreds.c (revision 232571)
+++ genpreds.c (working copy)
@@ -659,11 +659,11 @@ write_one_predicate_function (struct pre
/* 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[
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, regi
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.
-
- 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.
+ 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_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
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
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
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;
Index: gensupport.c
===================================================================
--- gensupport.c (revision 232571)
+++ gensupport.c (working copy)
@@ -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;
Index: ira-costs.c
===================================================================
--- ira-costs.c (revision 232571)
+++ ira-costs.c (working copy)
@@ -777,6 +777,7 @@ record_reg_classes (int n_alts, int n_op
break;
case CT_MEMORY:
+ case CT_SPECIAL_MEMORY:
/* Every MEM can be reloaded to fit. */
insn_allows_mem[i] = allows_mem[i] = 1;
if (MEM_P (op))
Index: ira-lives.c
===================================================================
--- ira-lives.c (revision 232571)
+++ ira-lives.c (working copy)
@@ -774,6 +774,7 @@ single_reg_class (const char *constraint
/* ??? 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)
Index: ira.c
===================================================================
--- ira.c (revision 232571)
+++ ira.c (working copy)
@@ -1868,6 +1868,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG
case CT_ADDRESS:
case CT_MEMORY:
+ case CT_SPECIAL_MEMORY:
goto op_success;
case CT_FIXED_FORM:
Index: lra-constraints.c
===================================================================
--- lra-constraints.c (revision 232571)
+++ lra-constraints.c (working copy)
@@ -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_alternati
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;
}
Index: recog.c
===================================================================
--- recog.c (revision 232571)
+++ recog.c (working copy)
@@ -1791,6 +1791,7 @@ asm_operand_ok (rtx op, const char *cons
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,
break;
case CT_MEMORY:
+ case CT_SPECIAL_MEMORY:
op_alt[i].memory_ok = 1;
break;
Index: reload.c
===================================================================
--- reload.c (revision 232571)
+++ reload.c (working copy)
@@ -3471,6 +3471,23 @@ find_reloads (rtx_insn *insn, int replac
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;
Index: rtl.def
===================================================================
--- rtl.def (revision 232571)
+++ rtl.def (working copy)
@@ -1035,6 +1035,7 @@ DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT,
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)
Index: stmt.c
===================================================================
--- stmt.c (revision 232571)
+++ stmt.c (working copy)
@@ -434,7 +434,8 @@ parse_input_constraint (const char **con
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);