1 //===- GIMatchDag.h - Represent a DAG to be matched -----------------------===//
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 #ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAG_H
10 #define LLVM_UTILS_TABLEGEN_GIMATCHDAG_H
11 
12 #include "GIMatchDagEdge.h"
13 #include "GIMatchDagInstr.h"
14 #include "GIMatchDagOperands.h"
15 #include "GIMatchDagPredicate.h"
16 #include "GIMatchDagPredicateDependencyEdge.h"
17 
18 namespace llvm {
19 class GIMatchDag;
20 
21 /// This class manages lifetimes for data associated with the GIMatchDag object.
22 class GIMatchDagContext {
23   GIMatchDagOperandListContext OperandListCtx;
24 
25 public:
makeEmptyOperandList()26   const GIMatchDagOperandList &makeEmptyOperandList() {
27     return OperandListCtx.makeEmptyOperandList();
28   }
29 
makeOperandList(const CodeGenInstruction & I)30   const GIMatchDagOperandList &makeOperandList(const CodeGenInstruction &I) {
31     return OperandListCtx.makeOperandList(I);
32   }
33 
makeMIPredicateOperandList()34   const GIMatchDagOperandList &makeMIPredicateOperandList() {
35     return OperandListCtx.makeMIPredicateOperandList();
36   }
37 
38 
makeTwoMOPredicateOperandList()39   const GIMatchDagOperandList &makeTwoMOPredicateOperandList() {
40     return OperandListCtx.makeTwoMOPredicateOperandList();
41   }
42 
print(raw_ostream & OS)43   void print(raw_ostream &OS) const {
44     OperandListCtx.print(OS);
45   }
46 
47 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()48   LLVM_DUMP_METHOD void dump() const { print(errs()); }
49 #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
50 };
51 
52 class GIMatchDag {
53 public:
54   using InstrNodesVec = std::vector<std::unique_ptr<GIMatchDagInstr>>;
55   using instr_node_iterator = raw_pointer_iterator<InstrNodesVec::iterator>;
56   using const_instr_node_iterator =
57       raw_pointer_iterator<InstrNodesVec::const_iterator>;
58 
59   using EdgesVec = std::vector<std::unique_ptr<GIMatchDagEdge>>;
60   using edge_iterator = raw_pointer_iterator<EdgesVec::iterator>;
61   using const_edge_iterator = raw_pointer_iterator<EdgesVec::const_iterator>;
62 
63   using PredicateNodesVec = std::vector<std::unique_ptr<GIMatchDagPredicate>>;
64   using predicate_iterator = raw_pointer_iterator<PredicateNodesVec::iterator>;
65   using const_predicate_iterator =
66       raw_pointer_iterator<PredicateNodesVec::const_iterator>;
67 
68   using PredicateDependencyEdgesVec =
69       std::vector<std::unique_ptr<GIMatchDagPredicateDependencyEdge>>;
70   using predicate_edge_iterator =
71       raw_pointer_iterator<PredicateDependencyEdgesVec::iterator>;
72   using const_predicate_edge_iterator =
73       raw_pointer_iterator<PredicateDependencyEdgesVec::const_iterator>;
74 
75 protected:
76   GIMatchDagContext &Ctx;
77   InstrNodesVec InstrNodes;
78   PredicateNodesVec PredicateNodes;
79   EdgesVec Edges;
80   PredicateDependencyEdgesVec PredicateDependencies;
81   std::vector<GIMatchDagInstr *> MatchRoots;
82   // FIXME: This is a temporary measure while we still accept arbitrary code
83   //        blocks to fix up the matcher while it's being developed.
84   bool HasPostMatchPredicate = false;
85 
86 public:
GIMatchDag(GIMatchDagContext & Ctx)87   GIMatchDag(GIMatchDagContext &Ctx)
88       : Ctx(Ctx), InstrNodes(), PredicateNodes(), Edges(),
89         PredicateDependencies() {}
90   GIMatchDag(const GIMatchDag &) = delete;
91 
getContext()92   GIMatchDagContext &getContext() const { return Ctx; }
edges_begin()93   edge_iterator edges_begin() {
94     return raw_pointer_iterator<EdgesVec::iterator>(Edges.begin());
95   }
edges_end()96   edge_iterator edges_end() {
97     return raw_pointer_iterator<EdgesVec::iterator>(Edges.end());
98   }
edges_begin()99   const_edge_iterator edges_begin() const {
100     return raw_pointer_iterator<EdgesVec::const_iterator>(Edges.begin());
101   }
edges_end()102   const_edge_iterator edges_end() const {
103     return raw_pointer_iterator<EdgesVec::const_iterator>(Edges.end());
104   }
edges()105   iterator_range<edge_iterator> edges() {
106     return make_range(edges_begin(), edges_end());
107   }
edges()108   iterator_range<const_edge_iterator> edges() const {
109     return make_range(edges_begin(), edges_end());
110   }
roots()111   iterator_range<std::vector<GIMatchDagInstr *>::iterator> roots() {
112     return make_range(MatchRoots.begin(), MatchRoots.end());
113   }
roots()114   iterator_range<std::vector<GIMatchDagInstr *>::const_iterator> roots() const {
115     return make_range(MatchRoots.begin(), MatchRoots.end());
116   }
117 
instr_nodes_begin()118   instr_node_iterator instr_nodes_begin() {
119     return raw_pointer_iterator<InstrNodesVec::iterator>(InstrNodes.begin());
120   }
instr_nodes_end()121   instr_node_iterator instr_nodes_end() {
122     return raw_pointer_iterator<InstrNodesVec::iterator>(InstrNodes.end());
123   }
instr_nodes_begin()124   const_instr_node_iterator instr_nodes_begin() const {
125     return raw_pointer_iterator<InstrNodesVec::const_iterator>(
126         InstrNodes.begin());
127   }
instr_nodes_end()128   const_instr_node_iterator instr_nodes_end() const {
129     return raw_pointer_iterator<InstrNodesVec::const_iterator>(
130         InstrNodes.end());
131   }
instr_nodes()132   iterator_range<instr_node_iterator> instr_nodes() {
133     return make_range(instr_nodes_begin(), instr_nodes_end());
134   }
instr_nodes()135   iterator_range<const_instr_node_iterator> instr_nodes() const {
136     return make_range(instr_nodes_begin(), instr_nodes_end());
137   }
predicate_edges_begin()138   predicate_edge_iterator predicate_edges_begin() {
139     return raw_pointer_iterator<PredicateDependencyEdgesVec::iterator>(
140         PredicateDependencies.begin());
141   }
predicate_edges_end()142   predicate_edge_iterator predicate_edges_end() {
143     return raw_pointer_iterator<PredicateDependencyEdgesVec::iterator>(
144         PredicateDependencies.end());
145   }
predicate_edges_begin()146   const_predicate_edge_iterator predicate_edges_begin() const {
147     return raw_pointer_iterator<PredicateDependencyEdgesVec::const_iterator>(
148         PredicateDependencies.begin());
149   }
predicate_edges_end()150   const_predicate_edge_iterator predicate_edges_end() const {
151     return raw_pointer_iterator<PredicateDependencyEdgesVec::const_iterator>(
152         PredicateDependencies.end());
153   }
predicate_edges()154   iterator_range<predicate_edge_iterator> predicate_edges() {
155     return make_range(predicate_edges_begin(), predicate_edges_end());
156   }
predicate_edges()157   iterator_range<const_predicate_edge_iterator> predicate_edges() const {
158     return make_range(predicate_edges_begin(), predicate_edges_end());
159   }
predicates_begin()160   predicate_iterator predicates_begin() {
161     return raw_pointer_iterator<PredicateNodesVec::iterator>(
162         PredicateNodes.begin());
163   }
predicates_end()164   predicate_iterator predicates_end() {
165     return raw_pointer_iterator<PredicateNodesVec::iterator>(
166         PredicateNodes.end());
167   }
predicates_begin()168   const_predicate_iterator predicates_begin() const {
169     return raw_pointer_iterator<PredicateNodesVec::const_iterator>(
170         PredicateNodes.begin());
171   }
predicates_end()172   const_predicate_iterator predicates_end() const {
173     return raw_pointer_iterator<PredicateNodesVec::const_iterator>(
174         PredicateNodes.end());
175   }
predicates()176   iterator_range<predicate_iterator> predicates() {
177     return make_range(predicates_begin(), predicates_end());
178   }
predicates()179   iterator_range<const_predicate_iterator> predicates() const {
180     return make_range(predicates_begin(), predicates_end());
181   }
182 
addInstrNode(Args &&...args)183   template <class... Args> GIMatchDagInstr *addInstrNode(Args &&... args) {
184     auto Obj =
185         std::make_unique<GIMatchDagInstr>(*this, std::forward<Args>(args)...);
186     auto ObjRaw = Obj.get();
187     InstrNodes.push_back(std::move(Obj));
188     return ObjRaw;
189   }
190 
191   template <class T, class... Args>
addPredicateNode(Args &&...args)192   T *addPredicateNode(Args &&... args) {
193     auto Obj = std::make_unique<T>(getContext(), std::forward<Args>(args)...);
194     auto ObjRaw = Obj.get();
195     PredicateNodes.push_back(std::move(Obj));
196     return ObjRaw;
197   }
198 
addEdge(Args &&...args)199   template <class... Args> GIMatchDagEdge *addEdge(Args &&... args) {
200     auto Obj = std::make_unique<GIMatchDagEdge>(std::forward<Args>(args)...);
201     auto ObjRaw = Obj.get();
202     Edges.push_back(std::move(Obj));
203     return ObjRaw;
204   }
205 
206   template <class... Args>
addPredicateDependency(Args &&...args)207   GIMatchDagPredicateDependencyEdge *addPredicateDependency(Args &&... args) {
208     auto Obj = std::make_unique<GIMatchDagPredicateDependencyEdge>(
209         std::forward<Args>(args)...);
210     auto ObjRaw = Obj.get();
211     PredicateDependencies.push_back(std::move(Obj));
212     return ObjRaw;
213   }
214 
getInstrNodeIdx(instr_node_iterator I)215   size_t getInstrNodeIdx(instr_node_iterator I) {
216     return std::distance(instr_nodes_begin(), I);
217   }
getInstrNodeIdx(const_instr_node_iterator I)218   size_t getInstrNodeIdx(const_instr_node_iterator I) const {
219     return std::distance(instr_nodes_begin(), I);
220   }
getNumInstrNodes()221   size_t getNumInstrNodes() const { return InstrNodes.size(); }
getNumEdges()222   size_t getNumEdges() const { return Edges.size(); }
getNumPredicates()223   size_t getNumPredicates() const { return PredicateNodes.size(); }
224 
setHasPostMatchPredicate(bool V)225   void setHasPostMatchPredicate(bool V) { HasPostMatchPredicate = V; }
hasPostMatchPredicate()226   bool hasPostMatchPredicate() const { return HasPostMatchPredicate; }
227 
addMatchRoot(GIMatchDagInstr * N)228   void addMatchRoot(GIMatchDagInstr *N) { MatchRoots.push_back(N); }
229 
230   LLVM_DUMP_METHOD void print(raw_ostream &OS) const;
231 
232 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()233   LLVM_DUMP_METHOD void dump() const { print(errs()); }
234 #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
235 
236   void writeDOTGraph(raw_ostream &OS, StringRef ID) const;
237 };
238 
239 raw_ostream &operator<<(raw_ostream &OS, const GIMatchDag &G);
240 
241 } // end namespace llvm
242 
243 #endif // ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAG_H
244