10b57cec5SDimitry Andric //===- GVNExpression.h - GVN Expression classes -----------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// 110b57cec5SDimitry Andric /// The header file for the GVN pass that contains expression handling 120b57cec5SDimitry Andric /// classes 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #ifndef LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H 170b57cec5SDimitry Andric #define LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "llvm/ADT/Hashing.h" 200b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 210b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSA.h" 220b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 230b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 240b57cec5SDimitry Andric #include "llvm/IR/Value.h" 250b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 260b57cec5SDimitry Andric #include "llvm/Support/ArrayRecycler.h" 270b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 280b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric #include <algorithm> 310b57cec5SDimitry Andric #include <cassert> 320b57cec5SDimitry Andric #include <iterator> 330b57cec5SDimitry Andric #include <utility> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric namespace llvm { 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric class BasicBlock; 380b57cec5SDimitry Andric class Type; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric namespace GVNExpression { 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric enum ExpressionType { 430b57cec5SDimitry Andric ET_Base, 440b57cec5SDimitry Andric ET_Constant, 450b57cec5SDimitry Andric ET_Variable, 460b57cec5SDimitry Andric ET_Dead, 470b57cec5SDimitry Andric ET_Unknown, 480b57cec5SDimitry Andric ET_BasicStart, 490b57cec5SDimitry Andric ET_Basic, 500b57cec5SDimitry Andric ET_AggregateValue, 510b57cec5SDimitry Andric ET_Phi, 520b57cec5SDimitry Andric ET_MemoryStart, 530b57cec5SDimitry Andric ET_Call, 540b57cec5SDimitry Andric ET_Load, 550b57cec5SDimitry Andric ET_Store, 560b57cec5SDimitry Andric ET_MemoryEnd, 570b57cec5SDimitry Andric ET_BasicEnd 580b57cec5SDimitry Andric }; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric class Expression { 610b57cec5SDimitry Andric private: 620b57cec5SDimitry Andric ExpressionType EType; 630b57cec5SDimitry Andric unsigned Opcode; 640b57cec5SDimitry Andric mutable hash_code HashVal = 0; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric public: 670b57cec5SDimitry Andric Expression(ExpressionType ET = ET_Base, unsigned O = ~2U) EType(ET)680b57cec5SDimitry Andric : EType(ET), Opcode(O) {} 690b57cec5SDimitry Andric Expression(const Expression &) = delete; 700b57cec5SDimitry Andric Expression &operator=(const Expression &) = delete; 710b57cec5SDimitry Andric virtual ~Expression(); 720b57cec5SDimitry Andric getEmptyKey()730b57cec5SDimitry Andric static unsigned getEmptyKey() { return ~0U; } getTombstoneKey()740b57cec5SDimitry Andric static unsigned getTombstoneKey() { return ~1U; } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric bool operator!=(const Expression &Other) const { return !(*this == Other); } 770b57cec5SDimitry Andric bool operator==(const Expression &Other) const { 780b57cec5SDimitry Andric if (getOpcode() != Other.getOpcode()) 790b57cec5SDimitry Andric return false; 800b57cec5SDimitry Andric if (getOpcode() == getEmptyKey() || getOpcode() == getTombstoneKey()) 810b57cec5SDimitry Andric return true; 820b57cec5SDimitry Andric // Compare the expression type for anything but load and store. 830b57cec5SDimitry Andric // For load and store we set the opcode to zero to make them equal. 840b57cec5SDimitry Andric if (getExpressionType() != ET_Load && getExpressionType() != ET_Store && 850b57cec5SDimitry Andric getExpressionType() != Other.getExpressionType()) 860b57cec5SDimitry Andric return false; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric return equals(Other); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric getComputedHash()910b57cec5SDimitry Andric hash_code getComputedHash() const { 920b57cec5SDimitry Andric // It's theoretically possible for a thing to hash to zero. In that case, 930b57cec5SDimitry Andric // we will just compute the hash a few extra times, which is no worse that 940b57cec5SDimitry Andric // we did before, which was to compute it always. 950b57cec5SDimitry Andric if (static_cast<unsigned>(HashVal) == 0) 960b57cec5SDimitry Andric HashVal = getHashValue(); 970b57cec5SDimitry Andric return HashVal; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric equals(const Expression & Other)1000b57cec5SDimitry Andric virtual bool equals(const Expression &Other) const { return true; } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Return true if the two expressions are exactly the same, including the 1030b57cec5SDimitry Andric // normally ignored fields. exactlyEquals(const Expression & Other)1040b57cec5SDimitry Andric virtual bool exactlyEquals(const Expression &Other) const { 1050b57cec5SDimitry Andric return getExpressionType() == Other.getExpressionType() && equals(Other); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric getOpcode()1080b57cec5SDimitry Andric unsigned getOpcode() const { return Opcode; } setOpcode(unsigned opcode)1090b57cec5SDimitry Andric void setOpcode(unsigned opcode) { Opcode = opcode; } getExpressionType()1100b57cec5SDimitry Andric ExpressionType getExpressionType() const { return EType; } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // We deliberately leave the expression type out of the hash value. getHashValue()1130b57cec5SDimitry Andric virtual hash_code getHashValue() const { return getOpcode(); } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)1160b57cec5SDimitry Andric virtual void printInternal(raw_ostream &OS, bool PrintEType) const { 1170b57cec5SDimitry Andric if (PrintEType) 1180b57cec5SDimitry Andric OS << "etype = " << getExpressionType() << ","; 1190b57cec5SDimitry Andric OS << "opcode = " << getOpcode() << ", "; 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric print(raw_ostream & OS)1220b57cec5SDimitry Andric void print(raw_ostream &OS) const { 1230b57cec5SDimitry Andric OS << "{ "; 1240b57cec5SDimitry Andric printInternal(OS, true); 1250b57cec5SDimitry Andric OS << "}"; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric LLVM_DUMP_METHOD void dump() const; 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const Expression &E) { 1320b57cec5SDimitry Andric E.print(OS); 1330b57cec5SDimitry Andric return OS; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric class BasicExpression : public Expression { 1370b57cec5SDimitry Andric private: 1380b57cec5SDimitry Andric using RecyclerType = ArrayRecycler<Value *>; 1390b57cec5SDimitry Andric using RecyclerCapacity = RecyclerType::Capacity; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric Value **Operands = nullptr; 1420b57cec5SDimitry Andric unsigned MaxOperands; 1430b57cec5SDimitry Andric unsigned NumOperands = 0; 1440b57cec5SDimitry Andric Type *ValueType = nullptr; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric public: BasicExpression(unsigned NumOperands)1470b57cec5SDimitry Andric BasicExpression(unsigned NumOperands) 1480b57cec5SDimitry Andric : BasicExpression(NumOperands, ET_Basic) {} BasicExpression(unsigned NumOperands,ExpressionType ET)1490b57cec5SDimitry Andric BasicExpression(unsigned NumOperands, ExpressionType ET) 1500b57cec5SDimitry Andric : Expression(ET), MaxOperands(NumOperands) {} 1510b57cec5SDimitry Andric BasicExpression() = delete; 1520b57cec5SDimitry Andric BasicExpression(const BasicExpression &) = delete; 1530b57cec5SDimitry Andric BasicExpression &operator=(const BasicExpression &) = delete; 1540b57cec5SDimitry Andric ~BasicExpression() override; 1550b57cec5SDimitry Andric classof(const Expression * EB)1560b57cec5SDimitry Andric static bool classof(const Expression *EB) { 1570b57cec5SDimitry Andric ExpressionType ET = EB->getExpressionType(); 1580b57cec5SDimitry Andric return ET > ET_BasicStart && ET < ET_BasicEnd; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric /// Swap two operands. Used during GVN to put commutative operands in 1620b57cec5SDimitry Andric /// order. swapOperands(unsigned First,unsigned Second)1630b57cec5SDimitry Andric void swapOperands(unsigned First, unsigned Second) { 1640b57cec5SDimitry Andric std::swap(Operands[First], Operands[Second]); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric getOperand(unsigned N)1670b57cec5SDimitry Andric Value *getOperand(unsigned N) const { 1680b57cec5SDimitry Andric assert(Operands && "Operands not allocated"); 1690b57cec5SDimitry Andric assert(N < NumOperands && "Operand out of range"); 1700b57cec5SDimitry Andric return Operands[N]; 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric setOperand(unsigned N,Value * V)1730b57cec5SDimitry Andric void setOperand(unsigned N, Value *V) { 1740b57cec5SDimitry Andric assert(Operands && "Operands not allocated before setting"); 1750b57cec5SDimitry Andric assert(N < NumOperands && "Operand out of range"); 1760b57cec5SDimitry Andric Operands[N] = V; 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric getNumOperands()1790b57cec5SDimitry Andric unsigned getNumOperands() const { return NumOperands; } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric using op_iterator = Value **; 1820b57cec5SDimitry Andric using const_op_iterator = Value *const *; 1830b57cec5SDimitry Andric op_begin()1840b57cec5SDimitry Andric op_iterator op_begin() { return Operands; } op_end()1850b57cec5SDimitry Andric op_iterator op_end() { return Operands + NumOperands; } op_begin()1860b57cec5SDimitry Andric const_op_iterator op_begin() const { return Operands; } op_end()1870b57cec5SDimitry Andric const_op_iterator op_end() const { return Operands + NumOperands; } operands()1880b57cec5SDimitry Andric iterator_range<op_iterator> operands() { 1890b57cec5SDimitry Andric return iterator_range<op_iterator>(op_begin(), op_end()); 1900b57cec5SDimitry Andric } operands()1910b57cec5SDimitry Andric iterator_range<const_op_iterator> operands() const { 1920b57cec5SDimitry Andric return iterator_range<const_op_iterator>(op_begin(), op_end()); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric op_push_back(Value * Arg)1950b57cec5SDimitry Andric void op_push_back(Value *Arg) { 1960b57cec5SDimitry Andric assert(NumOperands < MaxOperands && "Tried to add too many operands"); 1970b57cec5SDimitry Andric assert(Operands && "Operandss not allocated before pushing"); 1980b57cec5SDimitry Andric Operands[NumOperands++] = Arg; 1990b57cec5SDimitry Andric } op_empty()2000b57cec5SDimitry Andric bool op_empty() const { return getNumOperands() == 0; } 2010b57cec5SDimitry Andric allocateOperands(RecyclerType & Recycler,BumpPtrAllocator & Allocator)2020b57cec5SDimitry Andric void allocateOperands(RecyclerType &Recycler, BumpPtrAllocator &Allocator) { 2030b57cec5SDimitry Andric assert(!Operands && "Operands already allocated"); 2040b57cec5SDimitry Andric Operands = Recycler.allocate(RecyclerCapacity::get(MaxOperands), Allocator); 2050b57cec5SDimitry Andric } deallocateOperands(RecyclerType & Recycler)2060b57cec5SDimitry Andric void deallocateOperands(RecyclerType &Recycler) { 2070b57cec5SDimitry Andric Recycler.deallocate(RecyclerCapacity::get(MaxOperands), Operands); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric setType(Type * T)2100b57cec5SDimitry Andric void setType(Type *T) { ValueType = T; } getType()2110b57cec5SDimitry Andric Type *getType() const { return ValueType; } 2120b57cec5SDimitry Andric equals(const Expression & Other)2130b57cec5SDimitry Andric bool equals(const Expression &Other) const override { 2140b57cec5SDimitry Andric if (getOpcode() != Other.getOpcode()) 2150b57cec5SDimitry Andric return false; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric const auto &OE = cast<BasicExpression>(Other); 2180b57cec5SDimitry Andric return getType() == OE.getType() && NumOperands == OE.NumOperands && 2190b57cec5SDimitry Andric std::equal(op_begin(), op_end(), OE.op_begin()); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric getHashValue()2220b57cec5SDimitry Andric hash_code getHashValue() const override { 2230b57cec5SDimitry Andric return hash_combine(this->Expression::getHashValue(), ValueType, 2240b57cec5SDimitry Andric hash_combine_range(op_begin(), op_end())); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)2280b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 2290b57cec5SDimitry Andric if (PrintEType) 2300b57cec5SDimitry Andric OS << "ExpressionTypeBasic, "; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric this->Expression::printInternal(OS, false); 2330b57cec5SDimitry Andric OS << "operands = {"; 2340b57cec5SDimitry Andric for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { 2350b57cec5SDimitry Andric OS << "[" << i << "] = "; 2360b57cec5SDimitry Andric Operands[i]->printAsOperand(OS); 2370b57cec5SDimitry Andric OS << " "; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric OS << "} "; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric }; 2420b57cec5SDimitry Andric 243*fe6060f1SDimitry Andric class op_inserter { 2440b57cec5SDimitry Andric private: 2450b57cec5SDimitry Andric using Container = BasicExpression; 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric Container *BE; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric public: 250*fe6060f1SDimitry Andric using iterator_category = std::output_iterator_tag; 251*fe6060f1SDimitry Andric using value_type = void; 252*fe6060f1SDimitry Andric using difference_type = void; 253*fe6060f1SDimitry Andric using pointer = void; 254*fe6060f1SDimitry Andric using reference = void; 255*fe6060f1SDimitry Andric op_inserter(BasicExpression & E)2560b57cec5SDimitry Andric explicit op_inserter(BasicExpression &E) : BE(&E) {} op_inserter(BasicExpression * E)2570b57cec5SDimitry Andric explicit op_inserter(BasicExpression *E) : BE(E) {} 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric op_inserter &operator=(Value *val) { 2600b57cec5SDimitry Andric BE->op_push_back(val); 2610b57cec5SDimitry Andric return *this; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric op_inserter &operator*() { return *this; } 2640b57cec5SDimitry Andric op_inserter &operator++() { return *this; } 2650b57cec5SDimitry Andric op_inserter &operator++(int) { return *this; } 2660b57cec5SDimitry Andric }; 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric class MemoryExpression : public BasicExpression { 2690b57cec5SDimitry Andric private: 2700b57cec5SDimitry Andric const MemoryAccess *MemoryLeader; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric public: MemoryExpression(unsigned NumOperands,enum ExpressionType EType,const MemoryAccess * MemoryLeader)2730b57cec5SDimitry Andric MemoryExpression(unsigned NumOperands, enum ExpressionType EType, 2740b57cec5SDimitry Andric const MemoryAccess *MemoryLeader) 2750b57cec5SDimitry Andric : BasicExpression(NumOperands, EType), MemoryLeader(MemoryLeader) {} 2760b57cec5SDimitry Andric MemoryExpression() = delete; 2770b57cec5SDimitry Andric MemoryExpression(const MemoryExpression &) = delete; 2780b57cec5SDimitry Andric MemoryExpression &operator=(const MemoryExpression &) = delete; 2790b57cec5SDimitry Andric classof(const Expression * EB)2800b57cec5SDimitry Andric static bool classof(const Expression *EB) { 2810b57cec5SDimitry Andric return EB->getExpressionType() > ET_MemoryStart && 2820b57cec5SDimitry Andric EB->getExpressionType() < ET_MemoryEnd; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric getHashValue()2850b57cec5SDimitry Andric hash_code getHashValue() const override { 2860b57cec5SDimitry Andric return hash_combine(this->BasicExpression::getHashValue(), MemoryLeader); 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric equals(const Expression & Other)2890b57cec5SDimitry Andric bool equals(const Expression &Other) const override { 2900b57cec5SDimitry Andric if (!this->BasicExpression::equals(Other)) 2910b57cec5SDimitry Andric return false; 2920b57cec5SDimitry Andric const MemoryExpression &OtherMCE = cast<MemoryExpression>(Other); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric return MemoryLeader == OtherMCE.MemoryLeader; 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric getMemoryLeader()2970b57cec5SDimitry Andric const MemoryAccess *getMemoryLeader() const { return MemoryLeader; } setMemoryLeader(const MemoryAccess * ML)2980b57cec5SDimitry Andric void setMemoryLeader(const MemoryAccess *ML) { MemoryLeader = ML; } 2990b57cec5SDimitry Andric }; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric class CallExpression final : public MemoryExpression { 3020b57cec5SDimitry Andric private: 3030b57cec5SDimitry Andric CallInst *Call; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric public: CallExpression(unsigned NumOperands,CallInst * C,const MemoryAccess * MemoryLeader)3060b57cec5SDimitry Andric CallExpression(unsigned NumOperands, CallInst *C, 3070b57cec5SDimitry Andric const MemoryAccess *MemoryLeader) 3080b57cec5SDimitry Andric : MemoryExpression(NumOperands, ET_Call, MemoryLeader), Call(C) {} 3090b57cec5SDimitry Andric CallExpression() = delete; 3100b57cec5SDimitry Andric CallExpression(const CallExpression &) = delete; 3110b57cec5SDimitry Andric CallExpression &operator=(const CallExpression &) = delete; 3120b57cec5SDimitry Andric ~CallExpression() override; 3130b57cec5SDimitry Andric classof(const Expression * EB)3140b57cec5SDimitry Andric static bool classof(const Expression *EB) { 3150b57cec5SDimitry Andric return EB->getExpressionType() == ET_Call; 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)3190b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 3200b57cec5SDimitry Andric if (PrintEType) 3210b57cec5SDimitry Andric OS << "ExpressionTypeCall, "; 3220b57cec5SDimitry Andric this->BasicExpression::printInternal(OS, false); 3230b57cec5SDimitry Andric OS << " represents call at "; 3240b57cec5SDimitry Andric Call->printAsOperand(OS); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric }; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric class LoadExpression final : public MemoryExpression { 3290b57cec5SDimitry Andric private: 3300b57cec5SDimitry Andric LoadInst *Load; 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric public: LoadExpression(unsigned NumOperands,LoadInst * L,const MemoryAccess * MemoryLeader)3330b57cec5SDimitry Andric LoadExpression(unsigned NumOperands, LoadInst *L, 3340b57cec5SDimitry Andric const MemoryAccess *MemoryLeader) 3350b57cec5SDimitry Andric : LoadExpression(ET_Load, NumOperands, L, MemoryLeader) {} 3360b57cec5SDimitry Andric LoadExpression(enum ExpressionType EType,unsigned NumOperands,LoadInst * L,const MemoryAccess * MemoryLeader)3370b57cec5SDimitry Andric LoadExpression(enum ExpressionType EType, unsigned NumOperands, LoadInst *L, 3380b57cec5SDimitry Andric const MemoryAccess *MemoryLeader) 3395ffd83dbSDimitry Andric : MemoryExpression(NumOperands, EType, MemoryLeader), Load(L) {} 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric LoadExpression() = delete; 3420b57cec5SDimitry Andric LoadExpression(const LoadExpression &) = delete; 3430b57cec5SDimitry Andric LoadExpression &operator=(const LoadExpression &) = delete; 3440b57cec5SDimitry Andric ~LoadExpression() override; 3450b57cec5SDimitry Andric classof(const Expression * EB)3460b57cec5SDimitry Andric static bool classof(const Expression *EB) { 3470b57cec5SDimitry Andric return EB->getExpressionType() == ET_Load; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric getLoadInst()3500b57cec5SDimitry Andric LoadInst *getLoadInst() const { return Load; } setLoadInst(LoadInst * L)3510b57cec5SDimitry Andric void setLoadInst(LoadInst *L) { Load = L; } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric bool equals(const Expression &Other) const override; exactlyEquals(const Expression & Other)3540b57cec5SDimitry Andric bool exactlyEquals(const Expression &Other) const override { 3550b57cec5SDimitry Andric return Expression::exactlyEquals(Other) && 3560b57cec5SDimitry Andric cast<LoadExpression>(Other).getLoadInst() == getLoadInst(); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)3600b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 3610b57cec5SDimitry Andric if (PrintEType) 3620b57cec5SDimitry Andric OS << "ExpressionTypeLoad, "; 3630b57cec5SDimitry Andric this->BasicExpression::printInternal(OS, false); 3640b57cec5SDimitry Andric OS << " represents Load at "; 3650b57cec5SDimitry Andric Load->printAsOperand(OS); 3660b57cec5SDimitry Andric OS << " with MemoryLeader " << *getMemoryLeader(); 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric }; 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric class StoreExpression final : public MemoryExpression { 3710b57cec5SDimitry Andric private: 3720b57cec5SDimitry Andric StoreInst *Store; 3730b57cec5SDimitry Andric Value *StoredValue; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric public: StoreExpression(unsigned NumOperands,StoreInst * S,Value * StoredValue,const MemoryAccess * MemoryLeader)3760b57cec5SDimitry Andric StoreExpression(unsigned NumOperands, StoreInst *S, Value *StoredValue, 3770b57cec5SDimitry Andric const MemoryAccess *MemoryLeader) 3780b57cec5SDimitry Andric : MemoryExpression(NumOperands, ET_Store, MemoryLeader), Store(S), 3790b57cec5SDimitry Andric StoredValue(StoredValue) {} 3800b57cec5SDimitry Andric StoreExpression() = delete; 3810b57cec5SDimitry Andric StoreExpression(const StoreExpression &) = delete; 3820b57cec5SDimitry Andric StoreExpression &operator=(const StoreExpression &) = delete; 3830b57cec5SDimitry Andric ~StoreExpression() override; 3840b57cec5SDimitry Andric classof(const Expression * EB)3850b57cec5SDimitry Andric static bool classof(const Expression *EB) { 3860b57cec5SDimitry Andric return EB->getExpressionType() == ET_Store; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric getStoreInst()3890b57cec5SDimitry Andric StoreInst *getStoreInst() const { return Store; } getStoredValue()3900b57cec5SDimitry Andric Value *getStoredValue() const { return StoredValue; } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric bool equals(const Expression &Other) const override; 3930b57cec5SDimitry Andric exactlyEquals(const Expression & Other)3940b57cec5SDimitry Andric bool exactlyEquals(const Expression &Other) const override { 3950b57cec5SDimitry Andric return Expression::exactlyEquals(Other) && 3960b57cec5SDimitry Andric cast<StoreExpression>(Other).getStoreInst() == getStoreInst(); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)4000b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 4010b57cec5SDimitry Andric if (PrintEType) 4020b57cec5SDimitry Andric OS << "ExpressionTypeStore, "; 4030b57cec5SDimitry Andric this->BasicExpression::printInternal(OS, false); 4040b57cec5SDimitry Andric OS << " represents Store " << *Store; 4050b57cec5SDimitry Andric OS << " with StoredValue "; 4060b57cec5SDimitry Andric StoredValue->printAsOperand(OS); 4070b57cec5SDimitry Andric OS << " and MemoryLeader " << *getMemoryLeader(); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric }; 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric class AggregateValueExpression final : public BasicExpression { 4120b57cec5SDimitry Andric private: 4130b57cec5SDimitry Andric unsigned MaxIntOperands; 4140b57cec5SDimitry Andric unsigned NumIntOperands = 0; 4150b57cec5SDimitry Andric unsigned *IntOperands = nullptr; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric public: AggregateValueExpression(unsigned NumOperands,unsigned NumIntOperands)4180b57cec5SDimitry Andric AggregateValueExpression(unsigned NumOperands, unsigned NumIntOperands) 4190b57cec5SDimitry Andric : BasicExpression(NumOperands, ET_AggregateValue), 4200b57cec5SDimitry Andric MaxIntOperands(NumIntOperands) {} 4210b57cec5SDimitry Andric AggregateValueExpression() = delete; 4220b57cec5SDimitry Andric AggregateValueExpression(const AggregateValueExpression &) = delete; 4230b57cec5SDimitry Andric AggregateValueExpression & 4240b57cec5SDimitry Andric operator=(const AggregateValueExpression &) = delete; 4250b57cec5SDimitry Andric ~AggregateValueExpression() override; 4260b57cec5SDimitry Andric classof(const Expression * EB)4270b57cec5SDimitry Andric static bool classof(const Expression *EB) { 4280b57cec5SDimitry Andric return EB->getExpressionType() == ET_AggregateValue; 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric using int_arg_iterator = unsigned *; 4320b57cec5SDimitry Andric using const_int_arg_iterator = const unsigned *; 4330b57cec5SDimitry Andric int_op_begin()4340b57cec5SDimitry Andric int_arg_iterator int_op_begin() { return IntOperands; } int_op_end()4350b57cec5SDimitry Andric int_arg_iterator int_op_end() { return IntOperands + NumIntOperands; } int_op_begin()4360b57cec5SDimitry Andric const_int_arg_iterator int_op_begin() const { return IntOperands; } int_op_end()4370b57cec5SDimitry Andric const_int_arg_iterator int_op_end() const { 4380b57cec5SDimitry Andric return IntOperands + NumIntOperands; 4390b57cec5SDimitry Andric } int_op_size()4400b57cec5SDimitry Andric unsigned int_op_size() const { return NumIntOperands; } int_op_empty()4410b57cec5SDimitry Andric bool int_op_empty() const { return NumIntOperands == 0; } int_op_push_back(unsigned IntOperand)4420b57cec5SDimitry Andric void int_op_push_back(unsigned IntOperand) { 4430b57cec5SDimitry Andric assert(NumIntOperands < MaxIntOperands && 4440b57cec5SDimitry Andric "Tried to add too many int operands"); 4450b57cec5SDimitry Andric assert(IntOperands && "Operands not allocated before pushing"); 4460b57cec5SDimitry Andric IntOperands[NumIntOperands++] = IntOperand; 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric allocateIntOperands(BumpPtrAllocator & Allocator)4490b57cec5SDimitry Andric virtual void allocateIntOperands(BumpPtrAllocator &Allocator) { 4500b57cec5SDimitry Andric assert(!IntOperands && "Operands already allocated"); 4510b57cec5SDimitry Andric IntOperands = Allocator.Allocate<unsigned>(MaxIntOperands); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric equals(const Expression & Other)4540b57cec5SDimitry Andric bool equals(const Expression &Other) const override { 4550b57cec5SDimitry Andric if (!this->BasicExpression::equals(Other)) 4560b57cec5SDimitry Andric return false; 4570b57cec5SDimitry Andric const AggregateValueExpression &OE = cast<AggregateValueExpression>(Other); 4580b57cec5SDimitry Andric return NumIntOperands == OE.NumIntOperands && 4590b57cec5SDimitry Andric std::equal(int_op_begin(), int_op_end(), OE.int_op_begin()); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric getHashValue()4620b57cec5SDimitry Andric hash_code getHashValue() const override { 4630b57cec5SDimitry Andric return hash_combine(this->BasicExpression::getHashValue(), 4640b57cec5SDimitry Andric hash_combine_range(int_op_begin(), int_op_end())); 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)4680b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 4690b57cec5SDimitry Andric if (PrintEType) 4700b57cec5SDimitry Andric OS << "ExpressionTypeAggregateValue, "; 4710b57cec5SDimitry Andric this->BasicExpression::printInternal(OS, false); 4720b57cec5SDimitry Andric OS << ", intoperands = {"; 4730b57cec5SDimitry Andric for (unsigned i = 0, e = int_op_size(); i != e; ++i) { 4740b57cec5SDimitry Andric OS << "[" << i << "] = " << IntOperands[i] << " "; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric OS << "}"; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric }; 4790b57cec5SDimitry Andric 480*fe6060f1SDimitry Andric class int_op_inserter { 4810b57cec5SDimitry Andric private: 4820b57cec5SDimitry Andric using Container = AggregateValueExpression; 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric Container *AVE; 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric public: 487*fe6060f1SDimitry Andric using iterator_category = std::output_iterator_tag; 488*fe6060f1SDimitry Andric using value_type = void; 489*fe6060f1SDimitry Andric using difference_type = void; 490*fe6060f1SDimitry Andric using pointer = void; 491*fe6060f1SDimitry Andric using reference = void; 492*fe6060f1SDimitry Andric int_op_inserter(AggregateValueExpression & E)4930b57cec5SDimitry Andric explicit int_op_inserter(AggregateValueExpression &E) : AVE(&E) {} int_op_inserter(AggregateValueExpression * E)4940b57cec5SDimitry Andric explicit int_op_inserter(AggregateValueExpression *E) : AVE(E) {} 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric int_op_inserter &operator=(unsigned int val) { 4970b57cec5SDimitry Andric AVE->int_op_push_back(val); 4980b57cec5SDimitry Andric return *this; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric int_op_inserter &operator*() { return *this; } 5010b57cec5SDimitry Andric int_op_inserter &operator++() { return *this; } 5020b57cec5SDimitry Andric int_op_inserter &operator++(int) { return *this; } 5030b57cec5SDimitry Andric }; 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric class PHIExpression final : public BasicExpression { 5060b57cec5SDimitry Andric private: 5070b57cec5SDimitry Andric BasicBlock *BB; 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric public: PHIExpression(unsigned NumOperands,BasicBlock * B)5100b57cec5SDimitry Andric PHIExpression(unsigned NumOperands, BasicBlock *B) 5110b57cec5SDimitry Andric : BasicExpression(NumOperands, ET_Phi), BB(B) {} 5120b57cec5SDimitry Andric PHIExpression() = delete; 5130b57cec5SDimitry Andric PHIExpression(const PHIExpression &) = delete; 5140b57cec5SDimitry Andric PHIExpression &operator=(const PHIExpression &) = delete; 5150b57cec5SDimitry Andric ~PHIExpression() override; 5160b57cec5SDimitry Andric classof(const Expression * EB)5170b57cec5SDimitry Andric static bool classof(const Expression *EB) { 5180b57cec5SDimitry Andric return EB->getExpressionType() == ET_Phi; 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric equals(const Expression & Other)5210b57cec5SDimitry Andric bool equals(const Expression &Other) const override { 5220b57cec5SDimitry Andric if (!this->BasicExpression::equals(Other)) 5230b57cec5SDimitry Andric return false; 5240b57cec5SDimitry Andric const PHIExpression &OE = cast<PHIExpression>(Other); 5250b57cec5SDimitry Andric return BB == OE.BB; 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric getHashValue()5280b57cec5SDimitry Andric hash_code getHashValue() const override { 5290b57cec5SDimitry Andric return hash_combine(this->BasicExpression::getHashValue(), BB); 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)5330b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 5340b57cec5SDimitry Andric if (PrintEType) 5350b57cec5SDimitry Andric OS << "ExpressionTypePhi, "; 5360b57cec5SDimitry Andric this->BasicExpression::printInternal(OS, false); 5370b57cec5SDimitry Andric OS << "bb = " << BB; 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric }; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric class DeadExpression final : public Expression { 5420b57cec5SDimitry Andric public: DeadExpression()5430b57cec5SDimitry Andric DeadExpression() : Expression(ET_Dead) {} 5440b57cec5SDimitry Andric DeadExpression(const DeadExpression &) = delete; 5450b57cec5SDimitry Andric DeadExpression &operator=(const DeadExpression &) = delete; 5460b57cec5SDimitry Andric classof(const Expression * E)5470b57cec5SDimitry Andric static bool classof(const Expression *E) { 5480b57cec5SDimitry Andric return E->getExpressionType() == ET_Dead; 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric }; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric class VariableExpression final : public Expression { 5530b57cec5SDimitry Andric private: 5540b57cec5SDimitry Andric Value *VariableValue; 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric public: VariableExpression(Value * V)5570b57cec5SDimitry Andric VariableExpression(Value *V) : Expression(ET_Variable), VariableValue(V) {} 5580b57cec5SDimitry Andric VariableExpression() = delete; 5590b57cec5SDimitry Andric VariableExpression(const VariableExpression &) = delete; 5600b57cec5SDimitry Andric VariableExpression &operator=(const VariableExpression &) = delete; 5610b57cec5SDimitry Andric classof(const Expression * EB)5620b57cec5SDimitry Andric static bool classof(const Expression *EB) { 5630b57cec5SDimitry Andric return EB->getExpressionType() == ET_Variable; 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric getVariableValue()5660b57cec5SDimitry Andric Value *getVariableValue() const { return VariableValue; } setVariableValue(Value * V)5670b57cec5SDimitry Andric void setVariableValue(Value *V) { VariableValue = V; } 5680b57cec5SDimitry Andric equals(const Expression & Other)5690b57cec5SDimitry Andric bool equals(const Expression &Other) const override { 5700b57cec5SDimitry Andric const VariableExpression &OC = cast<VariableExpression>(Other); 5710b57cec5SDimitry Andric return VariableValue == OC.VariableValue; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric getHashValue()5740b57cec5SDimitry Andric hash_code getHashValue() const override { 5750b57cec5SDimitry Andric return hash_combine(this->Expression::getHashValue(), 5760b57cec5SDimitry Andric VariableValue->getType(), VariableValue); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)5800b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 5810b57cec5SDimitry Andric if (PrintEType) 5820b57cec5SDimitry Andric OS << "ExpressionTypeVariable, "; 5830b57cec5SDimitry Andric this->Expression::printInternal(OS, false); 5840b57cec5SDimitry Andric OS << " variable = " << *VariableValue; 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric }; 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric class ConstantExpression final : public Expression { 5890b57cec5SDimitry Andric private: 5900b57cec5SDimitry Andric Constant *ConstantValue = nullptr; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric public: ConstantExpression()5930b57cec5SDimitry Andric ConstantExpression() : Expression(ET_Constant) {} ConstantExpression(Constant * constantValue)5940b57cec5SDimitry Andric ConstantExpression(Constant *constantValue) 5950b57cec5SDimitry Andric : Expression(ET_Constant), ConstantValue(constantValue) {} 5960b57cec5SDimitry Andric ConstantExpression(const ConstantExpression &) = delete; 5970b57cec5SDimitry Andric ConstantExpression &operator=(const ConstantExpression &) = delete; 5980b57cec5SDimitry Andric classof(const Expression * EB)5990b57cec5SDimitry Andric static bool classof(const Expression *EB) { 6000b57cec5SDimitry Andric return EB->getExpressionType() == ET_Constant; 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric getConstantValue()6030b57cec5SDimitry Andric Constant *getConstantValue() const { return ConstantValue; } setConstantValue(Constant * V)6040b57cec5SDimitry Andric void setConstantValue(Constant *V) { ConstantValue = V; } 6050b57cec5SDimitry Andric equals(const Expression & Other)6060b57cec5SDimitry Andric bool equals(const Expression &Other) const override { 6070b57cec5SDimitry Andric const ConstantExpression &OC = cast<ConstantExpression>(Other); 6080b57cec5SDimitry Andric return ConstantValue == OC.ConstantValue; 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric getHashValue()6110b57cec5SDimitry Andric hash_code getHashValue() const override { 6120b57cec5SDimitry Andric return hash_combine(this->Expression::getHashValue(), 6130b57cec5SDimitry Andric ConstantValue->getType(), ConstantValue); 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)6170b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 6180b57cec5SDimitry Andric if (PrintEType) 6190b57cec5SDimitry Andric OS << "ExpressionTypeConstant, "; 6200b57cec5SDimitry Andric this->Expression::printInternal(OS, false); 6210b57cec5SDimitry Andric OS << " constant = " << *ConstantValue; 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric }; 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric class UnknownExpression final : public Expression { 6260b57cec5SDimitry Andric private: 6270b57cec5SDimitry Andric Instruction *Inst; 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric public: UnknownExpression(Instruction * I)6300b57cec5SDimitry Andric UnknownExpression(Instruction *I) : Expression(ET_Unknown), Inst(I) {} 6310b57cec5SDimitry Andric UnknownExpression() = delete; 6320b57cec5SDimitry Andric UnknownExpression(const UnknownExpression &) = delete; 6330b57cec5SDimitry Andric UnknownExpression &operator=(const UnknownExpression &) = delete; 6340b57cec5SDimitry Andric classof(const Expression * EB)6350b57cec5SDimitry Andric static bool classof(const Expression *EB) { 6360b57cec5SDimitry Andric return EB->getExpressionType() == ET_Unknown; 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric getInstruction()6390b57cec5SDimitry Andric Instruction *getInstruction() const { return Inst; } setInstruction(Instruction * I)6400b57cec5SDimitry Andric void setInstruction(Instruction *I) { Inst = I; } 6410b57cec5SDimitry Andric equals(const Expression & Other)6420b57cec5SDimitry Andric bool equals(const Expression &Other) const override { 6430b57cec5SDimitry Andric const auto &OU = cast<UnknownExpression>(Other); 6440b57cec5SDimitry Andric return Inst == OU.Inst; 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric getHashValue()6470b57cec5SDimitry Andric hash_code getHashValue() const override { 6480b57cec5SDimitry Andric return hash_combine(this->Expression::getHashValue(), Inst); 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric // Debugging support printInternal(raw_ostream & OS,bool PrintEType)6520b57cec5SDimitry Andric void printInternal(raw_ostream &OS, bool PrintEType) const override { 6530b57cec5SDimitry Andric if (PrintEType) 6540b57cec5SDimitry Andric OS << "ExpressionTypeUnknown, "; 6550b57cec5SDimitry Andric this->Expression::printInternal(OS, false); 6560b57cec5SDimitry Andric OS << " inst = " << *Inst; 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric }; 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric } // end namespace GVNExpression 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric } // end namespace llvm 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric #endif // LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H 665