https://gcc.gnu.org/g:541e9dd84889e5da19b6394d9d2e38cc13f9ae4a
commit r17-1780-g541e9dd84889e5da19b6394d9d2e38cc13f9ae4a Author: Robin Dapp <[email protected]> Date: Wed Apr 29 09:53:46 2026 +0200 recog: Handle dependent filters. 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. Diff: --- gcc/recog.cc | 32 +++++++++++++++++++++++++++++++- gcc/recog.h | 16 ++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/gcc/recog.cc b/gcc/recog.cc index a45a37db6bb9..f9cff68e4573 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,29 @@ struct funny_match int this_op, other; }; +/* For a register constraint CN with a dependent filter, return true if + the respective filter allows REGNO (OP) + OFFSET given the ref-operand + in recog_data.operand 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 +3366,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 1f22dbf4d9b8..409314543f79 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,
