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
18namespace llvm {
19class GIMatchDag;
20
21/// This class manages lifetimes for data associated with the GIMatchDag object.
22class GIMatchDagContext {
23  GIMatchDagOperandListContext OperandListCtx;
24
25public:
26  const GIMatchDagOperandList &makeEmptyOperandList() {
27    return OperandListCtx.makeEmptyOperandList();
28  }
29
30  const GIMatchDagOperandList &makeOperandList(const CodeGenInstruction &I) {
31    return OperandListCtx.makeOperandList(I);
32  }
33
34  const GIMatchDagOperandList &makeMIPredicateOperandList() {
35    return OperandListCtx.makeMIPredicateOperandList();
36  }
37
38
39  const GIMatchDagOperandList &makeTwoMOPredicateOperandList() {
40    return OperandListCtx.makeTwoMOPredicateOperandList();
41  }
42
43  void print(raw_ostream &OS) const {
44    OperandListCtx.print(OS);
45  }
46
47#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
48  LLVM_DUMP_METHOD void dump() const { print(errs()); }
49#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
50};
51
52class GIMatchDag {
53public:
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
75protected:
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
86public:
87  GIMatchDag(GIMatchDagContext &Ctx)
88      : Ctx(Ctx), InstrNodes(), PredicateNodes(), Edges(),
89        PredicateDependencies() {}
90  GIMatchDag(const GIMatchDag &) = delete;
91
92  GIMatchDagContext &getContext() const { return Ctx; }
93  edge_iterator edges_begin() {
94    return raw_pointer_iterator<EdgesVec::iterator>(Edges.begin());
95  }
96  edge_iterator edges_end() {
97    return raw_pointer_iterator<EdgesVec::iterator>(Edges.end());
98  }
99  const_edge_iterator edges_begin() const {
100    return raw_pointer_iterator<EdgesVec::const_iterator>(Edges.begin());
101  }
102  const_edge_iterator edges_end() const {
103    return raw_pointer_iterator<EdgesVec::const_iterator>(Edges.end());
104  }
105  iterator_range<edge_iterator> edges() {
106    return make_range(edges_begin(), edges_end());
107  }
108  iterator_range<const_edge_iterator> edges() const {
109    return make_range(edges_begin(), edges_end());
110  }
111  iterator_range<std::vector<GIMatchDagInstr *>::iterator> roots() {
112    return make_range(MatchRoots.begin(), MatchRoots.end());
113  }
114  iterator_range<std::vector<GIMatchDagInstr *>::const_iterator> roots() const {
115    return make_range(MatchRoots.begin(), MatchRoots.end());
116  }
117
118  instr_node_iterator instr_nodes_begin() {
119    return raw_pointer_iterator<InstrNodesVec::iterator>(InstrNodes.begin());
120  }
121  instr_node_iterator instr_nodes_end() {
122    return raw_pointer_iterator<InstrNodesVec::iterator>(InstrNodes.end());
123  }
124  const_instr_node_iterator instr_nodes_begin() const {
125    return raw_pointer_iterator<InstrNodesVec::const_iterator>(
126        InstrNodes.begin());
127  }
128  const_instr_node_iterator instr_nodes_end() const {
129    return raw_pointer_iterator<InstrNodesVec::const_iterator>(
130        InstrNodes.end());
131  }
132  iterator_range<instr_node_iterator> instr_nodes() {
133    return make_range(instr_nodes_begin(), instr_nodes_end());
134  }
135  iterator_range<const_instr_node_iterator> instr_nodes() const {
136    return make_range(instr_nodes_begin(), instr_nodes_end());
137  }
138  predicate_edge_iterator predicate_edges_begin() {
139    return raw_pointer_iterator<PredicateDependencyEdgesVec::iterator>(
140        PredicateDependencies.begin());
141  }
142  predicate_edge_iterator predicate_edges_end() {
143    return raw_pointer_iterator<PredicateDependencyEdgesVec::iterator>(
144        PredicateDependencies.end());
145  }
146  const_predicate_edge_iterator predicate_edges_begin() const {
147    return raw_pointer_iterator<PredicateDependencyEdgesVec::const_iterator>(
148        PredicateDependencies.begin());
149  }
150  const_predicate_edge_iterator predicate_edges_end() const {
151    return raw_pointer_iterator<PredicateDependencyEdgesVec::const_iterator>(
152        PredicateDependencies.end());
153  }
154  iterator_range<predicate_edge_iterator> predicate_edges() {
155    return make_range(predicate_edges_begin(), predicate_edges_end());
156  }
157  iterator_range<const_predicate_edge_iterator> predicate_edges() const {
158    return make_range(predicate_edges_begin(), predicate_edges_end());
159  }
160  predicate_iterator predicates_begin() {
161    return raw_pointer_iterator<PredicateNodesVec::iterator>(
162        PredicateNodes.begin());
163  }
164  predicate_iterator predicates_end() {
165    return raw_pointer_iterator<PredicateNodesVec::iterator>(
166        PredicateNodes.end());
167  }
168  const_predicate_iterator predicates_begin() const {
169    return raw_pointer_iterator<PredicateNodesVec::const_iterator>(
170        PredicateNodes.begin());
171  }
172  const_predicate_iterator predicates_end() const {
173    return raw_pointer_iterator<PredicateNodesVec::const_iterator>(
174        PredicateNodes.end());
175  }
176  iterator_range<predicate_iterator> predicates() {
177    return make_range(predicates_begin(), predicates_end());
178  }
179  iterator_range<const_predicate_iterator> predicates() const {
180    return make_range(predicates_begin(), predicates_end());
181  }
182
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>
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
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>
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
215  size_t getInstrNodeIdx(instr_node_iterator I) {
216    return std::distance(instr_nodes_begin(), I);
217  }
218  size_t getInstrNodeIdx(const_instr_node_iterator I) const {
219    return std::distance(instr_nodes_begin(), I);
220  }
221  size_t getNumInstrNodes() const { return InstrNodes.size(); }
222  size_t getNumEdges() const { return Edges.size(); }
223  size_t getNumPredicates() const { return PredicateNodes.size(); }
224
225  void setHasPostMatchPredicate(bool V) { HasPostMatchPredicate = V; }
226  bool hasPostMatchPredicate() const { return HasPostMatchPredicate; }
227
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)
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
239raw_ostream &operator<<(raw_ostream &OS, const GIMatchDag &G);
240
241} // end namespace llvm
242
243#endif // ifndef LLVM_UTILS_TABLEGEN_GIMATCHDAG_H
244