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