[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