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