Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- GVNExpression.h - GVN Expression classes -----------------*- 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 | /// \file |
||
10 | /// |
||
11 | /// The header file for the GVN pass that contains expression handling |
||
12 | /// classes |
||
13 | // |
||
14 | //===----------------------------------------------------------------------===// |
||
15 | |||
16 | #ifndef LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H |
||
17 | #define LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H |
||
18 | |||
19 | #include "llvm/ADT/Hashing.h" |
||
20 | #include "llvm/ADT/iterator_range.h" |
||
21 | #include "llvm/Analysis/MemorySSA.h" |
||
22 | #include "llvm/IR/Constant.h" |
||
23 | #include "llvm/IR/Instructions.h" |
||
24 | #include "llvm/IR/Value.h" |
||
25 | #include "llvm/Support/Allocator.h" |
||
26 | #include "llvm/Support/ArrayRecycler.h" |
||
27 | #include "llvm/Support/Casting.h" |
||
28 | #include "llvm/Support/Compiler.h" |
||
29 | #include "llvm/Support/raw_ostream.h" |
||
30 | #include <algorithm> |
||
31 | #include <cassert> |
||
32 | #include <iterator> |
||
33 | #include <utility> |
||
34 | |||
35 | namespace llvm { |
||
36 | |||
37 | class BasicBlock; |
||
38 | class Type; |
||
39 | |||
40 | namespace GVNExpression { |
||
41 | |||
42 | enum ExpressionType { |
||
43 | ET_Base, |
||
44 | ET_Constant, |
||
45 | ET_Variable, |
||
46 | ET_Dead, |
||
47 | ET_Unknown, |
||
48 | ET_BasicStart, |
||
49 | ET_Basic, |
||
50 | ET_AggregateValue, |
||
51 | ET_Phi, |
||
52 | ET_MemoryStart, |
||
53 | ET_Call, |
||
54 | ET_Load, |
||
55 | ET_Store, |
||
56 | ET_MemoryEnd, |
||
57 | ET_BasicEnd |
||
58 | }; |
||
59 | |||
60 | class Expression { |
||
61 | private: |
||
62 | ExpressionType EType; |
||
63 | unsigned Opcode; |
||
64 | mutable hash_code HashVal = 0; |
||
65 | |||
66 | public: |
||
67 | Expression(ExpressionType ET = ET_Base, unsigned O = ~2U) |
||
68 | : EType(ET), Opcode(O) {} |
||
69 | Expression(const Expression &) = delete; |
||
70 | Expression &operator=(const Expression &) = delete; |
||
71 | virtual ~Expression(); |
||
72 | |||
73 | static unsigned getEmptyKey() { return ~0U; } |
||
74 | static unsigned getTombstoneKey() { return ~1U; } |
||
75 | |||
76 | bool operator!=(const Expression &Other) const { return !(*this == Other); } |
||
77 | bool operator==(const Expression &Other) const { |
||
78 | if (getOpcode() != Other.getOpcode()) |
||
79 | return false; |
||
80 | if (getOpcode() == getEmptyKey() || getOpcode() == getTombstoneKey()) |
||
81 | return true; |
||
82 | // Compare the expression type for anything but load and store. |
||
83 | // For load and store we set the opcode to zero to make them equal. |
||
84 | if (getExpressionType() != ET_Load && getExpressionType() != ET_Store && |
||
85 | getExpressionType() != Other.getExpressionType()) |
||
86 | return false; |
||
87 | |||
88 | return equals(Other); |
||
89 | } |
||
90 | |||
91 | hash_code getComputedHash() const { |
||
92 | // It's theoretically possible for a thing to hash to zero. In that case, |
||
93 | // we will just compute the hash a few extra times, which is no worse that |
||
94 | // we did before, which was to compute it always. |
||
95 | if (static_cast<unsigned>(HashVal) == 0) |
||
96 | HashVal = getHashValue(); |
||
97 | return HashVal; |
||
98 | } |
||
99 | |||
100 | virtual bool equals(const Expression &Other) const { return true; } |
||
101 | |||
102 | // Return true if the two expressions are exactly the same, including the |
||
103 | // normally ignored fields. |
||
104 | virtual bool exactlyEquals(const Expression &Other) const { |
||
105 | return getExpressionType() == Other.getExpressionType() && equals(Other); |
||
106 | } |
||
107 | |||
108 | unsigned getOpcode() const { return Opcode; } |
||
109 | void setOpcode(unsigned opcode) { Opcode = opcode; } |
||
110 | ExpressionType getExpressionType() const { return EType; } |
||
111 | |||
112 | // We deliberately leave the expression type out of the hash value. |
||
113 | virtual hash_code getHashValue() const { return getOpcode(); } |
||
114 | |||
115 | // Debugging support |
||
116 | virtual void printInternal(raw_ostream &OS, bool PrintEType) const { |
||
117 | if (PrintEType) |
||
118 | OS << "etype = " << getExpressionType() << ","; |
||
119 | OS << "opcode = " << getOpcode() << ", "; |
||
120 | } |
||
121 | |||
122 | void print(raw_ostream &OS) const { |
||
123 | OS << "{ "; |
||
124 | printInternal(OS, true); |
||
125 | OS << "}"; |
||
126 | } |
||
127 | |||
128 | LLVM_DUMP_METHOD void dump() const; |
||
129 | }; |
||
130 | |||
131 | inline raw_ostream &operator<<(raw_ostream &OS, const Expression &E) { |
||
132 | E.print(OS); |
||
133 | return OS; |
||
134 | } |
||
135 | |||
136 | class BasicExpression : public Expression { |
||
137 | private: |
||
138 | using RecyclerType = ArrayRecycler<Value *>; |
||
139 | using RecyclerCapacity = RecyclerType::Capacity; |
||
140 | |||
141 | Value **Operands = nullptr; |
||
142 | unsigned MaxOperands; |
||
143 | unsigned NumOperands = 0; |
||
144 | Type *ValueType = nullptr; |
||
145 | |||
146 | public: |
||
147 | BasicExpression(unsigned NumOperands) |
||
148 | : BasicExpression(NumOperands, ET_Basic) {} |
||
149 | BasicExpression(unsigned NumOperands, ExpressionType ET) |
||
150 | : Expression(ET), MaxOperands(NumOperands) {} |
||
151 | BasicExpression() = delete; |
||
152 | BasicExpression(const BasicExpression &) = delete; |
||
153 | BasicExpression &operator=(const BasicExpression &) = delete; |
||
154 | ~BasicExpression() override; |
||
155 | |||
156 | static bool classof(const Expression *EB) { |
||
157 | ExpressionType ET = EB->getExpressionType(); |
||
158 | return ET > ET_BasicStart && ET < ET_BasicEnd; |
||
159 | } |
||
160 | |||
161 | /// Swap two operands. Used during GVN to put commutative operands in |
||
162 | /// order. |
||
163 | void swapOperands(unsigned First, unsigned Second) { |
||
164 | std::swap(Operands[First], Operands[Second]); |
||
165 | } |
||
166 | |||
167 | Value *getOperand(unsigned N) const { |
||
168 | assert(Operands && "Operands not allocated"); |
||
169 | assert(N < NumOperands && "Operand out of range"); |
||
170 | return Operands[N]; |
||
171 | } |
||
172 | |||
173 | void setOperand(unsigned N, Value *V) { |
||
174 | assert(Operands && "Operands not allocated before setting"); |
||
175 | assert(N < NumOperands && "Operand out of range"); |
||
176 | Operands[N] = V; |
||
177 | } |
||
178 | |||
179 | unsigned getNumOperands() const { return NumOperands; } |
||
180 | |||
181 | using op_iterator = Value **; |
||
182 | using const_op_iterator = Value *const *; |
||
183 | |||
184 | op_iterator op_begin() { return Operands; } |
||
185 | op_iterator op_end() { return Operands + NumOperands; } |
||
186 | const_op_iterator op_begin() const { return Operands; } |
||
187 | const_op_iterator op_end() const { return Operands + NumOperands; } |
||
188 | iterator_range<op_iterator> operands() { |
||
189 | return iterator_range<op_iterator>(op_begin(), op_end()); |
||
190 | } |
||
191 | iterator_range<const_op_iterator> operands() const { |
||
192 | return iterator_range<const_op_iterator>(op_begin(), op_end()); |
||
193 | } |
||
194 | |||
195 | void op_push_back(Value *Arg) { |
||
196 | assert(NumOperands < MaxOperands && "Tried to add too many operands"); |
||
197 | assert(Operands && "Operandss not allocated before pushing"); |
||
198 | Operands[NumOperands++] = Arg; |
||
199 | } |
||
200 | bool op_empty() const { return getNumOperands() == 0; } |
||
201 | |||
202 | void allocateOperands(RecyclerType &Recycler, BumpPtrAllocator &Allocator) { |
||
203 | assert(!Operands && "Operands already allocated"); |
||
204 | Operands = Recycler.allocate(RecyclerCapacity::get(MaxOperands), Allocator); |
||
205 | } |
||
206 | void deallocateOperands(RecyclerType &Recycler) { |
||
207 | Recycler.deallocate(RecyclerCapacity::get(MaxOperands), Operands); |
||
208 | } |
||
209 | |||
210 | void setType(Type *T) { ValueType = T; } |
||
211 | Type *getType() const { return ValueType; } |
||
212 | |||
213 | bool equals(const Expression &Other) const override { |
||
214 | if (getOpcode() != Other.getOpcode()) |
||
215 | return false; |
||
216 | |||
217 | const auto &OE = cast<BasicExpression>(Other); |
||
218 | return getType() == OE.getType() && NumOperands == OE.NumOperands && |
||
219 | std::equal(op_begin(), op_end(), OE.op_begin()); |
||
220 | } |
||
221 | |||
222 | hash_code getHashValue() const override { |
||
223 | return hash_combine(this->Expression::getHashValue(), ValueType, |
||
224 | hash_combine_range(op_begin(), op_end())); |
||
225 | } |
||
226 | |||
227 | // Debugging support |
||
228 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
229 | if (PrintEType) |
||
230 | OS << "ExpressionTypeBasic, "; |
||
231 | |||
232 | this->Expression::printInternal(OS, false); |
||
233 | OS << "operands = {"; |
||
234 | for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { |
||
235 | OS << "[" << i << "] = "; |
||
236 | Operands[i]->printAsOperand(OS); |
||
237 | OS << " "; |
||
238 | } |
||
239 | OS << "} "; |
||
240 | } |
||
241 | }; |
||
242 | |||
243 | class op_inserter { |
||
244 | private: |
||
245 | using Container = BasicExpression; |
||
246 | |||
247 | Container *BE; |
||
248 | |||
249 | public: |
||
250 | using iterator_category = std::output_iterator_tag; |
||
251 | using value_type = void; |
||
252 | using difference_type = void; |
||
253 | using pointer = void; |
||
254 | using reference = void; |
||
255 | |||
256 | explicit op_inserter(BasicExpression &E) : BE(&E) {} |
||
257 | explicit op_inserter(BasicExpression *E) : BE(E) {} |
||
258 | |||
259 | op_inserter &operator=(Value *val) { |
||
260 | BE->op_push_back(val); |
||
261 | return *this; |
||
262 | } |
||
263 | op_inserter &operator*() { return *this; } |
||
264 | op_inserter &operator++() { return *this; } |
||
265 | op_inserter &operator++(int) { return *this; } |
||
266 | }; |
||
267 | |||
268 | class MemoryExpression : public BasicExpression { |
||
269 | private: |
||
270 | const MemoryAccess *MemoryLeader; |
||
271 | |||
272 | public: |
||
273 | MemoryExpression(unsigned NumOperands, enum ExpressionType EType, |
||
274 | const MemoryAccess *MemoryLeader) |
||
275 | : BasicExpression(NumOperands, EType), MemoryLeader(MemoryLeader) {} |
||
276 | MemoryExpression() = delete; |
||
277 | MemoryExpression(const MemoryExpression &) = delete; |
||
278 | MemoryExpression &operator=(const MemoryExpression &) = delete; |
||
279 | |||
280 | static bool classof(const Expression *EB) { |
||
281 | return EB->getExpressionType() > ET_MemoryStart && |
||
282 | EB->getExpressionType() < ET_MemoryEnd; |
||
283 | } |
||
284 | |||
285 | hash_code getHashValue() const override { |
||
286 | return hash_combine(this->BasicExpression::getHashValue(), MemoryLeader); |
||
287 | } |
||
288 | |||
289 | bool equals(const Expression &Other) const override { |
||
290 | if (!this->BasicExpression::equals(Other)) |
||
291 | return false; |
||
292 | const MemoryExpression &OtherMCE = cast<MemoryExpression>(Other); |
||
293 | |||
294 | return MemoryLeader == OtherMCE.MemoryLeader; |
||
295 | } |
||
296 | |||
297 | const MemoryAccess *getMemoryLeader() const { return MemoryLeader; } |
||
298 | void setMemoryLeader(const MemoryAccess *ML) { MemoryLeader = ML; } |
||
299 | }; |
||
300 | |||
301 | class CallExpression final : public MemoryExpression { |
||
302 | private: |
||
303 | CallInst *Call; |
||
304 | |||
305 | public: |
||
306 | CallExpression(unsigned NumOperands, CallInst *C, |
||
307 | const MemoryAccess *MemoryLeader) |
||
308 | : MemoryExpression(NumOperands, ET_Call, MemoryLeader), Call(C) {} |
||
309 | CallExpression() = delete; |
||
310 | CallExpression(const CallExpression &) = delete; |
||
311 | CallExpression &operator=(const CallExpression &) = delete; |
||
312 | ~CallExpression() override; |
||
313 | |||
314 | static bool classof(const Expression *EB) { |
||
315 | return EB->getExpressionType() == ET_Call; |
||
316 | } |
||
317 | |||
318 | // Debugging support |
||
319 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
320 | if (PrintEType) |
||
321 | OS << "ExpressionTypeCall, "; |
||
322 | this->BasicExpression::printInternal(OS, false); |
||
323 | OS << " represents call at "; |
||
324 | Call->printAsOperand(OS); |
||
325 | } |
||
326 | }; |
||
327 | |||
328 | class LoadExpression final : public MemoryExpression { |
||
329 | private: |
||
330 | LoadInst *Load; |
||
331 | |||
332 | public: |
||
333 | LoadExpression(unsigned NumOperands, LoadInst *L, |
||
334 | const MemoryAccess *MemoryLeader) |
||
335 | : LoadExpression(ET_Load, NumOperands, L, MemoryLeader) {} |
||
336 | |||
337 | LoadExpression(enum ExpressionType EType, unsigned NumOperands, LoadInst *L, |
||
338 | const MemoryAccess *MemoryLeader) |
||
339 | : MemoryExpression(NumOperands, EType, MemoryLeader), Load(L) {} |
||
340 | |||
341 | LoadExpression() = delete; |
||
342 | LoadExpression(const LoadExpression &) = delete; |
||
343 | LoadExpression &operator=(const LoadExpression &) = delete; |
||
344 | ~LoadExpression() override; |
||
345 | |||
346 | static bool classof(const Expression *EB) { |
||
347 | return EB->getExpressionType() == ET_Load; |
||
348 | } |
||
349 | |||
350 | LoadInst *getLoadInst() const { return Load; } |
||
351 | void setLoadInst(LoadInst *L) { Load = L; } |
||
352 | |||
353 | bool equals(const Expression &Other) const override; |
||
354 | bool exactlyEquals(const Expression &Other) const override { |
||
355 | return Expression::exactlyEquals(Other) && |
||
356 | cast<LoadExpression>(Other).getLoadInst() == getLoadInst(); |
||
357 | } |
||
358 | |||
359 | // Debugging support |
||
360 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
361 | if (PrintEType) |
||
362 | OS << "ExpressionTypeLoad, "; |
||
363 | this->BasicExpression::printInternal(OS, false); |
||
364 | OS << " represents Load at "; |
||
365 | Load->printAsOperand(OS); |
||
366 | OS << " with MemoryLeader " << *getMemoryLeader(); |
||
367 | } |
||
368 | }; |
||
369 | |||
370 | class StoreExpression final : public MemoryExpression { |
||
371 | private: |
||
372 | StoreInst *Store; |
||
373 | Value *StoredValue; |
||
374 | |||
375 | public: |
||
376 | StoreExpression(unsigned NumOperands, StoreInst *S, Value *StoredValue, |
||
377 | const MemoryAccess *MemoryLeader) |
||
378 | : MemoryExpression(NumOperands, ET_Store, MemoryLeader), Store(S), |
||
379 | StoredValue(StoredValue) {} |
||
380 | StoreExpression() = delete; |
||
381 | StoreExpression(const StoreExpression &) = delete; |
||
382 | StoreExpression &operator=(const StoreExpression &) = delete; |
||
383 | ~StoreExpression() override; |
||
384 | |||
385 | static bool classof(const Expression *EB) { |
||
386 | return EB->getExpressionType() == ET_Store; |
||
387 | } |
||
388 | |||
389 | StoreInst *getStoreInst() const { return Store; } |
||
390 | Value *getStoredValue() const { return StoredValue; } |
||
391 | |||
392 | bool equals(const Expression &Other) const override; |
||
393 | |||
394 | bool exactlyEquals(const Expression &Other) const override { |
||
395 | return Expression::exactlyEquals(Other) && |
||
396 | cast<StoreExpression>(Other).getStoreInst() == getStoreInst(); |
||
397 | } |
||
398 | |||
399 | // Debugging support |
||
400 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
401 | if (PrintEType) |
||
402 | OS << "ExpressionTypeStore, "; |
||
403 | this->BasicExpression::printInternal(OS, false); |
||
404 | OS << " represents Store " << *Store; |
||
405 | OS << " with StoredValue "; |
||
406 | StoredValue->printAsOperand(OS); |
||
407 | OS << " and MemoryLeader " << *getMemoryLeader(); |
||
408 | } |
||
409 | }; |
||
410 | |||
411 | class AggregateValueExpression final : public BasicExpression { |
||
412 | private: |
||
413 | unsigned MaxIntOperands; |
||
414 | unsigned NumIntOperands = 0; |
||
415 | unsigned *IntOperands = nullptr; |
||
416 | |||
417 | public: |
||
418 | AggregateValueExpression(unsigned NumOperands, unsigned NumIntOperands) |
||
419 | : BasicExpression(NumOperands, ET_AggregateValue), |
||
420 | MaxIntOperands(NumIntOperands) {} |
||
421 | AggregateValueExpression() = delete; |
||
422 | AggregateValueExpression(const AggregateValueExpression &) = delete; |
||
423 | AggregateValueExpression & |
||
424 | operator=(const AggregateValueExpression &) = delete; |
||
425 | ~AggregateValueExpression() override; |
||
426 | |||
427 | static bool classof(const Expression *EB) { |
||
428 | return EB->getExpressionType() == ET_AggregateValue; |
||
429 | } |
||
430 | |||
431 | using int_arg_iterator = unsigned *; |
||
432 | using const_int_arg_iterator = const unsigned *; |
||
433 | |||
434 | int_arg_iterator int_op_begin() { return IntOperands; } |
||
435 | int_arg_iterator int_op_end() { return IntOperands + NumIntOperands; } |
||
436 | const_int_arg_iterator int_op_begin() const { return IntOperands; } |
||
437 | const_int_arg_iterator int_op_end() const { |
||
438 | return IntOperands + NumIntOperands; |
||
439 | } |
||
440 | unsigned int_op_size() const { return NumIntOperands; } |
||
441 | bool int_op_empty() const { return NumIntOperands == 0; } |
||
442 | void int_op_push_back(unsigned IntOperand) { |
||
443 | assert(NumIntOperands < MaxIntOperands && |
||
444 | "Tried to add too many int operands"); |
||
445 | assert(IntOperands && "Operands not allocated before pushing"); |
||
446 | IntOperands[NumIntOperands++] = IntOperand; |
||
447 | } |
||
448 | |||
449 | virtual void allocateIntOperands(BumpPtrAllocator &Allocator) { |
||
450 | assert(!IntOperands && "Operands already allocated"); |
||
451 | IntOperands = Allocator.Allocate<unsigned>(MaxIntOperands); |
||
452 | } |
||
453 | |||
454 | bool equals(const Expression &Other) const override { |
||
455 | if (!this->BasicExpression::equals(Other)) |
||
456 | return false; |
||
457 | const AggregateValueExpression &OE = cast<AggregateValueExpression>(Other); |
||
458 | return NumIntOperands == OE.NumIntOperands && |
||
459 | std::equal(int_op_begin(), int_op_end(), OE.int_op_begin()); |
||
460 | } |
||
461 | |||
462 | hash_code getHashValue() const override { |
||
463 | return hash_combine(this->BasicExpression::getHashValue(), |
||
464 | hash_combine_range(int_op_begin(), int_op_end())); |
||
465 | } |
||
466 | |||
467 | // Debugging support |
||
468 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
469 | if (PrintEType) |
||
470 | OS << "ExpressionTypeAggregateValue, "; |
||
471 | this->BasicExpression::printInternal(OS, false); |
||
472 | OS << ", intoperands = {"; |
||
473 | for (unsigned i = 0, e = int_op_size(); i != e; ++i) { |
||
474 | OS << "[" << i << "] = " << IntOperands[i] << " "; |
||
475 | } |
||
476 | OS << "}"; |
||
477 | } |
||
478 | }; |
||
479 | |||
480 | class int_op_inserter { |
||
481 | private: |
||
482 | using Container = AggregateValueExpression; |
||
483 | |||
484 | Container *AVE; |
||
485 | |||
486 | public: |
||
487 | using iterator_category = std::output_iterator_tag; |
||
488 | using value_type = void; |
||
489 | using difference_type = void; |
||
490 | using pointer = void; |
||
491 | using reference = void; |
||
492 | |||
493 | explicit int_op_inserter(AggregateValueExpression &E) : AVE(&E) {} |
||
494 | explicit int_op_inserter(AggregateValueExpression *E) : AVE(E) {} |
||
495 | |||
496 | int_op_inserter &operator=(unsigned int val) { |
||
497 | AVE->int_op_push_back(val); |
||
498 | return *this; |
||
499 | } |
||
500 | int_op_inserter &operator*() { return *this; } |
||
501 | int_op_inserter &operator++() { return *this; } |
||
502 | int_op_inserter &operator++(int) { return *this; } |
||
503 | }; |
||
504 | |||
505 | class PHIExpression final : public BasicExpression { |
||
506 | private: |
||
507 | BasicBlock *BB; |
||
508 | |||
509 | public: |
||
510 | PHIExpression(unsigned NumOperands, BasicBlock *B) |
||
511 | : BasicExpression(NumOperands, ET_Phi), BB(B) {} |
||
512 | PHIExpression() = delete; |
||
513 | PHIExpression(const PHIExpression &) = delete; |
||
514 | PHIExpression &operator=(const PHIExpression &) = delete; |
||
515 | ~PHIExpression() override; |
||
516 | |||
517 | static bool classof(const Expression *EB) { |
||
518 | return EB->getExpressionType() == ET_Phi; |
||
519 | } |
||
520 | |||
521 | bool equals(const Expression &Other) const override { |
||
522 | if (!this->BasicExpression::equals(Other)) |
||
523 | return false; |
||
524 | const PHIExpression &OE = cast<PHIExpression>(Other); |
||
525 | return BB == OE.BB; |
||
526 | } |
||
527 | |||
528 | hash_code getHashValue() const override { |
||
529 | return hash_combine(this->BasicExpression::getHashValue(), BB); |
||
530 | } |
||
531 | |||
532 | // Debugging support |
||
533 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
534 | if (PrintEType) |
||
535 | OS << "ExpressionTypePhi, "; |
||
536 | this->BasicExpression::printInternal(OS, false); |
||
537 | OS << "bb = " << BB; |
||
538 | } |
||
539 | }; |
||
540 | |||
541 | class DeadExpression final : public Expression { |
||
542 | public: |
||
543 | DeadExpression() : Expression(ET_Dead) {} |
||
544 | DeadExpression(const DeadExpression &) = delete; |
||
545 | DeadExpression &operator=(const DeadExpression &) = delete; |
||
546 | |||
547 | static bool classof(const Expression *E) { |
||
548 | return E->getExpressionType() == ET_Dead; |
||
549 | } |
||
550 | }; |
||
551 | |||
552 | class VariableExpression final : public Expression { |
||
553 | private: |
||
554 | Value *VariableValue; |
||
555 | |||
556 | public: |
||
557 | VariableExpression(Value *V) : Expression(ET_Variable), VariableValue(V) {} |
||
558 | VariableExpression() = delete; |
||
559 | VariableExpression(const VariableExpression &) = delete; |
||
560 | VariableExpression &operator=(const VariableExpression &) = delete; |
||
561 | |||
562 | static bool classof(const Expression *EB) { |
||
563 | return EB->getExpressionType() == ET_Variable; |
||
564 | } |
||
565 | |||
566 | Value *getVariableValue() const { return VariableValue; } |
||
567 | void setVariableValue(Value *V) { VariableValue = V; } |
||
568 | |||
569 | bool equals(const Expression &Other) const override { |
||
570 | const VariableExpression &OC = cast<VariableExpression>(Other); |
||
571 | return VariableValue == OC.VariableValue; |
||
572 | } |
||
573 | |||
574 | hash_code getHashValue() const override { |
||
575 | return hash_combine(this->Expression::getHashValue(), |
||
576 | VariableValue->getType(), VariableValue); |
||
577 | } |
||
578 | |||
579 | // Debugging support |
||
580 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
581 | if (PrintEType) |
||
582 | OS << "ExpressionTypeVariable, "; |
||
583 | this->Expression::printInternal(OS, false); |
||
584 | OS << " variable = " << *VariableValue; |
||
585 | } |
||
586 | }; |
||
587 | |||
588 | class ConstantExpression final : public Expression { |
||
589 | private: |
||
590 | Constant *ConstantValue = nullptr; |
||
591 | |||
592 | public: |
||
593 | ConstantExpression() : Expression(ET_Constant) {} |
||
594 | ConstantExpression(Constant *constantValue) |
||
595 | : Expression(ET_Constant), ConstantValue(constantValue) {} |
||
596 | ConstantExpression(const ConstantExpression &) = delete; |
||
597 | ConstantExpression &operator=(const ConstantExpression &) = delete; |
||
598 | |||
599 | static bool classof(const Expression *EB) { |
||
600 | return EB->getExpressionType() == ET_Constant; |
||
601 | } |
||
602 | |||
603 | Constant *getConstantValue() const { return ConstantValue; } |
||
604 | void setConstantValue(Constant *V) { ConstantValue = V; } |
||
605 | |||
606 | bool equals(const Expression &Other) const override { |
||
607 | const ConstantExpression &OC = cast<ConstantExpression>(Other); |
||
608 | return ConstantValue == OC.ConstantValue; |
||
609 | } |
||
610 | |||
611 | hash_code getHashValue() const override { |
||
612 | return hash_combine(this->Expression::getHashValue(), |
||
613 | ConstantValue->getType(), ConstantValue); |
||
614 | } |
||
615 | |||
616 | // Debugging support |
||
617 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
618 | if (PrintEType) |
||
619 | OS << "ExpressionTypeConstant, "; |
||
620 | this->Expression::printInternal(OS, false); |
||
621 | OS << " constant = " << *ConstantValue; |
||
622 | } |
||
623 | }; |
||
624 | |||
625 | class UnknownExpression final : public Expression { |
||
626 | private: |
||
627 | Instruction *Inst; |
||
628 | |||
629 | public: |
||
630 | UnknownExpression(Instruction *I) : Expression(ET_Unknown), Inst(I) {} |
||
631 | UnknownExpression() = delete; |
||
632 | UnknownExpression(const UnknownExpression &) = delete; |
||
633 | UnknownExpression &operator=(const UnknownExpression &) = delete; |
||
634 | |||
635 | static bool classof(const Expression *EB) { |
||
636 | return EB->getExpressionType() == ET_Unknown; |
||
637 | } |
||
638 | |||
639 | Instruction *getInstruction() const { return Inst; } |
||
640 | void setInstruction(Instruction *I) { Inst = I; } |
||
641 | |||
642 | bool equals(const Expression &Other) const override { |
||
643 | const auto &OU = cast<UnknownExpression>(Other); |
||
644 | return Inst == OU.Inst; |
||
645 | } |
||
646 | |||
647 | hash_code getHashValue() const override { |
||
648 | return hash_combine(this->Expression::getHashValue(), Inst); |
||
649 | } |
||
650 | |||
651 | // Debugging support |
||
652 | void printInternal(raw_ostream &OS, bool PrintEType) const override { |
||
653 | if (PrintEType) |
||
654 | OS << "ExpressionTypeUnknown, "; |
||
655 | this->Expression::printInternal(OS, false); |
||
656 | OS << " inst = " << *Inst; |
||
657 | } |
||
658 | }; |
||
659 | |||
660 | } // end namespace GVNExpression |
||
661 | |||
662 | } // end namespace llvm |
||
663 | |||
664 | #endif // LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H |