Commit 9eb1ca69 by Vladimir Makarov Committed by Vladimir Makarov

re PR target/69299 (-mavx performance degradation with r232088)

2016-01-29  Vladimir Makarov  <vmakarov@redhat.com>

	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.

From-SVN: r232993
parent 6bbacdb5
2016-01-29 Vladimir Makarov <vmakarov@redhat.com>
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 <hongjiu.lu@intel.com> 2016-01-29 H.J. Lu <hongjiu.lu@intel.com>
PR target/69530 PR target/69530
......
...@@ -162,7 +162,7 @@ ...@@ -162,7 +162,7 @@
"@internal GOT memory operand." "@internal GOT memory operand."
(match_operand 0 "GOT_memory_operand")) (match_operand 0 "GOT_memory_operand"))
(define_constraint "Bm" (define_special_memory_constraint "Bm"
"@internal Vector memory operand." "@internal Vector memory operand."
(match_operand 0 "vector_memory_operand")) (match_operand 0 "vector_memory_operand"))
......
...@@ -4424,6 +4424,20 @@ The syntax and semantics are otherwise identical to ...@@ -4424,6 +4424,20 @@ The syntax and semantics are otherwise identical to
@code{define_constraint}. @code{define_constraint}.
@end deffn @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 @deffn {MD Expression} define_address_constraint name docstring exp
Use this expression for constraints that match a subset of all address Use this expression for constraints that match a subset of all address
operands: that is, @code{reload} can make the constraint match by operands: that is, @code{reload} can make the constraint match by
......
...@@ -1019,6 +1019,7 @@ main (int argc, char **argv) ...@@ -1019,6 +1019,7 @@ main (int argc, char **argv)
case DEFINE_REGISTER_CONSTRAINT: case DEFINE_REGISTER_CONSTRAINT:
case DEFINE_ADDRESS_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT:
case DEFINE_MEMORY_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT:
case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
note_constraint (&info); note_constraint (&info);
break; break;
......
...@@ -659,11 +659,11 @@ write_one_predicate_function (struct pred_data *p) ...@@ -659,11 +659,11 @@ write_one_predicate_function (struct pred_data *p)
/* Constraints fall into two categories: register constraints /* Constraints fall into two categories: register constraints
(define_register_constraint), and others (define_constraint, (define_register_constraint), and others (define_constraint,
define_memory_constraint, define_address_constraint). We define_memory_constraint, define_special_memory_constraint,
work out automatically which of the various old-style macros define_address_constraint). We work out automatically which of the
they correspond to, and produce appropriate code. They all various old-style macros they correspond to, and produce
go in the same hash table so we can verify that there are no appropriate code. They all go in the same hash table so we can
duplicate names. */ verify that there are no duplicate names. */
/* All data from one constraint definition. */ /* All data from one constraint definition. */
struct constraint_data struct constraint_data
...@@ -681,6 +681,7 @@ struct constraint_data ...@@ -681,6 +681,7 @@ struct constraint_data
unsigned int is_const_dbl : 1; unsigned int is_const_dbl : 1;
unsigned int is_extra : 1; unsigned int is_extra : 1;
unsigned int is_memory : 1; unsigned int is_memory : 1;
unsigned int is_special_memory: 1;
unsigned int is_address : 1; unsigned int is_address : 1;
unsigned int maybe_allows_reg : 1; unsigned int maybe_allows_reg : 1;
unsigned int maybe_allows_mem : 1; unsigned int maybe_allows_mem : 1;
...@@ -718,6 +719,7 @@ static const char const_dbl_constraints[] = "GH"; ...@@ -718,6 +719,7 @@ static const char const_dbl_constraints[] = "GH";
static unsigned int constraint_max_namelen; static unsigned int constraint_max_namelen;
static bool have_register_constraints; static bool have_register_constraints;
static bool have_memory_constraints; static bool have_memory_constraints;
static bool have_special_memory_constraints;
static bool have_address_constraints; static bool have_address_constraints;
static bool have_extra_constraints; static bool have_extra_constraints;
static bool have_const_int_constraints; static bool have_const_int_constraints;
...@@ -728,6 +730,7 @@ static unsigned int register_start, register_end; ...@@ -728,6 +730,7 @@ static unsigned int register_start, register_end;
static unsigned int satisfied_start; static unsigned int satisfied_start;
static unsigned int const_int_start, const_int_end; static unsigned int const_int_start, const_int_end;
static unsigned int memory_start, memory_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 address_start, address_end;
static unsigned int maybe_allows_none_start, maybe_allows_none_end; static unsigned int maybe_allows_none_start, maybe_allows_none_end;
static unsigned int maybe_allows_reg_start, maybe_allows_reg_end; static unsigned int maybe_allows_reg_start, maybe_allows_reg_end;
...@@ -754,20 +757,22 @@ mangle (const char *name) ...@@ -754,20 +757,22 @@ mangle (const char *name)
/* Add one constraint, of any sort, to the tables. NAME is its 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 REGCLASS is the register class, if any; EXP is the expression to
test, if any; IS_MEMORY and IS_ADDRESS indicate memory and address test, if any; IS_MEMORY, IS_SPECIAL_MEMORY and IS_ADDRESS indicate
constraints, respectively; LOC is the .md file location. memory, special memory, and address constraints, respectively; LOC
is the .md file location.
Not all combinations of arguments are valid; most importantly, REGCLASS Not all combinations of arguments are valid; most importantly,
is mutually exclusive with EXP, and IS_MEMORY/IS_ADDRESS are only REGCLASS is mutually exclusive with EXP, and
meaningful for constraints with EXP. IS_MEMORY/IS_SPECIAL_MEMORY/IS_ADDRESS are only meaningful for
constraints with EXP.
This function enforces all syntactic and semantic rules about what This function enforces all syntactic and semantic rules about what
constraints can be defined. */ constraints can be defined. */
static void static void
add_constraint (const char *name, const char *regclass, add_constraint (const char *name, const char *regclass,
rtx exp, bool is_memory, bool is_address, rtx exp, bool is_memory, bool is_special_memory,
file_location loc) bool is_address, file_location loc)
{ {
struct constraint_data *c, **iter, **slot; struct constraint_data *c, **iter, **slot;
const char *p; const char *p;
...@@ -878,6 +883,17 @@ add_constraint (const char *name, const char *regclass, ...@@ -878,6 +883,17 @@ add_constraint (const char *name, const char *regclass,
name, name[0]); name, name[0]);
return; 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) else if (is_address)
{ {
if (name[1] == '\0') if (name[1] == '\0')
...@@ -904,6 +920,7 @@ add_constraint (const char *name, const char *regclass, ...@@ -904,6 +920,7 @@ add_constraint (const char *name, const char *regclass,
c->is_const_dbl = is_const_dbl; c->is_const_dbl = is_const_dbl;
c->is_extra = !(regclass || is_const_int || is_const_dbl); c->is_extra = !(regclass || is_const_int || is_const_dbl);
c->is_memory = is_memory; c->is_memory = is_memory;
c->is_special_memory = is_special_memory;
c->is_address = is_address; c->is_address = is_address;
c->maybe_allows_reg = true; c->maybe_allows_reg = true;
c->maybe_allows_mem = true; c->maybe_allows_mem = true;
...@@ -930,17 +947,20 @@ add_constraint (const char *name, const char *regclass, ...@@ -930,17 +947,20 @@ add_constraint (const char *name, const char *regclass,
have_const_int_constraints |= c->is_const_int; have_const_int_constraints |= c->is_const_int;
have_extra_constraints |= c->is_extra; have_extra_constraints |= c->is_extra;
have_memory_constraints |= c->is_memory; have_memory_constraints |= c->is_memory;
have_special_memory_constraints |= c->is_special_memory;
have_address_constraints |= c->is_address; have_address_constraints |= c->is_address;
num_constraints += 1; num_constraints += 1;
} }
/* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, or /* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT,
DEFINE_ADDRESS_CONSTRAINT expression, C. */ DEFINE_SPECIAL_MEMORY_CONSTRAINT, or DEFINE_ADDRESS_CONSTRAINT
expression, C. */
static void static void
process_define_constraint (md_rtx_info *info) process_define_constraint (md_rtx_info *info)
{ {
add_constraint (XSTR (info->def, 0), 0, XEXP (info->def, 2), add_constraint (XSTR (info->def, 0), 0, XEXP (info->def, 2),
GET_CODE (info->def) == DEFINE_MEMORY_CONSTRAINT, GET_CODE (info->def) == DEFINE_MEMORY_CONSTRAINT,
GET_CODE (info->def) == DEFINE_SPECIAL_MEMORY_CONSTRAINT,
GET_CODE (info->def) == DEFINE_ADDRESS_CONSTRAINT, GET_CODE (info->def) == DEFINE_ADDRESS_CONSTRAINT,
info->loc); info->loc);
} }
...@@ -950,7 +970,7 @@ static void ...@@ -950,7 +970,7 @@ static void
process_define_register_constraint (md_rtx_info *info) process_define_register_constraint (md_rtx_info *info)
{ {
add_constraint (XSTR (info->def, 0), XSTR (info->def, 1), 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 /* Put the constraints into enum order. We want to keep constraints
...@@ -984,6 +1004,12 @@ choose_enum_order (void) ...@@ -984,6 +1004,12 @@ choose_enum_order (void)
enum_order[next++] = c; enum_order[next++] = c;
memory_end = next; 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; address_start = next;
FOR_ALL_CONSTRAINTS (c) FOR_ALL_CONSTRAINTS (c)
if (c->is_address) if (c->is_address)
...@@ -992,27 +1018,31 @@ choose_enum_order (void) ...@@ -992,27 +1018,31 @@ choose_enum_order (void)
maybe_allows_none_start = next; maybe_allows_none_start = next;
FOR_ALL_CONSTRAINTS (c) 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) && !c->maybe_allows_reg && !c->maybe_allows_mem)
enum_order[next++] = c; enum_order[next++] = c;
maybe_allows_none_end = next; maybe_allows_none_end = next;
maybe_allows_reg_start = next; maybe_allows_reg_start = next;
FOR_ALL_CONSTRAINTS (c) 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) && c->maybe_allows_reg && !c->maybe_allows_mem)
enum_order[next++] = c; enum_order[next++] = c;
maybe_allows_reg_end = next; maybe_allows_reg_end = next;
maybe_allows_mem_start = next; maybe_allows_mem_start = next;
FOR_ALL_CONSTRAINTS (c) 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) && !c->maybe_allows_reg && c->maybe_allows_mem)
enum_order[next++] = c; enum_order[next++] = c;
maybe_allows_mem_end = next; maybe_allows_mem_end = next;
FOR_ALL_CONSTRAINTS (c) 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) && c->maybe_allows_reg && c->maybe_allows_mem)
enum_order[next++] = c; enum_order[next++] = c;
gcc_assert (next == num_constraints); gcc_assert (next == num_constraints);
...@@ -1431,6 +1461,8 @@ write_tm_preds_h (void) ...@@ -1431,6 +1461,8 @@ write_tm_preds_h (void)
register_start, register_end); register_start, register_end);
write_range_function ("insn_extra_memory_constraint", write_range_function ("insn_extra_memory_constraint",
memory_start, memory_end); 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", write_range_function ("insn_extra_address_constraint",
address_start, address_end); address_start, address_end);
write_allows_reg_mem_function (); write_allows_reg_mem_function ();
...@@ -1479,6 +1511,7 @@ write_tm_preds_h (void) ...@@ -1479,6 +1511,7 @@ write_tm_preds_h (void)
" CT_REGISTER,\n" " CT_REGISTER,\n"
" CT_CONST_INT,\n" " CT_CONST_INT,\n"
" CT_MEMORY,\n" " CT_MEMORY,\n"
" CT_SPECIAL_MEMORY,\n"
" CT_ADDRESS,\n" " CT_ADDRESS,\n"
" CT_FIXED_FORM\n" " CT_FIXED_FORM\n"
"};\n" "};\n"
...@@ -1491,6 +1524,8 @@ write_tm_preds_h (void) ...@@ -1491,6 +1524,8 @@ write_tm_preds_h (void)
values.safe_push (std::make_pair (const_int_start, "CT_CONST_INT")); values.safe_push (std::make_pair (const_int_start, "CT_CONST_INT"));
if (memory_start != memory_end) if (memory_start != memory_end)
values.safe_push (std::make_pair (memory_start, "CT_MEMORY")); 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) if (address_start != address_end)
values.safe_push (std::make_pair (address_start, "CT_ADDRESS")); values.safe_push (std::make_pair (address_start, "CT_ADDRESS"));
if (address_end != num_constraints) if (address_end != num_constraints)
...@@ -1602,6 +1637,7 @@ main (int argc, char **argv) ...@@ -1602,6 +1637,7 @@ main (int argc, char **argv)
case DEFINE_CONSTRAINT: case DEFINE_CONSTRAINT:
case DEFINE_MEMORY_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT:
case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
case DEFINE_ADDRESS_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT:
process_define_constraint (&info); process_define_constraint (&info);
break; break;
......
...@@ -521,6 +521,7 @@ process_rtx (rtx desc, file_location loc) ...@@ -521,6 +521,7 @@ process_rtx (rtx desc, file_location loc)
case DEFINE_CONSTRAINT: case DEFINE_CONSTRAINT:
case DEFINE_REGISTER_CONSTRAINT: case DEFINE_REGISTER_CONSTRAINT:
case DEFINE_MEMORY_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT:
case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
case DEFINE_ADDRESS_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT:
queue_pattern (desc, &define_pred_tail, loc); queue_pattern (desc, &define_pred_tail, loc);
break; break;
......
...@@ -783,6 +783,12 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, ...@@ -783,6 +783,12 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
win = 1; win = 1;
break; 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: case CT_ADDRESS:
/* Every address can be reloaded to fit. */ /* Every address can be reloaded to fit. */
allows_addr = 1; allows_addr = 1;
......
...@@ -774,6 +774,7 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const) ...@@ -774,6 +774,7 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
/* ??? Is this the best way to handle memory constraints? */ /* ??? Is this the best way to handle memory constraints? */
cn = lookup_constraint (constraints); cn = lookup_constraint (constraints);
if (insn_extra_memory_constraint (cn) if (insn_extra_memory_constraint (cn)
|| insn_extra_special_memory_constraint (cn)
|| insn_extra_address_constraint (cn)) || insn_extra_address_constraint (cn))
return NO_REGS; return NO_REGS;
if (constraint_satisfied_p (op, cn) if (constraint_satisfied_p (op, cn)
......
...@@ -1868,6 +1868,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts) ...@@ -1868,6 +1868,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
case CT_ADDRESS: case CT_ADDRESS:
case CT_MEMORY: case CT_MEMORY:
case CT_SPECIAL_MEMORY:
goto op_success; goto op_success;
case CT_FIXED_FORM: case CT_FIXED_FORM:
......
...@@ -400,7 +400,7 @@ valid_address_p (struct address_info *ad) ...@@ -400,7 +400,7 @@ valid_address_p (struct address_info *ad)
} }
/* Return true if the eliminated form of memory reference OP satisfies /* Return true if the eliminated form of memory reference OP satisfies
extra memory constraint CONSTRAINT. */ extra (special) memory constraint CONSTRAINT. */
static bool static bool
satisfies_memory_constraint_p (rtx op, enum constraint_num constraint) satisfies_memory_constraint_p (rtx op, enum constraint_num constraint)
{ {
...@@ -2038,6 +2038,14 @@ process_alt_operands (int only_alternative) ...@@ -2038,6 +2038,14 @@ process_alt_operands (int only_alternative)
if (constraint_satisfied_p (op, cn)) if (constraint_satisfied_p (op, cn))
win = true; win = true;
break; 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; break;
...@@ -3701,7 +3709,8 @@ curr_insn_transform (bool check_only_p) ...@@ -3701,7 +3709,8 @@ curr_insn_transform (bool check_only_p)
constraint += CONSTRAINT_LEN (c, constraint)) constraint += CONSTRAINT_LEN (c, constraint))
{ {
enum constraint_num cn = lookup_constraint (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)) && satisfies_memory_constraint_p (tem, cn))
break; break;
} }
......
...@@ -1791,6 +1791,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints) ...@@ -1791,6 +1791,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
break; break;
case CT_MEMORY: case CT_MEMORY:
case CT_SPECIAL_MEMORY:
/* Every memory operand can be reloaded to fit. */ /* Every memory operand can be reloaded to fit. */
result = result || memory_operand (op, VOIDmode); result = result || memory_operand (op, VOIDmode);
break; break;
...@@ -2403,6 +2404,7 @@ preprocess_constraints (int n_operands, int n_alternatives, ...@@ -2403,6 +2404,7 @@ preprocess_constraints (int n_operands, int n_alternatives,
break; break;
case CT_MEMORY: case CT_MEMORY:
case CT_SPECIAL_MEMORY:
op_alt[i].memory_ok = 1; op_alt[i].memory_ok = 1;
break; break;
......
...@@ -3471,6 +3471,23 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known, ...@@ -3471,6 +3471,23 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
offmemok = 1; offmemok = 1;
break; 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: case CT_ADDRESS:
if (constraint_satisfied_p (operand, cn)) if (constraint_satisfied_p (operand, cn))
win = 1; win = 1;
......
...@@ -1035,6 +1035,7 @@ DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sss", RT ...@@ -1035,6 +1035,7 @@ DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sss", RT
RTL object. */ RTL object. */
DEF_RTL_EXPR(DEFINE_CONSTRAINT, "define_constraint", "sse", RTX_EXTRA) 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_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) DEF_RTL_EXPR(DEFINE_ADDRESS_CONSTRAINT, "define_address_constraint", "sse", RTX_EXTRA)
......
...@@ -434,7 +434,8 @@ parse_input_constraint (const char **constraint_p, int input_num, ...@@ -434,7 +434,8 @@ parse_input_constraint (const char **constraint_p, int input_num,
if (reg_class_for_constraint (cn) != NO_REGS if (reg_class_for_constraint (cn) != NO_REGS
|| insn_extra_address_constraint (cn)) || insn_extra_address_constraint (cn))
*allows_reg = true; *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; *allows_mem = true;
else else
insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem); insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment