[llvm] [SCEV] Add initial matchers for SCEV expressions. (NFC) (PR #119390)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 15 12:17:23 PST 2024


================
@@ -52,6 +52,120 @@ inline cst_pred_ty<is_all_ones> m_scev_AllOnes() {
   return cst_pred_ty<is_all_ones>();
 }
 
+template <typename Class> struct class_match {
+  template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); }
+};
+
+template <typename Class> struct bind_ty {
+  Class *&VR;
+
+  bind_ty(Class *&V) : VR(V) {}
+
+  template <typename ITy> bool match(ITy *V) const {
+    if (auto *CV = dyn_cast<Class>(V)) {
+      VR = CV;
+      return true;
+    }
+    return false;
+  }
+};
+
+/// Match a SCEV, capturing it if we match.
+inline bind_ty<const SCEV> m_SCEV(const SCEV *&V) { return V; }
+inline bind_ty<const SCEVConstant> m_SCEVConstant(const SCEVConstant *&V) {
+  return V;
+}
+inline bind_ty<const SCEVUnknown> m_SCEVUnknown(const SCEVUnknown *&V) {
+  return V;
+}
+
+/// Match a specified const SCEV *.
+struct specificscev_ty {
+  const SCEV *Expr;
+
+  specificscev_ty(const SCEV *Expr) : Expr(Expr) {}
+
+  template <typename ITy> bool match(ITy *S) { return S == Expr; }
+};
+
+/// Match if we have a specific specified SCEV.
+inline specificscev_ty m_Specific(const SCEV *S) { return S; }
+
+namespace detail {
+
+template <typename TupleTy, typename Fn, std::size_t... Is>
+bool CheckTupleElements(const TupleTy &Ops, Fn P, std::index_sequence<Is...>) {
+  return (P(std::get<Is>(Ops), Is) && ...);
+}
+
+/// Helper to check if predicate \p P holds on all tuple elements in \p Ops
+template <typename TupleTy, typename Fn>
+bool all_of_tuple_elements(const TupleTy &Ops, Fn P) {
+  return CheckTupleElements(
+      Ops, P, std::make_index_sequence<std::tuple_size<TupleTy>::value>{});
+}
+
+} // namespace detail
+
+template <typename Ops_t, typename SCEVTy> struct SCEVExpr_match {
+  Ops_t Ops;
+
+  SCEVExpr_match() : Ops() {
+    static_assert(std::tuple_size<Ops_t>::value == 0 &&
+                  "constructor can only be used with zero operands");
+  }
+  SCEVExpr_match(Ops_t Ops) : Ops(Ops) {}
+  template <typename A_t, typename B_t>
+  SCEVExpr_match(A_t A, B_t B) : Ops({A, B}) {
+    static_assert(std::tuple_size<Ops_t>::value == 2 &&
+                  "constructor can only be used for binary matcher");
+  }
+
+  bool match(const SCEV *S) const {
+    auto *Cast = dyn_cast<SCEVTy>(S);
+    if (!Cast || Cast->getNumOperands() != std::tuple_size<Ops_t>::value)
+      return false;
+    return detail::all_of_tuple_elements(Ops, [Cast](auto Op, unsigned Idx) {
+      return Op.match(Cast->getOperand(Idx));
+    });
+  }
+};
+
+template <typename Op0_t, typename Op1_t, typename SCEVTy>
+using BinarySCEVExpr_match = SCEVExpr_match<std::tuple<Op0_t, Op1_t>, SCEVTy>;
+
+template <typename Op0_t, typename Op1_t, typename SCEVTy>
+inline BinarySCEVExpr_match<Op0_t, Op1_t, SCEVTy>
+m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1) {
+  return BinarySCEVExpr_match<Op0_t, Op1_t, SCEVTy>(Op0, Op1);
+}
+
+template <typename Op0_t, typename Op1_t>
+inline BinarySCEVExpr_match<Op0_t, Op1_t, SCEVAddExpr>
+m_scev_Add(const Op0_t &Op0, const Op1_t &Op1) {
+  return BinarySCEVExpr_match<Op0_t, Op1_t, SCEVAddExpr>(Op0, Op1);
+}
+
+template <typename Op0_t, typename SCEVTy>
+using UnarySCEVExpr_match = SCEVExpr_match<std::tuple<Op0_t>, SCEVTy>;
+
+template <typename Op0_t, typename Op1_t, typename SCEVTy>
+inline UnarySCEVExpr_match<Op0_t, SCEVTy> m_scev_Unary(const Op0_t &Op0) {
----------------
nikic wrote:

Same question here.

https://github.com/llvm/llvm-project/pull/119390


More information about the llvm-commits mailing list