xref: /llvm-project/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h (revision 2435dcd83a32c63aef91c82cb19b08604ba96b64)
1 //===- VPlanPatternMatch.h - Match on VPValues and recipes ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides a simple and efficient mechanism for performing general
10 // tree-based pattern matches on the VPlan values and recipes, based on
11 // LLVM's IR pattern matchers.
12 //
13 // Currently it provides generic matchers for unary and binary VPInstructions,
14 // and specialized matchers like m_Not, m_ActiveLaneMask, m_BranchOnCond,
15 // m_BranchOnCount to match specific VPInstructions.
16 // TODO: Add missing matchers for additional opcodes and recipes as needed.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #ifndef LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H
21 #define LLVM_TRANSFORM_VECTORIZE_VPLANPATTERNMATCH_H
22 
23 #include "VPlan.h"
24 
25 namespace llvm {
26 namespace VPlanPatternMatch {
27 
28 template <typename Val, typename Pattern> bool match(Val *V, const Pattern &P) {
29   return const_cast<Pattern &>(P).match(V);
30 }
31 
32 template <typename Class> struct class_match {
33   template <typename ITy> bool match(ITy *V) { return isa<Class>(V); }
34 };
35 
36 /// Match an arbitrary VPValue and ignore it.
37 inline class_match<VPValue> m_VPValue() { return class_match<VPValue>(); }
38 
39 template <typename Class> struct bind_ty {
40   Class *&VR;
41 
42   bind_ty(Class *&V) : VR(V) {}
43 
44   template <typename ITy> bool match(ITy *V) {
45     if (auto *CV = dyn_cast<Class>(V)) {
46       VR = CV;
47       return true;
48     }
49     return false;
50   }
51 };
52 
53 /// Match a VPValue, capturing it if we match.
54 inline bind_ty<VPValue> m_VPValue(VPValue *&V) { return V; }
55 
56 template <typename Op0_t, unsigned Opcode> struct UnaryVPInstruction_match {
57   Op0_t Op0;
58 
59   UnaryVPInstruction_match(Op0_t Op0) : Op0(Op0) {}
60 
61   bool match(const VPValue *V) {
62     auto *DefR = V->getDefiningRecipe();
63     return DefR && match(DefR);
64   }
65 
66   bool match(const VPRecipeBase *R) {
67     auto *DefR = dyn_cast<VPInstruction>(R);
68     if (!DefR || DefR->getOpcode() != Opcode)
69       return false;
70     assert(DefR->getNumOperands() == 1 &&
71            "recipe with matched opcode does not have 1 operands");
72     return Op0.match(DefR->getOperand(0));
73   }
74 };
75 
76 template <typename Op0_t, typename Op1_t, unsigned Opcode>
77 struct BinaryVPInstruction_match {
78   Op0_t Op0;
79   Op1_t Op1;
80 
81   BinaryVPInstruction_match(Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {}
82 
83   bool match(const VPValue *V) {
84     auto *DefR = V->getDefiningRecipe();
85     return DefR && match(DefR);
86   }
87 
88   bool match(const VPRecipeBase *R) {
89     auto *DefR = dyn_cast<VPInstruction>(R);
90     if (!DefR || DefR->getOpcode() != Opcode)
91       return false;
92     assert(DefR->getNumOperands() == 2 &&
93            "recipe with matched opcode does not have 2 operands");
94     return Op0.match(DefR->getOperand(0)) && Op1.match(DefR->getOperand(1));
95   }
96 };
97 
98 template <unsigned Opcode, typename Op0_t>
99 inline UnaryVPInstruction_match<Op0_t, Opcode>
100 m_VPInstruction(const Op0_t &Op0) {
101   return UnaryVPInstruction_match<Op0_t, Opcode>(Op0);
102 }
103 
104 template <unsigned Opcode, typename Op0_t, typename Op1_t>
105 inline BinaryVPInstruction_match<Op0_t, Op1_t, Opcode>
106 m_VPInstruction(const Op0_t &Op0, const Op1_t &Op1) {
107   return BinaryVPInstruction_match<Op0_t, Op1_t, Opcode>(Op0, Op1);
108 }
109 
110 template <typename Op0_t>
111 inline UnaryVPInstruction_match<Op0_t, VPInstruction::Not>
112 m_Not(const Op0_t &Op0) {
113   return m_VPInstruction<VPInstruction::Not>(Op0);
114 }
115 
116 template <typename Op0_t>
117 inline UnaryVPInstruction_match<Op0_t, VPInstruction::BranchOnCond>
118 m_BranchOnCond(const Op0_t &Op0) {
119   return m_VPInstruction<VPInstruction::BranchOnCond>(Op0);
120 }
121 
122 template <typename Op0_t, typename Op1_t>
123 inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::ActiveLaneMask>
124 m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1) {
125   return m_VPInstruction<VPInstruction::ActiveLaneMask>(Op0, Op1);
126 }
127 
128 template <typename Op0_t, typename Op1_t>
129 inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::BranchOnCount>
130 m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) {
131   return m_VPInstruction<VPInstruction::BranchOnCount>(Op0, Op1);
132 }
133 } // namespace VPlanPatternMatch
134 } // namespace llvm
135 
136 #endif
137