From: Richard Sandiford <rdsandiford@googlemail.com>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH 4/8] Remove old macros and make lookup_constraint explicit
Date: Thu, 05 Jun 2014 21:32:00 -0000 [thread overview]
Message-ID: <87bnu79h58.fsf@talisman.default> (raw)
In-Reply-To: <87sinj9hhy.fsf@talisman.default> (Richard Sandiford's message of "Thu, 05 Jun 2014 22:24:57 +0100")
Now that all extra constraints are defined in .md files, there's no real
need for the old REG_CLASS_FROM_CONSTRAINT-style macros. The macros also
seem dangerous performance-wise, since each one contains an embedded call to
lookup_constraint. This means that code like:
if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
{
if (EXTRA_MEMORY_CONSTRAINT (c, p))
... EXTRA_CONSTRAINT_STR ...
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
... EXTRA_CONSTRAINT_STR ...
... EXTRA_CONSTRAINT_STR ...
}
...REG_CLASS_FROM_CONSTRAINT...
looks up the same constraint several times.
This patch replaces all uses of:
REG_CLASS_FROM_CONSTRAINT
REG_CLASS_FOR_CONSTRAINT
EXTRA_CONSTRAINT_STR
EXTRA_MEMORY_CONSTRAINT
EXTRA_ADDRESS_CONSTRAINT
with separate calls to lookup_constraint and the underlying query function.
It poisons the old macros as a way of protecting against accidental use
(e.g. in #ifdef EXTRA_CONSTRAINT_STR blocks).
Several places want to handle each specific type of constraint in a
different way, so I added a convenience function for classifying constraints
into a type enum. This also makes the range checks more efficient.
I've treated CONSTRAINT__UNKNOWN as a register constraint (the first type)
since that avoids one more range check and means that each consumer doesn't
have to handle non-constraints specially. The range check in
reg_class_for_constraint already ensures that the CONSTRAINT__UNKNOWN->
NO_REGS mapping is inline.
Richard
gcc/
* system.h (REG_CLASS_FROM_CONSTRAINT): Poison.
(REG_CLASS_FOR_CONSTRAINT, EXTRA_CONSTRAINT_STR): Likewise.
(EXTRA_MEMORY_CONSTRAINT, EXTRA_ADDRESS_CONSTRAINT): Likewise.
* genpreds.c (print_type_tree): New function.
(write_tm_preds_h): Remove REG_CLASS_FROM_CONSTRAINT,
REG_CLASS_FOR_CONSTRAINT, EXTRA_MEMORY_CONSTRAINT,
EXTRA_ADDRESS_CONSTRAINT and EXTRA_CONSTRAINT_STR.
Write out enum constraint_type and get_constraint_type.
* lra-constraints.c (satisfies_memory_constraint_p): Take a
constraint_num rather than a constraint string.
(satisfies_address_constraint_p): Likewise.
(reg_class_from_constraints): Avoid old constraint macros.
(process_alt_operands, process_address_1): Likewise.
(curr_insn_transform): Likewise.
* ira-costs.c (record_reg_classes): Likewise.
(record_operand_costs): Likewise.
* ira-lives.c (single_reg_class): Likewise.
(ira_implicitly_set_insn_hard_regs): Likewise.
* ira.c (ira_setup_alts, ira_get_dup_out_num): Likewise.
* postreload.c (reload_cse_simplify_operands): Likewise.
* recog.c (asm_operand_ok, preprocess_constraints): Likewise.
(constrain_operands, peep2_find_free_register): Likewise.
* reload.c (push_secondary_reload, scratch_reload_class): Likewise.
(find_reloads, alternative_allows_const_pool_ref): Likewise.
* reload1.c (maybe_fix_stack_asms): Likewise.
* stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
* targhooks.c (default_secondary_reload): Likewise.
* config/m32c/m32c.c (m32c_matches_constraint_p): Avoid reference
to EXTRA_CONSTRAINT_STR.
* config/sparc/constraints.md (U): Likewise REG_CLASS_FROM_CONSTRAINT.
Index: gcc/system.h
===================================================================
--- gcc/system.h 2014-06-05 21:06:52.721540056 +0100
+++ gcc/system.h 2014-06-05 21:45:00.219282847 +0100
@@ -930,7 +930,10 @@ #define realloc xrealloc
GO_IF_MODE_DEPENDENT_ADDRESS DELAY_SLOTS_FOR_EPILOGUE \
ELIGIBLE_FOR_EPILOGUE_DELAY TARGET_C99_FUNCTIONS TARGET_HAS_SINCOS \
REG_CLASS_FROM_LETTER CONST_OK_FOR_LETTER_P \
- CONST_DOUBLE_OK_FOR_LETTER_P EXTRA_CONSTRAINT
+ CONST_DOUBLE_OK_FOR_LETTER_P EXTRA_CONSTRAINT \
+ REG_CLASS_FROM_CONSTRAINT REG_CLASS_FOR_CONSTRAINT \
+ EXTRA_CONSTRAINT_STR EXTRA_MEMORY_CONSTRAINT \
+ EXTRA_ADDRESS_CONSTRAINT
/* Hooks that are no longer used. */
#pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
Index: gcc/genpreds.c
===================================================================
--- gcc/genpreds.c 2014-06-05 21:45:00.187282566 +0100
+++ gcc/genpreds.c 2014-06-05 21:45:00.211282777 +0100
@@ -1232,6 +1232,33 @@ write_range_function (const char *name,
"}\n\n", name);
}
+/* VEC is a list of key/value pairs, with the keys being lower bounds
+ of a range. Output a decision tree that handles the keys covered by
+ [VEC[START], VEC[END]), returning FALLBACK for keys lower then VEC[START]'s.
+ INDENT is the number of spaces to indent the code. */
+static void
+print_type_tree (const vec <std::pair <unsigned int, const char *> > &vec,
+ unsigned int start, unsigned int end, const char *fallback,
+ unsigned int indent)
+{
+ while (start < end)
+ {
+ unsigned int mid = (start + end) / 2;
+ printf ("%*sif (c >= CONSTRAINT_%s)\n",
+ indent, "", enum_order[vec[mid].first]->c_name);
+ if (mid + 1 == end)
+ print_type_tree (vec, mid + 1, end, vec[mid].second, indent + 2);
+ else
+ {
+ printf ("%*s{\n", indent + 2, "");
+ print_type_tree (vec, mid + 1, end, vec[mid].second, indent + 4);
+ printf ("%*s}\n", indent + 2, "");
+ }
+ end = mid;
+ }
+ printf ("%*sreturn %s;\n", indent, "", fallback);
+}
+
/* Write tm-preds.h. Unfortunately, it is impossible to forward-declare
an enumeration in portable C, so we have to condition all these
prototypes on HAVE_MACHINE_MODES. */
@@ -1321,21 +1348,13 @@ #define GCC_TM_PREDS_H\n\
" if (insn_extra_register_constraint (c))\n"
" return reg_class_for_constraint_1 (c);\n"
" return NO_REGS;\n"
- "}\n"
- "\n"
- "#define REG_CLASS_FROM_CONSTRAINT(c_,s_) \\\n"
- " reg_class_for_constraint (lookup_constraint (s_))\n"
- "#define REG_CLASS_FOR_CONSTRAINT(x_) \\\n"
- " reg_class_for_constraint (x_)\n");
+ "}\n");
else
puts ("static inline enum reg_class\n"
"reg_class_for_constraint (enum constraint_num)\n"
"{\n"
" return NO_REGS;\n"
- "}\n\n"
- "#define REG_CLASS_FROM_CONSTRAINT(c_,s_) NO_REGS\n"
- "#define REG_CLASS_FOR_CONSTRAINT(x_) \\\n"
- " NO_REGS\n");
+ "}\n");
if (have_const_int_constraints)
puts ("extern bool insn_const_int_ok_for_constraint "
"(HOST_WIDE_INT, enum constraint_num);\n"
@@ -1347,19 +1366,27 @@ #define GCC_TM_PREDS_H\n\
" constraint_satisfied_p (v_, lookup_constraint (s_))\n");
else
puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) 0\n");
- if (have_extra_constraints)
- puts ("#define EXTRA_CONSTRAINT_STR(v_,c_,s_) \\\n"
- " constraint_satisfied_p (v_, lookup_constraint (s_))\n");
- if (have_memory_constraints)
- puts ("#define EXTRA_MEMORY_CONSTRAINT(c_,s_) "
- "insn_extra_memory_constraint (lookup_constraint (s_))\n");
- else
- puts ("#define EXTRA_MEMORY_CONSTRAINT(c_,s_) false\n");
- if (have_address_constraints)
- puts ("#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) "
- "insn_extra_address_constraint (lookup_constraint (s_))\n");
- else
- puts ("#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) false\n");
+
+ puts ("enum constraint_type\n"
+ "{\n"
+ " CT_REGISTER,\n"
+ " CT_MEMORY,\n"
+ " CT_ADDRESS,\n"
+ " CT_FIXED_FORM\n"
+ "};\n"
+ "\n"
+ "static inline enum constraint_type\n"
+ "get_constraint_type (enum constraint_num c)\n"
+ "{");
+ auto_vec <std::pair <unsigned int, const char *>, 3> values;
+ if (memory_start != memory_end)
+ values.safe_push (std::make_pair (memory_start, "CT_MEMORY"));
+ if (address_start != address_end)
+ values.safe_push (std::make_pair (address_start, "CT_ADDRESS"));
+ if (address_end != num_constraints)
+ values.safe_push (std::make_pair (address_end, "CT_FIXED_FORM"));
+ print_type_tree (values, 0, values.length (), "CT_REGISTER", 2);
+ puts ("}");
}
puts ("#endif /* tm-preds.h */");
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/lra-constraints.c 2014-06-05 21:46:37.913140623 +0100
@@ -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
@@ -982,21 +980,20 @@ reg_class_from_constraints (const char *
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;
@@ -1712,6 +1709,7 @@ process_alt_operands (int only_alternati
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)
@@ -2030,76 +2028,55 @@ process_alt_operands (int only_alternati
/* 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;
+ case CT_REGISTER:
+ cl = reg_class_for_constraint (cn);
+ if (cl != NO_REGS)
+ goto reg;
+ break;
- /* 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_MEMORY:
+ if (MEM_P (op)
+ && satisfies_memory_constraint_p (op, cn))
+ win = true;
+ else if (spilled_pseudo_p (op))
+ win = true;
- if (EXTRA_CONSTRAINT_STR (op, c, p))
+ /* 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 +2087,6 @@ process_alt_operands (int only_alternati
IOR_HARD_REG_SET (this_costly_alternative_set,
reg_class_contents[cl]);
}
- reg:
if (mode == BLKmode)
break;
winreg = true;
@@ -2856,10 +2832,11 @@ process_address_1 (int nop, rtx *before,
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))
+ || 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 +2865,12 @@ process_address_1 (int nop, rtx *before,
&& 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. */
+ /* Target hooks sometimes don't treat extra-constraint addresses as
+ legitimate address_operands, so handle them specially. */
if (constraint[0] != 'p'
- && EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
- && satisfies_address_constraint_p (&ad, constraint))
+ && 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:
@@ -3610,11 +3585,10 @@ curr_insn_transform (void)
{
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;
Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/ira-costs.c 2014-06-05 21:45:00.208282750 +0100
@@ -753,25 +753,28 @@ record_reg_classes (int n_alts, int n_op
break;
default:
- if (REG_CLASS_FROM_CONSTRAINT (c, p) != NO_REGS)
- classes[i] = ira_reg_class_subunion[classes[i]]
- [REG_CLASS_FROM_CONSTRAINT (c, p)];
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_CONSTRAINT_STR (op, c, p))
- win = 1;
-
- if (EXTRA_MEMORY_CONSTRAINT (c, p))
+ enum constraint_num cn = lookup_constraint (p);
+ enum reg_class cl;
+ switch (get_constraint_type (cn))
{
+ case CT_REGISTER:
+ cl = reg_class_for_constraint (cn);
+ if (cl != NO_REGS)
+ classes[i] = ira_reg_class_subunion[classes[i]][cl];
+ break;
+
+ case CT_MEMORY:
/* Every MEM can be reloaded to fit. */
insn_allows_mem[i] = allows_mem[i] = 1;
if (MEM_P (op))
win = 1;
- }
- if (EXTRA_ADDRESS_CONSTRAINT (c, p))
- {
+ break;
+
+ case CT_ADDRESS:
/* Every address can be reloaded to fit. */
allows_addr = 1;
- if (address_operand (op, GET_MODE (op)))
+ if (address_operand (op, GET_MODE (op))
+ || constraint_satisfied_p (op, cn))
win = 1;
/* We know this operand is an address, so we
want it to be allocated to a hard register
@@ -781,8 +784,13 @@ record_reg_classes (int n_alts, int n_op
= ira_reg_class_subunion[classes[i]]
[base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH)];
+ break;
+
+ case CT_FIXED_FORM:
+ if (constraint_satisfied_p (op, cn))
+ win = 1;
+ break;
}
-#endif
break;
}
p += CONSTRAINT_LEN (c, p);
@@ -1275,8 +1283,8 @@ record_operand_costs (rtx insn, enum reg
XEXP (recog_data.operand[i], 0),
0, MEM, SCRATCH, frequency * 2);
else if (constraints[i][0] == 'p'
- || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0],
- constraints[i]))
+ || (insn_extra_address_constraint
+ (lookup_constraint (constraints[i]))))
record_address_regs (VOIDmode, ADDR_SPACE_GENERIC,
recog_data.operand[i], 0, ADDRESS, SCRATCH,
frequency * 2);
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c 2014-06-05 21:45:00.132282083 +0100
+++ gcc/ira-lives.c 2014-06-05 21:45:00.212282786 +0100
@@ -759,6 +759,7 @@ single_reg_class (const char *constraint
{
int c;
enum reg_class cl, next_cl;
+ enum constraint_num cn;
cl = NO_REGS;
alternative_mask enabled = recog_data.enabled_alternatives;
@@ -849,20 +850,19 @@ single_reg_class (const char *constraint
case 'A': case 'B': case 'C': case 'D':
case 'Q': case 'R': case 'S': case 'T': case 'U':
case 'W': case 'Y': case 'Z':
-#ifdef EXTRA_CONSTRAINT_STR
/* ??? Is this the best way to handle memory constraints? */
- if (EXTRA_MEMORY_CONSTRAINT (c, constraints)
- || EXTRA_ADDRESS_CONSTRAINT (c, constraints))
+ cn = lookup_constraint (constraints);
+ if (insn_extra_memory_constraint (cn)
+ || insn_extra_address_constraint (cn))
return NO_REGS;
- if (EXTRA_CONSTRAINT_STR (op, c, constraints)
+ if (constraint_satisfied_p (op, cn)
|| (equiv_const != NULL_RTX
&& CONSTANT_P (equiv_const)
- && EXTRA_CONSTRAINT_STR (equiv_const, c, constraints)))
+ && constraint_satisfied_p (equiv_const, cn)))
return NO_REGS;
-#endif
next_cl = (c == 'r'
? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT (c, constraints));
+ : reg_class_for_constraint (cn));
if (next_cl == NO_REGS)
break;
if (cl == NO_REGS
@@ -950,7 +950,7 @@ ira_implicitly_set_insn_hard_regs (HARD_
case 'W': case 'Y': case 'Z':
cl = (c == 'r'
? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT (c, p));
+ : reg_class_for_constraint (lookup_constraint (p)));
if (cl != NO_REGS)
{
/* There is no register pressure problem if all of the
Index: gcc/ira.c
===================================================================
--- gcc/ira.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/ira.c 2014-06-05 21:45:00.204282715 +0100
@@ -1922,24 +1922,29 @@ ira_setup_alts (rtx insn, HARD_REG_SET &
break;
case 'o':
+ case 'r':
goto op_success;
break;
default:
{
- enum reg_class cl;
-
- cl = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
- if (cl != NO_REGS)
- goto op_success;
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_CONSTRAINT_STR (op, c, p))
- goto op_success;
- else if (EXTRA_MEMORY_CONSTRAINT (c, p))
- goto op_success;
- else if (EXTRA_ADDRESS_CONSTRAINT (c, p))
- goto op_success;
-#endif
+ enum constraint_num cn = lookup_constraint (p);
+ switch (get_constraint_type (cn))
+ {
+ case CT_REGISTER:
+ if (reg_class_for_constraint (cn) != NO_REGS)
+ goto op_success;
+ break;
+
+ case CT_ADDRESS:
+ case CT_MEMORY:
+ goto op_success;
+
+ case CT_FIXED_FORM:
+ if (constraint_satisfied_p (op, cn))
+ goto op_success;
+ break;
+ }
break;
}
}
@@ -1972,9 +1977,6 @@ ira_get_dup_out_num (int op_num, HARD_RE
int curr_alt, c, original, dup;
bool ignore_p, use_commut_op_p;
const char *str;
-#ifdef EXTRA_CONSTRAINT_STR
- rtx op;
-#endif
if (op_num < 0 || recog_data.n_alternatives == 0)
return -1;
@@ -1985,9 +1987,7 @@ ira_get_dup_out_num (int op_num, HARD_RE
use_commut_op_p = false;
for (;;)
{
-#ifdef EXTRA_CONSTRAINT_STR
- op = recog_data.operand[op_num];
-#endif
+ rtx op = recog_data.operand[op_num];
for (curr_alt = 0, ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt),
original = -1;;)
@@ -2010,6 +2010,9 @@ ira_get_dup_out_num (int op_num, HARD_RE
case 'g':
goto fail;
case 'r':
+ if (!targetm.class_likely_spilled_p (GENERAL_REGS))
+ goto fail;
+ break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'h': case 'j': case 'k': case 'l':
case 'q': case 't': case 'u':
@@ -2018,19 +2021,13 @@ ira_get_dup_out_num (int op_num, HARD_RE
case 'Q': case 'R': case 'S': case 'T': case 'U':
case 'W': case 'Y': case 'Z':
{
- enum reg_class cl;
-
- cl = (c == 'r'
- ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str));
- if (cl != NO_REGS)
- {
- if (! targetm.class_likely_spilled_p (cl))
- goto fail;
- }
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_CONSTRAINT_STR (op, c, str))
+ enum constraint_num cn = lookup_constraint (str);
+ enum reg_class cl = reg_class_for_constraint (cn);
+ if (cl != NO_REGS
+ && !targetm.class_likely_spilled_p (cl))
+ goto fail;
+ if (constraint_satisfied_p (op, cn))
goto fail;
-#endif
break;
}
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/postreload.c 2014-06-05 21:45:00.220282856 +0100
@@ -574,8 +574,8 @@ reload_cse_simplify_operands (rtx insn,
default:
rclass
= (reg_class_subunion
- [(int) rclass]
- [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
+ [rclass]
+ [reg_class_for_constraint (lookup_constraint (p))]);
break;
case ',': case '\0':
Index: gcc/recog.c
===================================================================
--- gcc/recog.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/recog.c 2014-06-05 21:45:00.209282759 +0100
@@ -1729,6 +1729,7 @@ asm_operand_ok (rtx op, const char *cons
while (*constraint)
{
+ enum constraint_num cn;
char c = *constraint;
int len;
switch (c)
@@ -1902,27 +1903,37 @@ asm_operand_ok (rtx op, const char *cons
result = 1;
break;
+ case 'r':
+ reg:
+ if (!result
+ && GET_MODE (op) != BLKmode
+ && register_operand (op, VOIDmode))
+ result = 1;
+ break;
+
default:
- /* For all other letters, we first check for a register class,
- otherwise it is an EXTRA_CONSTRAINT. */
- if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
+ cn = lookup_constraint (constraint);
+ switch (get_constraint_type (cn))
{
- case 'r':
- if (GET_MODE (op) == BLKmode)
- break;
- if (register_operand (op, VOIDmode))
- result = 1;
+ case CT_REGISTER:
+ if (reg_class_for_constraint (cn) != NO_REGS)
+ goto reg;
+ break;
+
+ case CT_MEMORY:
+ /* Every memory operand can be reloaded to fit. */
+ result = result || memory_operand (op, VOIDmode);
+ break;
+
+ case CT_ADDRESS:
+ /* Every address operand can be reloaded to fit. */
+ result = result || address_operand (op, VOIDmode);
+ break;
+
+ case CT_FIXED_FORM:
+ result = result || constraint_satisfied_p (op, cn);
+ break;
}
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_MEMORY_CONSTRAINT (c, constraint))
- /* Every memory operand can be reloaded to fit. */
- result = result || memory_operand (op, VOIDmode);
- else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint))
- /* Every address operand can be reloaded to fit. */
- result = result || address_operand (op, VOIDmode);
- else if (EXTRA_CONSTRAINT_STR (op, c, constraint))
- result = 1;
-#endif
break;
}
len = CONSTRAINT_LEN (c, constraint);
@@ -2434,13 +2445,21 @@ preprocess_constraints (int n_operands,
break;
default:
- if (EXTRA_MEMORY_CONSTRAINT (c, p))
+ enum constraint_num cn = lookup_constraint (p);
+ enum reg_class cl;
+ switch (get_constraint_type (cn))
{
+ case CT_REGISTER:
+ cl = reg_class_for_constraint (cn);
+ if (cl != NO_REGS)
+ op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl];
+ break;
+
+ case CT_MEMORY:
op_alt[i].memory_ok = 1;
break;
- }
- if (EXTRA_ADDRESS_CONSTRAINT (c, p))
- {
+
+ case CT_ADDRESS:
op_alt[i].is_address = 1;
op_alt[i].cl
= (reg_class_subunion
@@ -2448,12 +2467,10 @@ preprocess_constraints (int n_operands,
[(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH)]);
break;
- }
- op_alt[i].cl
- = (reg_class_subunion
- [(int) op_alt[i].cl]
- [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
+ case CT_FIXED_FORM:
+ break;
+ }
break;
}
p += CONSTRAINT_LEN (c, p);
@@ -2846,9 +2863,12 @@ constrain_operands (int strict)
default:
{
enum reg_class cl;
+ enum constraint_num cn = (c == 'r'
+ ? CONSTRAINT__UNKNOWN
+ : lookup_constraint (p));
cl = (c == 'r'
- ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
+ ? GENERAL_REGS : reg_class_for_constraint (cn));
if (cl != NO_REGS)
{
if (strict < 0
@@ -2860,11 +2880,11 @@ constrain_operands (int strict)
&& reg_fits_class_p (op, cl, offset, mode)))
win = 1;
}
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_CONSTRAINT_STR (op, c, p))
+
+ else if (constraint_satisfied_p (op, cn))
win = 1;
- else if (EXTRA_MEMORY_CONSTRAINT (c, p)
+ else if (insn_extra_memory_constraint (cn)
/* Every memory operand can be reloaded to fit. */
&& ((strict < 0 && MEM_P (op))
/* Before reload, accept what reload can turn
@@ -2874,7 +2894,7 @@ constrain_operands (int strict)
|| (reload_in_progress && REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)))
win = 1;
- else if (EXTRA_ADDRESS_CONSTRAINT (c, p)
+ else if (insn_extra_address_constraint (cn)
/* Every address operand can be reloaded to fit. */
&& strict < 0)
win = 1;
@@ -2885,10 +2905,9 @@ constrain_operands (int strict)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (op)] < 0
&& reg_equiv_mem (REGNO (op)) != 0
- && EXTRA_CONSTRAINT_STR
- (reg_equiv_mem (REGNO (op)), c, p))
+ && constraint_satisfied_p
+ (reg_equiv_mem (REGNO (op)), cn))
win = 1;
-#endif
break;
}
}
@@ -3283,7 +3302,7 @@ peep2_find_free_register (int from, int
}
cl = (class_str[0] == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
+ : reg_class_for_constraint (lookup_constraint (class_str)));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
Index: gcc/reload.c
===================================================================
--- gcc/reload.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/reload.c 2014-06-05 21:45:00.214282803 +0100
@@ -401,8 +401,8 @@ push_secondary_reload (int in_p, rtx x,
scratch_constraint++;
letter = *scratch_constraint;
scratch_class = (letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
- scratch_constraint));
+ : (reg_class_for_constraint
+ (lookup_constraint (scratch_constraint))));
rclass = scratch_class;
mode = insn_data[(int) icode].operand[2].mode;
@@ -560,8 +560,7 @@ scratch_reload_class (enum insn_code ico
scratch_letter = *scratch_constraint;
if (scratch_letter == 'r')
return GENERAL_REGS;
- rclass = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
- scratch_constraint);
+ rclass = reg_class_for_constraint (lookup_constraint (scratch_constraint));
gcc_assert (rclass != NO_REGS);
return rclass;
}
@@ -2852,7 +2851,8 @@ find_reloads (rtx insn, int replace, int
/* Ignore things like match_operator operands. */
;
else if (constraints[i][0] == 'p'
- || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
+ || (insn_extra_address_constraint
+ (lookup_constraint (constraints[i]))))
{
address_operand_reloaded[i]
= find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
@@ -3094,6 +3094,8 @@ find_reloads (rtx insn, int replace, int
operand. */
int constmemok = 0;
int earlyclobber = 0;
+ enum constraint_num cn;
+ enum reg_class cl;
/* If the predicate accepts a unary operator, it means that
we need to reload the operand, but do not do this for
@@ -3489,71 +3491,74 @@ find_reloads (rtx insn, int replace, int
/* Drop through into 'r' case. */
case 'r':
- this_alternative[i]
- = reg_class_subunion[this_alternative[i]][(int) 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 (force_reload)
- break;
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
- win = 1;
- /* If the address was already reloaded,
- we win as well. */
- else if (MEM_P (operand)
- && address_reloaded[i] == 1)
- 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
- && EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p))
- || (reg_equiv_address (REGNO (operand)) != 0)))
- win = 1;
-
- /* If we didn't already win, we can reload
- constants via force_const_mem, and other
- MEMs by reloading the address like for 'o'. */
- if (CONST_POOL_OK_P (operand_mode[i], operand)
- || MEM_P (operand))
- badop = 0;
- constmemok = 1;
- offmemok = 1;
- break;
- }
- if (EXTRA_ADDRESS_CONSTRAINT (c, p))
- {
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
- win = 1;
+ case CT_REGISTER:
+ cl = reg_class_for_constraint (cn);
+ if (cl != NO_REGS)
+ goto reg;
+ break;
- /* If we didn't already win, we can reload
- the address into a base register. */
- this_alternative[i]
- = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
- ADDRESS, SCRATCH);
- badop = 0;
- break;
- }
+ case CT_MEMORY:
+ if (force_reload)
+ break;
+ if (constraint_satisfied_p (operand, cn))
+ win = 1;
+ /* If the address was already reloaded,
+ we win as well. */
+ else if (MEM_P (operand) && address_reloaded[i] == 1)
+ 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)))
+ || (reg_equiv_address (REGNO (operand))
+ != 0)))
+ win = 1;
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
+ /* If we didn't already win, we can reload
+ constants via force_const_mem, and other
+ MEMs by reloading the address like for 'o'. */
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
+ || MEM_P (operand))
+ badop = 0;
+ constmemok = 1;
+ offmemok = 1;
+ break;
+
+ case CT_ADDRESS:
+ if (constraint_satisfied_p (operand, cn))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ the address into a base register. */
+ this_alternative[i]
+ = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH);
+ badop = 0;
+ break;
+
+ case CT_FIXED_FORM:
+ if (constraint_satisfied_p (operand, cn))
win = 1;
-#endif
break;
}
+ break;
- this_alternative[i]
- = (reg_class_subunion
- [this_alternative[i]]
- [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
reg:
+ this_alternative[i]
+ = reg_class_subunion[this_alternative[i]][cl];
if (GET_MODE (operand) == BLKmode)
break;
winreg = 1;
@@ -4687,11 +4692,10 @@ alternative_allows_const_pool_ref (rtx m
{
if (c == TARGET_MEM_CONSTRAINT || c == 'o')
return true;
-#ifdef EXTRA_CONSTRAINT_STR
- if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
- && (mem == NULL || EXTRA_CONSTRAINT_STR (mem, c, constraint)))
+ enum constraint_num cn = lookup_constraint (constraint);
+ if (insn_extra_memory_constraint (cn)
+ && (mem == NULL || constraint_satisfied_p (mem, cn)))
return true;
-#endif
}
return false;
}
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/reload1.c 2014-06-05 21:45:00.217282830 +0100
@@ -1437,13 +1437,15 @@ maybe_fix_stack_asms (void)
break;
default:
- if (EXTRA_ADDRESS_CONSTRAINT (c, p))
+ enum constraint_num cn = lookup_constraint (p);
+ if (insn_extra_address_constraint (cn))
cls = (int) reg_class_subunion[cls]
[(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH)];
else
cls = (int) reg_class_subunion[cls]
- [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
+ [reg_class_for_constraint (cn)];
+ break;
}
p += CONSTRAINT_LEN (c, p);
}
Index: gcc/stmt.c
===================================================================
--- gcc/stmt.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/stmt.c 2014-06-05 21:45:00.210282768 +0100
@@ -322,12 +322,11 @@ parse_output_constraint (const char **co
default:
if (!ISALPHA (*p))
break;
- if (REG_CLASS_FROM_CONSTRAINT (*p, p) != NO_REGS)
+ enum constraint_num cn = lookup_constraint (p);
+ if (reg_class_for_constraint (cn) != NO_REGS
+ || insn_extra_address_constraint (cn))
*allows_reg = true;
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_ADDRESS_CONSTRAINT (*p, p))
- *allows_reg = true;
- else if (EXTRA_MEMORY_CONSTRAINT (*p, p))
+ else if (insn_extra_memory_constraint (cn))
*allows_mem = true;
else
{
@@ -337,7 +336,6 @@ parse_output_constraint (const char **co
*allows_reg = true;
*allows_mem = true;
}
-#endif
break;
}
@@ -454,13 +452,11 @@ parse_input_constraint (const char **con
error ("invalid punctuation %qc in constraint", constraint[j]);
return false;
}
- if (REG_CLASS_FROM_CONSTRAINT (constraint[j], constraint + j)
- != NO_REGS)
- *allows_reg = true;
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j], constraint + j))
+ enum constraint_num cn = lookup_constraint (constraint + j);
+ if (reg_class_for_constraint (cn) != NO_REGS
+ || insn_extra_address_constraint (cn))
*allows_reg = true;
- else if (EXTRA_MEMORY_CONSTRAINT (constraint[j], constraint + j))
+ else if (insn_extra_memory_constraint (cn))
*allows_mem = true;
else
{
@@ -470,7 +466,6 @@ parse_input_constraint (const char **con
*allows_reg = true;
*allows_mem = true;
}
-#endif
break;
}
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/targhooks.c 2014-06-05 21:45:00.217282830 +0100
@@ -936,8 +936,8 @@ default_secondary_reload (bool in_p ATTR
insn_letter = *insn_constraint;
insn_class
= (insn_letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
- insn_constraint));
+ : (reg_class_for_constraint
+ (lookup_constraint (insn_constraint))));
gcc_assert (insn_class != NO_REGS);
}
@@ -954,8 +954,8 @@ default_secondary_reload (bool in_p ATTR
scratch_letter = *scratch_constraint;
scratch_class
= (scratch_letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
- scratch_constraint));
+ : (reg_class_for_constraint
+ (lookup_constraint (scratch_constraint))));
if (reg_class_subset_p (reload_class, insn_class))
{
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c 2014-06-05 21:06:52.721540056 +0100
+++ gcc/config/m32c/m32c.c 2014-06-05 21:45:00.219282847 +0100
@@ -854,7 +854,7 @@ #define IS_PSEUDO(rtx,strict) (!strict &
#define A0_OR_PSEUDO(x) (IS_REG(x, A0_REGNO) || REGNO (x) >= FIRST_PSEUDO_REGISTER)
-/* Implements EXTRA_CONSTRAINT_STR (see next function too). 'S' is
+/* Implements matching for constraints (see next function too). 'S' is
for memory constraints, plus "Rpa" for PARALLEL rtx's we use for
call return values. */
bool
Index: gcc/config/sparc/constraints.md
===================================================================
--- gcc/config/sparc/constraints.md 2014-06-05 21:06:52.721540056 +0100
+++ gcc/config/sparc/constraints.md 2014-06-05 21:45:00.220282856 +0100
@@ -171,7 +171,7 @@ (define_memory_constraint "T"
;; define_register_constraint would. This currently means that we cannot
;; use LRA on Sparc, since the constraint processing of LRA really depends
;; upon whether an extra constraint is for registers or not. It uses
-;; REG_CLASS_FROM_CONSTRAINT, and checks it against NO_REGS.
+;; reg_class_for_constraint, and checks it against NO_REGS.
(define_constraint "U"
"Pseudo-register or hard even-numbered integer register"
(and (match_test "TARGET_ARCH32")
next prev parent reply other threads:[~2014-06-05 21:32 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-05 21:25 [PATCH 0/8] Constraint matching TLC Richard Sandiford
2014-06-05 21:27 ` [PATCH 1/8] Faster checks for constraint types Richard Sandiford
2014-06-10 18:42 ` Jeff Law
2014-06-05 21:29 ` [PATCH 2/8] Speed up lookup_constraint Richard Sandiford
2014-06-10 18:41 ` Jeff Law
2014-06-05 21:31 ` [PATCH 3/8] Speed up constraint_satisfied_p Richard Sandiford
2014-06-10 18:42 ` Jeff Law
2014-06-05 21:32 ` Richard Sandiford [this message]
2014-06-10 20:53 ` [PATCH 4/8] Remove old macros and make lookup_constraint explicit Jeff Law
2014-06-05 21:33 ` [PATCH 5/8] Remove unused operand_alternative fields Richard Sandiford
2014-06-10 18:43 ` Jeff Law
2014-06-05 21:38 ` [PATCH 6/8] Treat 'I'-'P' as separate subtype Richard Sandiford
2014-06-10 18:48 ` Jeff Law
2014-06-05 21:41 ` [PATCH 7/8] Remove 'I'-'P' and 'G'/'H' cases Richard Sandiford
2014-06-10 18:50 ` Jeff Law
2014-06-05 21:43 ` [PATCH 8/8] Add a common .md file and define standard constraints there Richard Sandiford
2014-06-10 20:59 ` Jeff Law
2014-06-11 17:01 ` Richard Sandiford
2014-06-13 20:06 ` Steve Ellcey
2014-06-14 7:49 ` Richard Sandiford
2014-06-16 14:48 ` Steve Ellcey
2014-06-12 19:24 ` Segher Boessenkool
2014-06-12 19:39 ` Paul_Koning
2014-06-12 21:19 ` Segher Boessenkool
2014-06-14 9:58 ` Richard Sandiford
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87bnu79h58.fsf@talisman.default \
--to=rdsandiford@googlemail.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).