From: Robin Dapp <[email protected]>
This patch adds dependent-filter handling to recog.
When verifying the constraints of an instruction, just after register
filters are checked, it calls eval_dependent_filter for the operand and
its referenced operand.
gcc/ChangeLog:
* recog.cc (preprocess_constraints): Initialize dependent
filter.
(test_dependent_filter): New function wrapping
eval_dependent_filter.
(constrain_operands): Test dependent filter in strict mode.
* recog.h (struct operand_alternative): Declare
dependent_filters.
(alternative_dependent_filters): New function.
---
gcc/recog.cc | 33 ++++++++++++++++++++++++++++++++-
gcc/recog.h | 16 ++++++++++++++++
2 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/gcc/recog.cc b/gcc/recog.cc
index 4cae276f1f7..12874505518 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -2948,6 +2948,7 @@ preprocess_constraints (int n_operands, int
n_alternatives,
{
op_alt[i].cl = NO_REGS;
op_alt[i].register_filters = 0;
+ op_alt[i].dependent_filters = 0;
op_alt[i].constraint = p;
op_alt[i].matches = -1;
op_alt[i].matched = -1;
@@ -3015,6 +3016,9 @@ preprocess_constraints (int n_operands, int
n_alternatives,
auto filter_id = get_register_filter_id (cn);
if (filter_id >= 0)
op_alt[i].register_filters |= 1U << filter_id;
+ auto dep_filter_id = get_dependent_filter_id (cn);
+ if (dep_filter_id >= 0)
+ op_alt[i].dependent_filters |= 1U << dep_filter_id;
}
break;
@@ -3138,6 +3142,30 @@ struct funny_match
int this_op, other;
};
+/* For a register constraint CN with a dependent filter (i.e. a
+ dependent/dynamic filter), return true if the filter allows
+ REGNO (OP) + offset given the current ref-operand contents in
+ recog_data or false if it doesn't.
+ If the filter cannot be evaluated, for example when no hard reg
+ has been chosen yet, return true. */
+
+static bool
+test_dependent_filter (constraint_num cn, rtx op, int offset,
+ machine_mode mode)
+{
+ int id = get_dependent_filter_id (cn);
+ if (id < 0 || !REG_P (op))
+ return true;
+ int ref_opno = get_dependent_filter_ref (id);
+ if (ref_opno < 0 || ref_opno >= recog_data.n_operands)
+ return true;
+ rtx ref_op = recog_data.operand[ref_opno];
+ if (!REG_P (ref_op))
+ return true;
+ return eval_dependent_filter (id, REGNO (op) + offset, mode,
+ REGNO (ref_op), GET_MODE (ref_op));
+}
+
bool
constrain_operands (int strict, alternative_mask alternatives)
{
@@ -3339,7 +3367,10 @@ constrain_operands (int strict, alternative_mask
alternatives)
&& reg_fits_class_p (op, cl, offset, mode)
&& (!filter
|| TEST_HARD_REG_BIT (*filter,
- REGNO (op) + offset))))
+ REGNO (op) + offset))
+ && (strict <= 0
+ || test_dependent_filter (cn, op, offset,
+ mode))))
win = true;
}
diff --git a/gcc/recog.h b/gcc/recog.h
index 04cc1f192aa..835fc64f153 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -68,6 +68,10 @@ struct operand_alternative
to test whether REGNO is a valid start register for the operand. */
unsigned int register_filters : MAX (NUM_REGISTER_FILTERS, 1);
+ /* Bit ID is set if the constraint string includes a dependent
+ register constraint with dependent-filter id ID. */
+ unsigned int dependent_filters : MAX (NUM_DEPENDENT_FILTERS, 1);
+
/* Nonzero if '&' was found in the constraint string. */
unsigned int earlyclobber : 1;
/* Nonzero if TARGET_MEM_CONSTRAINT was found in the constraint
@@ -99,6 +103,18 @@ alternative_register_filters (const operand_alternative
*alt, int i)
? alt[alt[i].matches].register_filters
: alt[i].register_filters);
}
+
+/* Return the mask of dynamic register filters that should be applied to
+ operand I of alternative ALT, taking matching constraints into
+ account. */
+
+inline unsigned int
+alternative_dependent_filters (const operand_alternative *alt, int i)
+{
+ return (alt[i].matches >= 0
+ ? alt[alt[i].matches].dependent_filters
+ : alt[i].dependent_filters);
+}
#endif
/* A class for substituting one rtx for another within an instruction,
--
2.53.0