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