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

Reply via email to