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) EType(ET)68 : EType(ET), Opcode(O) {} 69 Expression(const Expression &) = delete; 70 Expression &operator=(const Expression &) = delete; 71 virtual ~Expression(); 72 getEmptyKey()73 static unsigned getEmptyKey() { return ~0U; } getTombstoneKey()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 getComputedHash()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 equals(const Expression & Other)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. exactlyEquals(const Expression & Other)104 virtual bool exactlyEquals(const Expression &Other) const { 105 return getExpressionType() == Other.getExpressionType() && equals(Other); 106 } 107 getOpcode()108 unsigned getOpcode() const { return Opcode; } setOpcode(unsigned opcode)109 void setOpcode(unsigned opcode) { Opcode = opcode; } getExpressionType()110 ExpressionType getExpressionType() const { return EType; } 111 112 // We deliberately leave the expression type out of the hash value. getHashValue()113 virtual hash_code getHashValue() const { return getOpcode(); } 114 115 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)116 virtual void printInternal(raw_ostream &OS, bool PrintEType) const { 117 if (PrintEType) 118 OS << "etype = " << getExpressionType() << ","; 119 OS << "opcode = " << getOpcode() << ", "; 120 } 121 print(raw_ostream & OS)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: BasicExpression(unsigned NumOperands)147 BasicExpression(unsigned NumOperands) 148 : BasicExpression(NumOperands, ET_Basic) {} BasicExpression(unsigned NumOperands,ExpressionType ET)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 classof(const Expression * EB)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. swapOperands(unsigned First,unsigned Second)163 void swapOperands(unsigned First, unsigned Second) { 164 std::swap(Operands[First], Operands[Second]); 165 } 166 getOperand(unsigned N)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 setOperand(unsigned N,Value * V)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 getNumOperands()179 unsigned getNumOperands() const { return NumOperands; } 180 181 using op_iterator = Value **; 182 using const_op_iterator = Value *const *; 183 op_begin()184 op_iterator op_begin() { return Operands; } op_end()185 op_iterator op_end() { return Operands + NumOperands; } op_begin()186 const_op_iterator op_begin() const { return Operands; } op_end()187 const_op_iterator op_end() const { return Operands + NumOperands; } operands()188 iterator_range<op_iterator> operands() { 189 return iterator_range<op_iterator>(op_begin(), op_end()); 190 } operands()191 iterator_range<const_op_iterator> operands() const { 192 return iterator_range<const_op_iterator>(op_begin(), op_end()); 193 } 194 op_push_back(Value * Arg)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 } op_empty()200 bool op_empty() const { return getNumOperands() == 0; } 201 allocateOperands(RecyclerType & Recycler,BumpPtrAllocator & Allocator)202 void allocateOperands(RecyclerType &Recycler, BumpPtrAllocator &Allocator) { 203 assert(!Operands && "Operands already allocated"); 204 Operands = Recycler.allocate(RecyclerCapacity::get(MaxOperands), Allocator); 205 } deallocateOperands(RecyclerType & Recycler)206 void deallocateOperands(RecyclerType &Recycler) { 207 Recycler.deallocate(RecyclerCapacity::get(MaxOperands), Operands); 208 } 209 setType(Type * T)210 void setType(Type *T) { ValueType = T; } getType()211 Type *getType() const { return ValueType; } 212 equals(const Expression & Other)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 getHashValue()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 printInternal(raw_ostream & OS,bool PrintEType)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 op_inserter(BasicExpression & E)256 explicit op_inserter(BasicExpression &E) : BE(&E) {} op_inserter(BasicExpression * 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: MemoryExpression(unsigned NumOperands,enum ExpressionType EType,const MemoryAccess * MemoryLeader)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 classof(const Expression * EB)280 static bool classof(const Expression *EB) { 281 return EB->getExpressionType() > ET_MemoryStart && 282 EB->getExpressionType() < ET_MemoryEnd; 283 } 284 getHashValue()285 hash_code getHashValue() const override { 286 return hash_combine(this->BasicExpression::getHashValue(), MemoryLeader); 287 } 288 equals(const Expression & Other)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 getMemoryLeader()297 const MemoryAccess *getMemoryLeader() const { return MemoryLeader; } setMemoryLeader(const MemoryAccess * ML)298 void setMemoryLeader(const MemoryAccess *ML) { MemoryLeader = ML; } 299 }; 300 301 class CallExpression final : public MemoryExpression { 302 private: 303 CallInst *Call; 304 305 public: CallExpression(unsigned NumOperands,CallInst * C,const MemoryAccess * MemoryLeader)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 classof(const Expression * EB)314 static bool classof(const Expression *EB) { 315 return EB->getExpressionType() == ET_Call; 316 } 317 318 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)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: LoadExpression(unsigned NumOperands,LoadInst * L,const MemoryAccess * MemoryLeader)333 LoadExpression(unsigned NumOperands, LoadInst *L, 334 const MemoryAccess *MemoryLeader) 335 : LoadExpression(ET_Load, NumOperands, L, MemoryLeader) {} 336 LoadExpression(enum ExpressionType EType,unsigned NumOperands,LoadInst * L,const MemoryAccess * MemoryLeader)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 classof(const Expression * EB)346 static bool classof(const Expression *EB) { 347 return EB->getExpressionType() == ET_Load; 348 } 349 getLoadInst()350 LoadInst *getLoadInst() const { return Load; } setLoadInst(LoadInst * L)351 void setLoadInst(LoadInst *L) { Load = L; } 352 353 bool equals(const Expression &Other) const override; exactlyEquals(const Expression & Other)354 bool exactlyEquals(const Expression &Other) const override { 355 return Expression::exactlyEquals(Other) && 356 cast<LoadExpression>(Other).getLoadInst() == getLoadInst(); 357 } 358 359 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)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: StoreExpression(unsigned NumOperands,StoreInst * S,Value * StoredValue,const MemoryAccess * MemoryLeader)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 classof(const Expression * EB)385 static bool classof(const Expression *EB) { 386 return EB->getExpressionType() == ET_Store; 387 } 388 getStoreInst()389 StoreInst *getStoreInst() const { return Store; } getStoredValue()390 Value *getStoredValue() const { return StoredValue; } 391 392 bool equals(const Expression &Other) const override; 393 exactlyEquals(const Expression & Other)394 bool exactlyEquals(const Expression &Other) const override { 395 return Expression::exactlyEquals(Other) && 396 cast<StoreExpression>(Other).getStoreInst() == getStoreInst(); 397 } 398 399 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)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: AggregateValueExpression(unsigned NumOperands,unsigned NumIntOperands)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 classof(const Expression * EB)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 int_op_begin()434 int_arg_iterator int_op_begin() { return IntOperands; } int_op_end()435 int_arg_iterator int_op_end() { return IntOperands + NumIntOperands; } int_op_begin()436 const_int_arg_iterator int_op_begin() const { return IntOperands; } int_op_end()437 const_int_arg_iterator int_op_end() const { 438 return IntOperands + NumIntOperands; 439 } int_op_size()440 unsigned int_op_size() const { return NumIntOperands; } int_op_empty()441 bool int_op_empty() const { return NumIntOperands == 0; } int_op_push_back(unsigned IntOperand)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 allocateIntOperands(BumpPtrAllocator & Allocator)449 virtual void allocateIntOperands(BumpPtrAllocator &Allocator) { 450 assert(!IntOperands && "Operands already allocated"); 451 IntOperands = Allocator.Allocate<unsigned>(MaxIntOperands); 452 } 453 equals(const Expression & Other)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 getHashValue()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 printInternal(raw_ostream & OS,bool PrintEType)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 int_op_inserter(AggregateValueExpression & E)493 explicit int_op_inserter(AggregateValueExpression &E) : AVE(&E) {} int_op_inserter(AggregateValueExpression * 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: PHIExpression(unsigned NumOperands,BasicBlock * B)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 classof(const Expression * EB)517 static bool classof(const Expression *EB) { 518 return EB->getExpressionType() == ET_Phi; 519 } 520 equals(const Expression & Other)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 getHashValue()528 hash_code getHashValue() const override { 529 return hash_combine(this->BasicExpression::getHashValue(), BB); 530 } 531 532 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)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: DeadExpression()543 DeadExpression() : Expression(ET_Dead) {} 544 DeadExpression(const DeadExpression &) = delete; 545 DeadExpression &operator=(const DeadExpression &) = delete; 546 classof(const Expression * E)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: VariableExpression(Value * V)557 VariableExpression(Value *V) : Expression(ET_Variable), VariableValue(V) {} 558 VariableExpression() = delete; 559 VariableExpression(const VariableExpression &) = delete; 560 VariableExpression &operator=(const VariableExpression &) = delete; 561 classof(const Expression * EB)562 static bool classof(const Expression *EB) { 563 return EB->getExpressionType() == ET_Variable; 564 } 565 getVariableValue()566 Value *getVariableValue() const { return VariableValue; } setVariableValue(Value * V)567 void setVariableValue(Value *V) { VariableValue = V; } 568 equals(const Expression & Other)569 bool equals(const Expression &Other) const override { 570 const VariableExpression &OC = cast<VariableExpression>(Other); 571 return VariableValue == OC.VariableValue; 572 } 573 getHashValue()574 hash_code getHashValue() const override { 575 return hash_combine(this->Expression::getHashValue(), 576 VariableValue->getType(), VariableValue); 577 } 578 579 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)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: ConstantExpression()593 ConstantExpression() : Expression(ET_Constant) {} ConstantExpression(Constant * constantValue)594 ConstantExpression(Constant *constantValue) 595 : Expression(ET_Constant), ConstantValue(constantValue) {} 596 ConstantExpression(const ConstantExpression &) = delete; 597 ConstantExpression &operator=(const ConstantExpression &) = delete; 598 classof(const Expression * EB)599 static bool classof(const Expression *EB) { 600 return EB->getExpressionType() == ET_Constant; 601 } 602 getConstantValue()603 Constant *getConstantValue() const { return ConstantValue; } setConstantValue(Constant * V)604 void setConstantValue(Constant *V) { ConstantValue = V; } 605 equals(const Expression & Other)606 bool equals(const Expression &Other) const override { 607 const ConstantExpression &OC = cast<ConstantExpression>(Other); 608 return ConstantValue == OC.ConstantValue; 609 } 610 getHashValue()611 hash_code getHashValue() const override { 612 return hash_combine(this->Expression::getHashValue(), 613 ConstantValue->getType(), ConstantValue); 614 } 615 616 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)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: UnknownExpression(Instruction * I)630 UnknownExpression(Instruction *I) : Expression(ET_Unknown), Inst(I) {} 631 UnknownExpression() = delete; 632 UnknownExpression(const UnknownExpression &) = delete; 633 UnknownExpression &operator=(const UnknownExpression &) = delete; 634 classof(const Expression * EB)635 static bool classof(const Expression *EB) { 636 return EB->getExpressionType() == ET_Unknown; 637 } 638 getInstruction()639 Instruction *getInstruction() const { return Inst; } setInstruction(Instruction * I)640 void setInstruction(Instruction *I) { Inst = I; } 641 equals(const Expression & Other)642 bool equals(const Expression &Other) const override { 643 const auto &OU = cast<UnknownExpression>(Other); 644 return Inst == OU.Inst; 645 } 646 getHashValue()647 hash_code getHashValue() const override { 648 return hash_combine(this->Expression::getHashValue(), Inst); 649 } 650 651 // Debugging support printInternal(raw_ostream & OS,bool PrintEType)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 665