1 | //===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// |
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 implements the SetTheory class that computes ordered sets of |
10 | // Records from DAG expressions. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/TableGen/SetTheory.h" |
15 | #include "llvm/ADT/ArrayRef.h" |
16 | #include "llvm/ADT/SmallVector.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/Support/Casting.h" |
19 | #include "llvm/Support/Format.h" |
20 | #include "llvm/Support/SMLoc.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | #include "llvm/TableGen/Error.h" |
23 | #include "llvm/TableGen/Record.h" |
24 | #include <algorithm> |
25 | #include <cstdint> |
26 | #include <string> |
27 | #include <utility> |
28 | |
29 | using namespace llvm; |
30 | |
31 | // Define the standard operators. |
32 | namespace { |
33 | |
34 | using RecSet = SetTheory::RecSet; |
35 | using RecVec = SetTheory::RecVec; |
36 | |
37 | // (add a, b, ...) Evaluate and union all arguments. |
38 | struct AddOp : public SetTheory::Operator { |
39 | void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, |
40 | ArrayRef<SMLoc> Loc) override { |
41 | ST.evaluate(begin: Expr->arg_begin(), end: Expr->arg_end(), Elts, Loc); |
42 | } |
43 | }; |
44 | |
45 | // (sub Add, Sub, ...) Set difference. |
46 | struct SubOp : public SetTheory::Operator { |
47 | void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, |
48 | ArrayRef<SMLoc> Loc) override { |
49 | if (Expr->arg_size() < 2) |
50 | PrintFatalError(ErrorLoc: Loc, Msg: "Set difference needs at least two arguments: " + |
51 | Expr->getAsString()); |
52 | RecSet Add, Sub; |
53 | ST.evaluate(Expr: *Expr->arg_begin(), Elts&: Add, Loc); |
54 | ST.evaluate(begin: Expr->arg_begin() + 1, end: Expr->arg_end(), Elts&: Sub, Loc); |
55 | for (const auto &I : Add) |
56 | if (!Sub.count(key: I)) |
57 | Elts.insert(X: I); |
58 | } |
59 | }; |
60 | |
61 | // (and S1, S2) Set intersection. |
62 | struct AndOp : public SetTheory::Operator { |
63 | void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, |
64 | ArrayRef<SMLoc> Loc) override { |
65 | if (Expr->arg_size() != 2) |
66 | PrintFatalError(ErrorLoc: Loc, Msg: "Set intersection requires two arguments: " + |
67 | Expr->getAsString()); |
68 | RecSet S1, S2; |
69 | ST.evaluate(Expr: Expr->arg_begin()[0], Elts&: S1, Loc); |
70 | ST.evaluate(Expr: Expr->arg_begin()[1], Elts&: S2, Loc); |
71 | for (const auto &I : S1) |
72 | if (S2.count(key: I)) |
73 | Elts.insert(X: I); |
74 | } |
75 | }; |
76 | |
77 | // SetIntBinOp - Abstract base class for (Op S, N) operators. |
78 | struct SetIntBinOp : public SetTheory::Operator { |
79 | virtual void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, |
80 | RecSet &Elts, ArrayRef<SMLoc> Loc) = 0; |
81 | |
82 | void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, |
83 | ArrayRef<SMLoc> Loc) override { |
84 | if (Expr->arg_size() != 2) |
85 | PrintFatalError(ErrorLoc: Loc, Msg: "Operator requires (Op Set, Int) arguments: " + |
86 | Expr->getAsString()); |
87 | RecSet Set; |
88 | ST.evaluate(Expr: Expr->arg_begin()[0], Elts&: Set, Loc); |
89 | IntInit *II = dyn_cast<IntInit>(Val: Expr->arg_begin()[1]); |
90 | if (!II) |
91 | PrintFatalError(ErrorLoc: Loc, Msg: "Second argument must be an integer: " + |
92 | Expr->getAsString()); |
93 | apply2(ST, Expr, Set, N: II->getValue(), Elts, Loc); |
94 | } |
95 | }; |
96 | |
97 | // (shl S, N) Shift left, remove the first N elements. |
98 | struct ShlOp : public SetIntBinOp { |
99 | void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, |
100 | RecSet &Elts, ArrayRef<SMLoc> Loc) override { |
101 | if (N < 0) |
102 | PrintFatalError(ErrorLoc: Loc, Msg: "Positive shift required: " + |
103 | Expr->getAsString()); |
104 | if (unsigned(N) < Set.size()) |
105 | Elts.insert(Start: Set.begin() + N, End: Set.end()); |
106 | } |
107 | }; |
108 | |
109 | // (trunc S, N) Truncate after the first N elements. |
110 | struct TruncOp : public SetIntBinOp { |
111 | void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, |
112 | RecSet &Elts, ArrayRef<SMLoc> Loc) override { |
113 | if (N < 0) |
114 | PrintFatalError(ErrorLoc: Loc, Msg: "Positive length required: " + |
115 | Expr->getAsString()); |
116 | if (unsigned(N) > Set.size()) |
117 | N = Set.size(); |
118 | Elts.insert(Start: Set.begin(), End: Set.begin() + N); |
119 | } |
120 | }; |
121 | |
122 | // Left/right rotation. |
123 | struct RotOp : public SetIntBinOp { |
124 | const bool Reverse; |
125 | |
126 | RotOp(bool Rev) : Reverse(Rev) {} |
127 | |
128 | void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, |
129 | RecSet &Elts, ArrayRef<SMLoc> Loc) override { |
130 | if (Reverse) |
131 | N = -N; |
132 | // N > 0 -> rotate left, N < 0 -> rotate right. |
133 | if (Set.empty()) |
134 | return; |
135 | if (N < 0) |
136 | N = Set.size() - (-N % Set.size()); |
137 | else |
138 | N %= Set.size(); |
139 | Elts.insert(Start: Set.begin() + N, End: Set.end()); |
140 | Elts.insert(Start: Set.begin(), End: Set.begin() + N); |
141 | } |
142 | }; |
143 | |
144 | // (decimate S, N) Pick every N'th element of S. |
145 | struct DecimateOp : public SetIntBinOp { |
146 | void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, |
147 | RecSet &Elts, ArrayRef<SMLoc> Loc) override { |
148 | if (N <= 0) |
149 | PrintFatalError(ErrorLoc: Loc, Msg: "Positive stride required: " + |
150 | Expr->getAsString()); |
151 | for (unsigned I = 0; I < Set.size(); I += N) |
152 | Elts.insert(X: Set[I]); |
153 | } |
154 | }; |
155 | |
156 | // (interleave S1, S2, ...) Interleave elements of the arguments. |
157 | struct InterleaveOp : public SetTheory::Operator { |
158 | void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, |
159 | ArrayRef<SMLoc> Loc) override { |
160 | // Evaluate the arguments individually. |
161 | SmallVector<RecSet, 4> Args(Expr->getNumArgs()); |
162 | unsigned MaxSize = 0; |
163 | for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { |
164 | ST.evaluate(Expr: Expr->getArg(Num: i), Elts&: Args[i], Loc); |
165 | MaxSize = std::max(a: MaxSize, b: unsigned(Args[i].size())); |
166 | } |
167 | // Interleave arguments into Elts. |
168 | for (unsigned n = 0; n != MaxSize; ++n) |
169 | for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) |
170 | if (n < Args[i].size()) |
171 | Elts.insert(X: Args[i][n]); |
172 | } |
173 | }; |
174 | |
175 | // (sequence "Format", From, To) Generate a sequence of records by name. |
176 | struct SequenceOp : public SetTheory::Operator { |
177 | void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, |
178 | ArrayRef<SMLoc> Loc) override { |
179 | int Step = 1; |
180 | if (Expr->arg_size() > 4) |
181 | PrintFatalError(ErrorLoc: Loc, Msg: "Bad args to (sequence \"Format\", From, To): " + |
182 | Expr->getAsString()); |
183 | else if (Expr->arg_size() == 4) { |
184 | if (IntInit *II = dyn_cast<IntInit>(Val: Expr->arg_begin()[3])) { |
185 | Step = II->getValue(); |
186 | } else |
187 | PrintFatalError(ErrorLoc: Loc, Msg: "Stride must be an integer: " + |
188 | Expr->getAsString()); |
189 | } |
190 | |
191 | std::string Format; |
192 | if (StringInit *SI = dyn_cast<StringInit>(Val: Expr->arg_begin()[0])) |
193 | Format = std::string(SI->getValue()); |
194 | else |
195 | PrintFatalError(ErrorLoc: Loc, Msg: "Format must be a string: " + Expr->getAsString()); |
196 | |
197 | int64_t From, To; |
198 | if (IntInit *II = dyn_cast<IntInit>(Val: Expr->arg_begin()[1])) |
199 | From = II->getValue(); |
200 | else |
201 | PrintFatalError(ErrorLoc: Loc, Msg: "From must be an integer: " + Expr->getAsString()); |
202 | if (From < 0 || From >= (1 << 30)) |
203 | PrintFatalError(ErrorLoc: Loc, Msg: "From out of range" ); |
204 | |
205 | if (IntInit *II = dyn_cast<IntInit>(Val: Expr->arg_begin()[2])) |
206 | To = II->getValue(); |
207 | else |
208 | PrintFatalError(ErrorLoc: Loc, Msg: "To must be an integer: " + Expr->getAsString()); |
209 | if (To < 0 || To >= (1 << 30)) |
210 | PrintFatalError(ErrorLoc: Loc, Msg: "To out of range" ); |
211 | |
212 | RecordKeeper &Records = |
213 | cast<DefInit>(Val: Expr->getOperator())->getDef()->getRecords(); |
214 | |
215 | Step *= From <= To ? 1 : -1; |
216 | while (true) { |
217 | if (Step > 0 && From > To) |
218 | break; |
219 | else if (Step < 0 && From < To) |
220 | break; |
221 | std::string Name; |
222 | raw_string_ostream OS(Name); |
223 | OS << format(Fmt: Format.c_str(), Vals: unsigned(From)); |
224 | Record *Rec = Records.getDef(Name); |
225 | if (!Rec) |
226 | PrintFatalError(ErrorLoc: Loc, Msg: "No def named '" + Name + "': " + |
227 | Expr->getAsString()); |
228 | // Try to reevaluate Rec in case it is a set. |
229 | if (const RecVec *Result = ST.expand(Set: Rec)) |
230 | Elts.insert(Start: Result->begin(), End: Result->end()); |
231 | else |
232 | Elts.insert(X: Rec); |
233 | |
234 | From += Step; |
235 | } |
236 | } |
237 | }; |
238 | |
239 | // Expand a Def into a set by evaluating one of its fields. |
240 | struct FieldExpander : public SetTheory::Expander { |
241 | StringRef FieldName; |
242 | |
243 | FieldExpander(StringRef fn) : FieldName(fn) {} |
244 | |
245 | void expand(SetTheory &ST, Record *Def, RecSet &Elts) override { |
246 | ST.evaluate(Expr: Def->getValueInit(FieldName), Elts, Loc: Def->getLoc()); |
247 | } |
248 | }; |
249 | |
250 | } // end anonymous namespace |
251 | |
252 | // Pin the vtables to this file. |
253 | void SetTheory::Operator::anchor() {} |
254 | void SetTheory::Expander::anchor() {} |
255 | |
256 | SetTheory::SetTheory() { |
257 | addOperator(Name: "add" , std::make_unique<AddOp>()); |
258 | addOperator(Name: "sub" , std::make_unique<SubOp>()); |
259 | addOperator(Name: "and" , std::make_unique<AndOp>()); |
260 | addOperator(Name: "shl" , std::make_unique<ShlOp>()); |
261 | addOperator(Name: "trunc" , std::make_unique<TruncOp>()); |
262 | addOperator(Name: "rotl" , std::make_unique<RotOp>(args: false)); |
263 | addOperator(Name: "rotr" , std::make_unique<RotOp>(args: true)); |
264 | addOperator(Name: "decimate" , std::make_unique<DecimateOp>()); |
265 | addOperator(Name: "interleave" , std::make_unique<InterleaveOp>()); |
266 | addOperator(Name: "sequence" , std::make_unique<SequenceOp>()); |
267 | } |
268 | |
269 | void SetTheory::addOperator(StringRef Name, std::unique_ptr<Operator> Op) { |
270 | Operators[Name] = std::move(Op); |
271 | } |
272 | |
273 | void SetTheory::addExpander(StringRef ClassName, std::unique_ptr<Expander> E) { |
274 | Expanders[ClassName] = std::move(E); |
275 | } |
276 | |
277 | void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { |
278 | addExpander(ClassName, E: std::make_unique<FieldExpander>(args&: FieldName)); |
279 | } |
280 | |
281 | void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { |
282 | // A def in a list can be a just an element, or it may expand. |
283 | if (DefInit *Def = dyn_cast<DefInit>(Val: Expr)) { |
284 | if (const RecVec *Result = expand(Set: Def->getDef())) |
285 | return Elts.insert(Start: Result->begin(), End: Result->end()); |
286 | Elts.insert(X: Def->getDef()); |
287 | return; |
288 | } |
289 | |
290 | // Lists simply expand. |
291 | if (ListInit *LI = dyn_cast<ListInit>(Val: Expr)) |
292 | return evaluate(begin: LI->begin(), end: LI->end(), Elts, Loc); |
293 | |
294 | // Anything else must be a DAG. |
295 | DagInit *DagExpr = dyn_cast<DagInit>(Val: Expr); |
296 | if (!DagExpr) |
297 | PrintFatalError(ErrorLoc: Loc, Msg: "Invalid set element: " + Expr->getAsString()); |
298 | DefInit *OpInit = dyn_cast<DefInit>(Val: DagExpr->getOperator()); |
299 | if (!OpInit) |
300 | PrintFatalError(ErrorLoc: Loc, Msg: "Bad set expression: " + Expr->getAsString()); |
301 | auto I = Operators.find(Key: OpInit->getDef()->getName()); |
302 | if (I == Operators.end()) |
303 | PrintFatalError(ErrorLoc: Loc, Msg: "Unknown set operator: " + Expr->getAsString()); |
304 | I->second->apply(*this, Expr: DagExpr, Elts, Loc); |
305 | } |
306 | |
307 | const RecVec *SetTheory::expand(Record *Set) { |
308 | // Check existing entries for Set and return early. |
309 | ExpandMap::iterator I = Expansions.find(x: Set); |
310 | if (I != Expansions.end()) |
311 | return &I->second; |
312 | |
313 | // This is the first time we see Set. Find a suitable expander. |
314 | ArrayRef<std::pair<Record *, SMRange>> SC = Set->getSuperClasses(); |
315 | for (const auto &SCPair : SC) { |
316 | // Skip unnamed superclasses. |
317 | if (!isa<StringInit>(Val: SCPair.first->getNameInit())) |
318 | continue; |
319 | auto I = Expanders.find(Key: SCPair.first->getName()); |
320 | if (I != Expanders.end()) { |
321 | // This breaks recursive definitions. |
322 | RecVec &EltVec = Expansions[Set]; |
323 | RecSet Elts; |
324 | I->second->expand(*this, Set, Elts); |
325 | EltVec.assign(first: Elts.begin(), last: Elts.end()); |
326 | return &EltVec; |
327 | } |
328 | } |
329 | |
330 | // Set is not expandable. |
331 | return nullptr; |
332 | } |
333 | |