1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// 2*03ce13f7SAndroid Build Coastguard Worker // 3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator 4*03ce13f7SAndroid Build Coastguard Worker // 5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker /// 10*03ce13f7SAndroid Build Coastguard Worker /// \file 11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the Inst class and its target-independent subclasses. 12*03ce13f7SAndroid Build Coastguard Worker /// 13*03ce13f7SAndroid Build Coastguard Worker /// These represent the high-level Vanilla ICE instructions and map roughly 1:1 14*03ce13f7SAndroid Build Coastguard Worker /// to LLVM instructions. 15*03ce13f7SAndroid Build Coastguard Worker /// 16*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 17*03ce13f7SAndroid Build Coastguard Worker 18*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEINST_H 19*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEINST_H 20*03ce13f7SAndroid Build Coastguard Worker 21*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h" 22*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 23*03ce13f7SAndroid Build Coastguard Worker #include "IceInst.def" 24*03ce13f7SAndroid Build Coastguard Worker #include "IceIntrinsics.h" 25*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h" 26*03ce13f7SAndroid Build Coastguard Worker #include "IceSwitchLowering.h" 27*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h" 28*03ce13f7SAndroid Build Coastguard Worker 29*03ce13f7SAndroid Build Coastguard Worker // TODO: The Cfg structure, and instructions in particular, need to be 30*03ce13f7SAndroid Build Coastguard Worker // validated for things like valid operand types, valid branch targets, proper 31*03ce13f7SAndroid Build Coastguard Worker // ordering of Phi and non-Phi instructions, etc. Most of the validity checking 32*03ce13f7SAndroid Build Coastguard Worker // will be done in the bitcode reader. We need a list of everything that should 33*03ce13f7SAndroid Build Coastguard Worker // be validated, and tests for each. 34*03ce13f7SAndroid Build Coastguard Worker 35*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 36*03ce13f7SAndroid Build Coastguard Worker 37*03ce13f7SAndroid Build Coastguard Worker /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and 38*03ce13f7SAndroid Build Coastguard Worker /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and 39*03ce13f7SAndroid Build Coastguard Worker /// low-level (target-specific) ICE instructions inherit from InstTarget. 40*03ce13f7SAndroid Build Coastguard Worker class Inst : public llvm::ilist_node<Inst> { 41*03ce13f7SAndroid Build Coastguard Worker Inst() = delete; 42*03ce13f7SAndroid Build Coastguard Worker Inst(const Inst &) = delete; 43*03ce13f7SAndroid Build Coastguard Worker Inst &operator=(const Inst &) = delete; 44*03ce13f7SAndroid Build Coastguard Worker 45*03ce13f7SAndroid Build Coastguard Worker public: 46*03ce13f7SAndroid Build Coastguard Worker enum InstKind { 47*03ce13f7SAndroid Build Coastguard Worker // Arbitrary (alphabetical) order, except put Unreachable first. 48*03ce13f7SAndroid Build Coastguard Worker Unreachable, 49*03ce13f7SAndroid Build Coastguard Worker Alloca, 50*03ce13f7SAndroid Build Coastguard Worker Arithmetic, 51*03ce13f7SAndroid Build Coastguard Worker Br, 52*03ce13f7SAndroid Build Coastguard Worker Call, 53*03ce13f7SAndroid Build Coastguard Worker Cast, 54*03ce13f7SAndroid Build Coastguard Worker ExtractElement, 55*03ce13f7SAndroid Build Coastguard Worker Fcmp, 56*03ce13f7SAndroid Build Coastguard Worker Icmp, 57*03ce13f7SAndroid Build Coastguard Worker Intrinsic, 58*03ce13f7SAndroid Build Coastguard Worker InsertElement, 59*03ce13f7SAndroid Build Coastguard Worker Load, 60*03ce13f7SAndroid Build Coastguard Worker Phi, 61*03ce13f7SAndroid Build Coastguard Worker Ret, 62*03ce13f7SAndroid Build Coastguard Worker Select, 63*03ce13f7SAndroid Build Coastguard Worker Store, 64*03ce13f7SAndroid Build Coastguard Worker Switch, 65*03ce13f7SAndroid Build Coastguard Worker Assign, // not part of LLVM/PNaCl bitcode 66*03ce13f7SAndroid Build Coastguard Worker Breakpoint, // not part of LLVM/PNaCl bitcode 67*03ce13f7SAndroid Build Coastguard Worker FakeDef, // not part of LLVM/PNaCl bitcode 68*03ce13f7SAndroid Build Coastguard Worker FakeUse, // not part of LLVM/PNaCl bitcode 69*03ce13f7SAndroid Build Coastguard Worker FakeKill, // not part of LLVM/PNaCl bitcode 70*03ce13f7SAndroid Build Coastguard Worker JumpTable, // not part of LLVM/PNaCl bitcode 71*03ce13f7SAndroid Build Coastguard Worker ShuffleVector, // not part of LLVM/PNaCl bitcode 72*03ce13f7SAndroid Build Coastguard Worker // Anything >= Target is an InstTarget subclass. Note that the value-spaces 73*03ce13f7SAndroid Build Coastguard Worker // are shared across targets. To avoid confusion over the definition of 74*03ce13f7SAndroid Build Coastguard Worker // shared values, an object specific to one target should never be passed 75*03ce13f7SAndroid Build Coastguard Worker // to a different target. 76*03ce13f7SAndroid Build Coastguard Worker Target, 77*03ce13f7SAndroid Build Coastguard Worker Target_Max = std::numeric_limits<uint8_t>::max(), 78*03ce13f7SAndroid Build Coastguard Worker }; 79*03ce13f7SAndroid Build Coastguard Worker static_assert(Target <= Target_Max, "Must not be above max."); getKind()80*03ce13f7SAndroid Build Coastguard Worker InstKind getKind() const { return Kind; } 81*03ce13f7SAndroid Build Coastguard Worker virtual const char *getInstName() const; 82*03ce13f7SAndroid Build Coastguard Worker getNumber()83*03ce13f7SAndroid Build Coastguard Worker InstNumberT getNumber() const { return Number; } 84*03ce13f7SAndroid Build Coastguard Worker void renumber(Cfg *Func); 85*03ce13f7SAndroid Build Coastguard Worker enum { 86*03ce13f7SAndroid Build Coastguard Worker NumberDeleted = -1, 87*03ce13f7SAndroid Build Coastguard Worker NumberSentinel = 0, 88*03ce13f7SAndroid Build Coastguard Worker NumberInitial = 2, 89*03ce13f7SAndroid Build Coastguard Worker NumberExtended = NumberInitial - 1 90*03ce13f7SAndroid Build Coastguard Worker }; 91*03ce13f7SAndroid Build Coastguard Worker isDeleted()92*03ce13f7SAndroid Build Coastguard Worker bool isDeleted() const { return Deleted; } setDeleted()93*03ce13f7SAndroid Build Coastguard Worker void setDeleted() { Deleted = true; } 94*03ce13f7SAndroid Build Coastguard Worker void setDead(bool Value = true) { Dead = Value; } 95*03ce13f7SAndroid Build Coastguard Worker void deleteIfDead(); 96*03ce13f7SAndroid Build Coastguard Worker hasSideEffects()97*03ce13f7SAndroid Build Coastguard Worker bool hasSideEffects() const { return HasSideEffects; } 98*03ce13f7SAndroid Build Coastguard Worker isDestRedefined()99*03ce13f7SAndroid Build Coastguard Worker bool isDestRedefined() const { return IsDestRedefined; } setDestRedefined()100*03ce13f7SAndroid Build Coastguard Worker void setDestRedefined() { IsDestRedefined = true; } 101*03ce13f7SAndroid Build Coastguard Worker getDest()102*03ce13f7SAndroid Build Coastguard Worker Variable *getDest() const { return Dest; } 103*03ce13f7SAndroid Build Coastguard Worker getSrcSize()104*03ce13f7SAndroid Build Coastguard Worker SizeT getSrcSize() const { return Srcs.size(); } getSrc(SizeT I)105*03ce13f7SAndroid Build Coastguard Worker Operand *getSrc(SizeT I) const { 106*03ce13f7SAndroid Build Coastguard Worker assert(I < getSrcSize()); 107*03ce13f7SAndroid Build Coastguard Worker return Srcs[I]; 108*03ce13f7SAndroid Build Coastguard Worker } replaceSource(SizeT Index,Operand * Replacement)109*03ce13f7SAndroid Build Coastguard Worker void replaceSource(SizeT Index, Operand *Replacement) { 110*03ce13f7SAndroid Build Coastguard Worker assert(Index < getSrcSize()); 111*03ce13f7SAndroid Build Coastguard Worker assert(!isDeleted()); 112*03ce13f7SAndroid Build Coastguard Worker Srcs[Index] = Replacement; 113*03ce13f7SAndroid Build Coastguard Worker } 114*03ce13f7SAndroid Build Coastguard Worker // Instructions which load data take their address in Src[0], while 115*03ce13f7SAndroid Build Coastguard Worker // store instructions use Src[1] for the address and Src[0] for the data. getLoadAddress()116*03ce13f7SAndroid Build Coastguard Worker Operand *getLoadAddress() const { return getSrc(0); } getStoreAddress()117*03ce13f7SAndroid Build Coastguard Worker Operand *getStoreAddress() const { return getSrc(1); } getData()118*03ce13f7SAndroid Build Coastguard Worker Operand *getData() const { return getSrc(0); } 119*03ce13f7SAndroid Build Coastguard Worker 120*03ce13f7SAndroid Build Coastguard Worker bool isLastUse(const Operand *Src) const; 121*03ce13f7SAndroid Build Coastguard Worker void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); 122*03ce13f7SAndroid Build Coastguard Worker 123*03ce13f7SAndroid Build Coastguard Worker /// Returns a list of out-edges corresponding to a terminator instruction, 124*03ce13f7SAndroid Build Coastguard Worker /// which is the last instruction of the block. The list must not contain 125*03ce13f7SAndroid Build Coastguard Worker /// duplicates. getTerminatorEdges()126*03ce13f7SAndroid Build Coastguard Worker virtual NodeList getTerminatorEdges() const { 127*03ce13f7SAndroid Build Coastguard Worker // All valid terminator instructions override this method. For the default 128*03ce13f7SAndroid Build Coastguard Worker // implementation, we assert in case some CfgNode is constructed without a 129*03ce13f7SAndroid Build Coastguard Worker // terminator instruction at the end. 130*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable( 131*03ce13f7SAndroid Build Coastguard Worker "getTerminatorEdges() called on a non-terminator instruction"); 132*03ce13f7SAndroid Build Coastguard Worker return NodeList(); 133*03ce13f7SAndroid Build Coastguard Worker } isUnconditionalBranch()134*03ce13f7SAndroid Build Coastguard Worker virtual bool isUnconditionalBranch() const { return false; } 135*03ce13f7SAndroid Build Coastguard Worker /// If the instruction is a branch-type instruction with OldNode as a target, 136*03ce13f7SAndroid Build Coastguard Worker /// repoint it to NewNode and return true, otherwise return false. Repoint all 137*03ce13f7SAndroid Build Coastguard Worker /// instances of OldNode as a target. repointEdges(CfgNode * OldNode,CfgNode * NewNode)138*03ce13f7SAndroid Build Coastguard Worker virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { 139*03ce13f7SAndroid Build Coastguard Worker (void)OldNode; 140*03ce13f7SAndroid Build Coastguard Worker (void)NewNode; 141*03ce13f7SAndroid Build Coastguard Worker return false; 142*03ce13f7SAndroid Build Coastguard Worker } 143*03ce13f7SAndroid Build Coastguard Worker 144*03ce13f7SAndroid Build Coastguard Worker /// Returns true if the instruction is equivalent to a simple 145*03ce13f7SAndroid Build Coastguard Worker /// "var_dest=var_src" assignment where the dest and src are both variables. isVarAssign()146*03ce13f7SAndroid Build Coastguard Worker virtual bool isVarAssign() const { return false; } 147*03ce13f7SAndroid Build Coastguard Worker 148*03ce13f7SAndroid Build Coastguard Worker /// Returns true if the instruction has a possible side effect of changing 149*03ce13f7SAndroid Build Coastguard Worker /// memory, in which case a memory load should not be reordered with respect 150*03ce13f7SAndroid Build Coastguard Worker /// to this instruction. It should really be pure virtual, but we can't 151*03ce13f7SAndroid Build Coastguard Worker /// because of g++ and llvm::ilist<>, so we implement it as 152*03ce13f7SAndroid Build Coastguard Worker /// report_fatal_error(). 153*03ce13f7SAndroid Build Coastguard Worker virtual bool isMemoryWrite() const; 154*03ce13f7SAndroid Build Coastguard Worker 155*03ce13f7SAndroid Build Coastguard Worker /// Returns true if the (target-specific) instruction represents an 156*03ce13f7SAndroid Build Coastguard Worker /// intra-block label, i.e. branch target. This is meant primarily for 157*03ce13f7SAndroid Build Coastguard Worker /// Cfg::splitLocalVars(). isLabel()158*03ce13f7SAndroid Build Coastguard Worker virtual bool isLabel() const { return false; } 159*03ce13f7SAndroid Build Coastguard Worker /// If the (target-specific) instruction represents an intra-block branch to 160*03ce13f7SAndroid Build Coastguard Worker /// some Label instruction, return that Label branch target instruction; 161*03ce13f7SAndroid Build Coastguard Worker /// otherwise return nullptr. getIntraBlockBranchTarget()162*03ce13f7SAndroid Build Coastguard Worker virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; } 163*03ce13f7SAndroid Build Coastguard Worker 164*03ce13f7SAndroid Build Coastguard Worker void livenessLightweight(Cfg *Func, LivenessBV &Live); 165*03ce13f7SAndroid Build Coastguard Worker /// Calculates liveness for this instruction. Returns true if this instruction 166*03ce13f7SAndroid Build Coastguard Worker /// is (tentatively) still live and should be retained, and false if this 167*03ce13f7SAndroid Build Coastguard Worker /// instruction is (tentatively) dead and should be deleted. The decision is 168*03ce13f7SAndroid Build Coastguard Worker /// tentative until the liveness dataflow algorithm has converged, and then a 169*03ce13f7SAndroid Build Coastguard Worker /// separate pass permanently deletes dead instructions. 170*03ce13f7SAndroid Build Coastguard Worker bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 171*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 172*03ce13f7SAndroid Build Coastguard Worker 173*03ce13f7SAndroid Build Coastguard Worker /// Get the number of native instructions that this instruction ultimately 174*03ce13f7SAndroid Build Coastguard Worker /// emits. By default, high-level instructions don't result in any native 175*03ce13f7SAndroid Build Coastguard Worker /// instructions, and a target-specific instruction results in a single native 176*03ce13f7SAndroid Build Coastguard Worker /// instruction. getEmitInstCount()177*03ce13f7SAndroid Build Coastguard Worker virtual uint32_t getEmitInstCount() const { return 0; } 178*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): Change Inst back to abstract once the g++ build issue is 179*03ce13f7SAndroid Build Coastguard Worker // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the 180*03ce13f7SAndroid Build Coastguard Worker // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't 181*03ce13f7SAndroid Build Coastguard Worker // allow the abstract class Ice::Inst. The method should be declared 182*03ce13f7SAndroid Build Coastguard Worker // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func) 183*03ce13f7SAndroid Build Coastguard Worker // const = 0; virtual void emitIAS(const Cfg *Func) const = 0; emit(const Cfg *)184*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const Cfg *) const { 185*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("emit on abstract class"); 186*03ce13f7SAndroid Build Coastguard Worker } emitIAS(const Cfg * Func)187*03ce13f7SAndroid Build Coastguard Worker virtual void emitIAS(const Cfg *Func) const { emit(Func); } 188*03ce13f7SAndroid Build Coastguard Worker virtual void dump(const Cfg *Func) const; 189*03ce13f7SAndroid Build Coastguard Worker virtual void dumpExtras(const Cfg *Func) const; 190*03ce13f7SAndroid Build Coastguard Worker void dumpDecorated(const Cfg *Func) const; 191*03ce13f7SAndroid Build Coastguard Worker void emitSources(const Cfg *Func) const; 192*03ce13f7SAndroid Build Coastguard Worker void dumpSources(const Cfg *Func) const; 193*03ce13f7SAndroid Build Coastguard Worker void dumpDest(const Cfg *Func) const; isRedundantAssign()194*03ce13f7SAndroid Build Coastguard Worker virtual bool isRedundantAssign() const { return false; } 195*03ce13f7SAndroid Build Coastguard Worker 196*03ce13f7SAndroid Build Coastguard Worker virtual ~Inst() = default; replaceDest(Variable * Var)197*03ce13f7SAndroid Build Coastguard Worker void replaceDest(Variable *Var) { Dest = Var; } 198*03ce13f7SAndroid Build Coastguard Worker delete(void * Ptr,std::size_t Size)199*03ce13f7SAndroid Build Coastguard Worker void operator delete(void *Ptr, std::size_t Size) { 200*03ce13f7SAndroid Build Coastguard Worker assert(CfgAllocatorTraits::current() != nullptr); 201*03ce13f7SAndroid Build Coastguard Worker CfgAllocatorTraits::current()->Deallocate(Ptr, Size); 202*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Inst unexpectedly deleted"); 203*03ce13f7SAndroid Build Coastguard Worker } 204*03ce13f7SAndroid Build Coastguard Worker getExternalData()205*03ce13f7SAndroid Build Coastguard Worker inline void *getExternalData() const { return externalData; } setExternalData(void * data)206*03ce13f7SAndroid Build Coastguard Worker inline void setExternalData(void *data) { externalData = data; } 207*03ce13f7SAndroid Build Coastguard Worker 208*03ce13f7SAndroid Build Coastguard Worker protected: 209*03ce13f7SAndroid Build Coastguard Worker Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); addSource(Operand * Src)210*03ce13f7SAndroid Build Coastguard Worker void addSource(Operand *Src) { 211*03ce13f7SAndroid Build Coastguard Worker assert(Src); 212*03ce13f7SAndroid Build Coastguard Worker Srcs.push_back(Src); 213*03ce13f7SAndroid Build Coastguard Worker } setLastUse(SizeT VarIndex)214*03ce13f7SAndroid Build Coastguard Worker void setLastUse(SizeT VarIndex) { 215*03ce13f7SAndroid Build Coastguard Worker if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 216*03ce13f7SAndroid Build Coastguard Worker LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 217*03ce13f7SAndroid Build Coastguard Worker } resetLastUses()218*03ce13f7SAndroid Build Coastguard Worker void resetLastUses() { LiveRangesEnded = 0; } 219*03ce13f7SAndroid Build Coastguard Worker /// The destroy() method lets the instruction cleanly release any memory that 220*03ce13f7SAndroid Build Coastguard Worker /// was allocated via the Cfg's allocator. destroy(Cfg *)221*03ce13f7SAndroid Build Coastguard Worker virtual void destroy(Cfg *) {} 222*03ce13f7SAndroid Build Coastguard Worker 223*03ce13f7SAndroid Build Coastguard Worker const InstKind Kind; 224*03ce13f7SAndroid Build Coastguard Worker /// Number is the instruction number for describing live ranges. 225*03ce13f7SAndroid Build Coastguard Worker InstNumberT Number; 226*03ce13f7SAndroid Build Coastguard Worker /// Deleted means irrevocably deleted. 227*03ce13f7SAndroid Build Coastguard Worker bool Deleted = false; 228*03ce13f7SAndroid Build Coastguard Worker /// Dead means one of two things depending on context: (1) pending deletion 229*03ce13f7SAndroid Build Coastguard Worker /// after liveness analysis converges, or (2) marked for deletion during 230*03ce13f7SAndroid Build Coastguard Worker /// lowering due to a folded bool operation. 231*03ce13f7SAndroid Build Coastguard Worker bool Dead = false; 232*03ce13f7SAndroid Build Coastguard Worker /// HasSideEffects means the instruction is something like a function call or 233*03ce13f7SAndroid Build Coastguard Worker /// a volatile load that can't be removed even if its Dest variable is not 234*03ce13f7SAndroid Build Coastguard Worker /// live. 235*03ce13f7SAndroid Build Coastguard Worker bool HasSideEffects = false; 236*03ce13f7SAndroid Build Coastguard Worker /// IsDestRedefined indicates that this instruction is not the first 237*03ce13f7SAndroid Build Coastguard Worker /// definition of Dest in the basic block. The effect is that liveness 238*03ce13f7SAndroid Build Coastguard Worker /// analysis shouldn't consider this instruction to be the start of Dest's 239*03ce13f7SAndroid Build Coastguard Worker /// live range; rather, there is some other instruction earlier in the basic 240*03ce13f7SAndroid Build Coastguard Worker /// block with the same Dest. This is maintained because liveness analysis 241*03ce13f7SAndroid Build Coastguard Worker /// has an invariant (primarily for performance reasons) that any Variable's 242*03ce13f7SAndroid Build Coastguard Worker /// live range recorded in a basic block has at most one start and at most one 243*03ce13f7SAndroid Build Coastguard Worker /// end. 244*03ce13f7SAndroid Build Coastguard Worker bool IsDestRedefined = false; 245*03ce13f7SAndroid Build Coastguard Worker /// External data can be set by an optimizer to compute and retain any 246*03ce13f7SAndroid Build Coastguard Worker /// information related to the current instruction. All the memory used to 247*03ce13f7SAndroid Build Coastguard Worker /// store this information must be managed by the optimizer. 248*03ce13f7SAndroid Build Coastguard Worker void *externalData = nullptr; 249*03ce13f7SAndroid Build Coastguard Worker 250*03ce13f7SAndroid Build Coastguard Worker Variable *Dest; 251*03ce13f7SAndroid Build Coastguard Worker const SizeT MaxSrcs; // only used for assert 252*03ce13f7SAndroid Build Coastguard Worker 253*03ce13f7SAndroid Build Coastguard Worker CfgVector<Operand *> Srcs; 254*03ce13f7SAndroid Build Coastguard Worker 255*03ce13f7SAndroid Build Coastguard Worker /// LiveRangesEnded marks which Variables' live ranges end in this 256*03ce13f7SAndroid Build Coastguard Worker /// instruction. An instruction can have an arbitrary number of source 257*03ce13f7SAndroid Build Coastguard Worker /// operands (e.g. a call instruction), and each source operand can contain 0 258*03ce13f7SAndroid Build Coastguard Worker /// or 1 Variable (and target-specific operands could contain more than 1 259*03ce13f7SAndroid Build Coastguard Worker /// Variable). All the variables in an instruction are conceptually flattened 260*03ce13f7SAndroid Build Coastguard Worker /// and each variable is mapped to one bit position of the LiveRangesEnded bit 261*03ce13f7SAndroid Build Coastguard Worker /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are 262*03ce13f7SAndroid Build Coastguard Worker /// tracked this way. 263*03ce13f7SAndroid Build Coastguard Worker using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry 264*03ce13f7SAndroid Build Coastguard Worker LREndedBits LiveRangesEnded; 265*03ce13f7SAndroid Build Coastguard Worker }; 266*03ce13f7SAndroid Build Coastguard Worker 267*03ce13f7SAndroid Build Coastguard Worker class InstHighLevel : public Inst { 268*03ce13f7SAndroid Build Coastguard Worker InstHighLevel() = delete; 269*03ce13f7SAndroid Build Coastguard Worker InstHighLevel(const InstHighLevel &) = delete; 270*03ce13f7SAndroid Build Coastguard Worker InstHighLevel &operator=(const InstHighLevel &) = delete; 271*03ce13f7SAndroid Build Coastguard Worker 272*03ce13f7SAndroid Build Coastguard Worker protected: InstHighLevel(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)273*03ce13f7SAndroid Build Coastguard Worker InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 274*03ce13f7SAndroid Build Coastguard Worker : Inst(Func, Kind, MaxSrcs, Dest) {} emit(const Cfg *)275*03ce13f7SAndroid Build Coastguard Worker void emit(const Cfg * /*Func*/) const override { 276*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("emit() called on a non-lowered instruction"); 277*03ce13f7SAndroid Build Coastguard Worker } emitIAS(const Cfg *)278*03ce13f7SAndroid Build Coastguard Worker void emitIAS(const Cfg * /*Func*/) const override { 279*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("emitIAS() called on a non-lowered instruction"); 280*03ce13f7SAndroid Build Coastguard Worker } 281*03ce13f7SAndroid Build Coastguard Worker }; 282*03ce13f7SAndroid Build Coastguard Worker 283*03ce13f7SAndroid Build Coastguard Worker /// Alloca instruction. This captures the size in bytes as getSrc(0), and the 284*03ce13f7SAndroid Build Coastguard Worker /// required alignment in bytes. The alignment must be either 0 (no alignment 285*03ce13f7SAndroid Build Coastguard Worker /// required) or a power of 2. 286*03ce13f7SAndroid Build Coastguard Worker class InstAlloca : public InstHighLevel { 287*03ce13f7SAndroid Build Coastguard Worker InstAlloca() = delete; 288*03ce13f7SAndroid Build Coastguard Worker InstAlloca(const InstAlloca &) = delete; 289*03ce13f7SAndroid Build Coastguard Worker InstAlloca &operator=(const InstAlloca &) = delete; 290*03ce13f7SAndroid Build Coastguard Worker 291*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,Variable * Dest,Operand * ByteCount,uint32_t AlignInBytes)292*03ce13f7SAndroid Build Coastguard Worker static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, 293*03ce13f7SAndroid Build Coastguard Worker uint32_t AlignInBytes) { 294*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstAlloca>()) 295*03ce13f7SAndroid Build Coastguard Worker InstAlloca(Func, Dest, ByteCount, AlignInBytes); 296*03ce13f7SAndroid Build Coastguard Worker } getAlignInBytes()297*03ce13f7SAndroid Build Coastguard Worker uint32_t getAlignInBytes() const { return AlignInBytes; } getSizeInBytes()298*03ce13f7SAndroid Build Coastguard Worker Operand *getSizeInBytes() const { return getSrc(0); } getKnownFrameOffset()299*03ce13f7SAndroid Build Coastguard Worker bool getKnownFrameOffset() const { return KnownFrameOffset; } setKnownFrameOffset()300*03ce13f7SAndroid Build Coastguard Worker void setKnownFrameOffset() { KnownFrameOffset = true; } isMemoryWrite()301*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 302*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)303*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } 304*03ce13f7SAndroid Build Coastguard Worker 305*03ce13f7SAndroid Build Coastguard Worker private: 306*03ce13f7SAndroid Build Coastguard Worker InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, 307*03ce13f7SAndroid Build Coastguard Worker uint32_t AlignInBytes); 308*03ce13f7SAndroid Build Coastguard Worker 309*03ce13f7SAndroid Build Coastguard Worker const uint32_t AlignInBytes; 310*03ce13f7SAndroid Build Coastguard Worker bool KnownFrameOffset = false; 311*03ce13f7SAndroid Build Coastguard Worker }; 312*03ce13f7SAndroid Build Coastguard Worker 313*03ce13f7SAndroid Build Coastguard Worker /// Binary arithmetic instruction. The source operands are captured in getSrc(0) 314*03ce13f7SAndroid Build Coastguard Worker /// and getSrc(1). 315*03ce13f7SAndroid Build Coastguard Worker class InstArithmetic : public InstHighLevel { 316*03ce13f7SAndroid Build Coastguard Worker InstArithmetic() = delete; 317*03ce13f7SAndroid Build Coastguard Worker InstArithmetic(const InstArithmetic &) = delete; 318*03ce13f7SAndroid Build Coastguard Worker InstArithmetic &operator=(const InstArithmetic &) = delete; 319*03ce13f7SAndroid Build Coastguard Worker 320*03ce13f7SAndroid Build Coastguard Worker public: 321*03ce13f7SAndroid Build Coastguard Worker enum OpKind { 322*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str, commutative) tag, 323*03ce13f7SAndroid Build Coastguard Worker ICEINSTARITHMETIC_TABLE 324*03ce13f7SAndroid Build Coastguard Worker #undef X 325*03ce13f7SAndroid Build Coastguard Worker _num 326*03ce13f7SAndroid Build Coastguard Worker }; 327*03ce13f7SAndroid Build Coastguard Worker create(Cfg * Func,OpKind Op,Variable * Dest,Operand * Source1,Operand * Source2)328*03ce13f7SAndroid Build Coastguard Worker static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, 329*03ce13f7SAndroid Build Coastguard Worker Operand *Source1, Operand *Source2) { 330*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstArithmetic>()) 331*03ce13f7SAndroid Build Coastguard Worker InstArithmetic(Func, Op, Dest, Source1, Source2); 332*03ce13f7SAndroid Build Coastguard Worker } getOp()333*03ce13f7SAndroid Build Coastguard Worker OpKind getOp() const { return Op; } 334*03ce13f7SAndroid Build Coastguard Worker 335*03ce13f7SAndroid Build Coastguard Worker virtual const char *getInstName() const override; 336*03ce13f7SAndroid Build Coastguard Worker 337*03ce13f7SAndroid Build Coastguard Worker static const char *getOpName(OpKind Op); 338*03ce13f7SAndroid Build Coastguard Worker bool isCommutative() const; isMemoryWrite()339*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 340*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)341*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 342*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == Arithmetic; 343*03ce13f7SAndroid Build Coastguard Worker } 344*03ce13f7SAndroid Build Coastguard Worker 345*03ce13f7SAndroid Build Coastguard Worker private: 346*03ce13f7SAndroid Build Coastguard Worker InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 347*03ce13f7SAndroid Build Coastguard Worker Operand *Source2); 348*03ce13f7SAndroid Build Coastguard Worker 349*03ce13f7SAndroid Build Coastguard Worker const OpKind Op; 350*03ce13f7SAndroid Build Coastguard Worker }; 351*03ce13f7SAndroid Build Coastguard Worker 352*03ce13f7SAndroid Build Coastguard Worker /// Assignment instruction. The source operand is captured in getSrc(0). This is 353*03ce13f7SAndroid Build Coastguard Worker /// not part of the LLVM bitcode, but is a useful abstraction for some of the 354*03ce13f7SAndroid Build Coastguard Worker /// lowering. E.g., if Phi instruction lowering happens before target lowering, 355*03ce13f7SAndroid Build Coastguard Worker /// or for representing an Inttoptr instruction, or as an intermediate step for 356*03ce13f7SAndroid Build Coastguard Worker /// lowering a Load instruction. 357*03ce13f7SAndroid Build Coastguard Worker class InstAssign : public InstHighLevel { 358*03ce13f7SAndroid Build Coastguard Worker InstAssign() = delete; 359*03ce13f7SAndroid Build Coastguard Worker InstAssign(const InstAssign &) = delete; 360*03ce13f7SAndroid Build Coastguard Worker InstAssign &operator=(const InstAssign &) = delete; 361*03ce13f7SAndroid Build Coastguard Worker 362*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,Variable * Dest,Operand * Source)363*03ce13f7SAndroid Build Coastguard Worker static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 364*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 365*03ce13f7SAndroid Build Coastguard Worker } 366*03ce13f7SAndroid Build Coastguard Worker bool isVarAssign() const override; isMemoryWrite()367*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 368*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)369*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } 370*03ce13f7SAndroid Build Coastguard Worker 371*03ce13f7SAndroid Build Coastguard Worker private: 372*03ce13f7SAndroid Build Coastguard Worker InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 373*03ce13f7SAndroid Build Coastguard Worker }; 374*03ce13f7SAndroid Build Coastguard Worker 375*03ce13f7SAndroid Build Coastguard Worker /// Branch instruction. This represents both conditional and unconditional 376*03ce13f7SAndroid Build Coastguard Worker /// branches. 377*03ce13f7SAndroid Build Coastguard Worker class InstBr : public InstHighLevel { 378*03ce13f7SAndroid Build Coastguard Worker InstBr() = delete; 379*03ce13f7SAndroid Build Coastguard Worker InstBr(const InstBr &) = delete; 380*03ce13f7SAndroid Build Coastguard Worker InstBr &operator=(const InstBr &) = delete; 381*03ce13f7SAndroid Build Coastguard Worker 382*03ce13f7SAndroid Build Coastguard Worker public: 383*03ce13f7SAndroid Build Coastguard Worker /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized 384*03ce13f7SAndroid Build Coastguard Worker /// to an unconditional branch. create(Cfg * Func,Operand * Source,CfgNode * TargetTrue,CfgNode * TargetFalse)385*03ce13f7SAndroid Build Coastguard Worker static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 386*03ce13f7SAndroid Build Coastguard Worker CfgNode *TargetFalse) { 387*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstBr>()) 388*03ce13f7SAndroid Build Coastguard Worker InstBr(Func, Source, TargetTrue, TargetFalse); 389*03ce13f7SAndroid Build Coastguard Worker } 390*03ce13f7SAndroid Build Coastguard Worker /// Create an unconditional branch. create(Cfg * Func,CfgNode * Target)391*03ce13f7SAndroid Build Coastguard Worker static InstBr *create(Cfg *Func, CfgNode *Target) { 392*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstBr>()) InstBr(Func, Target); 393*03ce13f7SAndroid Build Coastguard Worker } isUnconditional()394*03ce13f7SAndroid Build Coastguard Worker bool isUnconditional() const { return getTargetTrue() == nullptr; } getCondition()395*03ce13f7SAndroid Build Coastguard Worker Operand *getCondition() const { 396*03ce13f7SAndroid Build Coastguard Worker assert(!isUnconditional()); 397*03ce13f7SAndroid Build Coastguard Worker return getSrc(0); 398*03ce13f7SAndroid Build Coastguard Worker } getTargetTrue()399*03ce13f7SAndroid Build Coastguard Worker CfgNode *getTargetTrue() const { return TargetTrue; } getTargetFalse()400*03ce13f7SAndroid Build Coastguard Worker CfgNode *getTargetFalse() const { return TargetFalse; } getTargetUnconditional()401*03ce13f7SAndroid Build Coastguard Worker CfgNode *getTargetUnconditional() const { 402*03ce13f7SAndroid Build Coastguard Worker assert(isUnconditional()); 403*03ce13f7SAndroid Build Coastguard Worker return getTargetFalse(); 404*03ce13f7SAndroid Build Coastguard Worker } 405*03ce13f7SAndroid Build Coastguard Worker NodeList getTerminatorEdges() const override; isUnconditionalBranch()406*03ce13f7SAndroid Build Coastguard Worker bool isUnconditionalBranch() const override { return isUnconditional(); } 407*03ce13f7SAndroid Build Coastguard Worker bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; isMemoryWrite()408*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 409*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)410*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } 411*03ce13f7SAndroid Build Coastguard Worker 412*03ce13f7SAndroid Build Coastguard Worker private: 413*03ce13f7SAndroid Build Coastguard Worker /// Conditional branch 414*03ce13f7SAndroid Build Coastguard Worker InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 415*03ce13f7SAndroid Build Coastguard Worker /// Unconditional branch 416*03ce13f7SAndroid Build Coastguard Worker InstBr(Cfg *Func, CfgNode *Target); 417*03ce13f7SAndroid Build Coastguard Worker 418*03ce13f7SAndroid Build Coastguard Worker CfgNode *TargetFalse; /// Doubles as unconditional branch target 419*03ce13f7SAndroid Build Coastguard Worker CfgNode *TargetTrue; /// nullptr if unconditional branch 420*03ce13f7SAndroid Build Coastguard Worker }; 421*03ce13f7SAndroid Build Coastguard Worker 422*03ce13f7SAndroid Build Coastguard Worker /// Call instruction. The call target is captured as getSrc(0), and arg I is 423*03ce13f7SAndroid Build Coastguard Worker /// captured as getSrc(I+1). 424*03ce13f7SAndroid Build Coastguard Worker class InstCall : public InstHighLevel { 425*03ce13f7SAndroid Build Coastguard Worker InstCall() = delete; 426*03ce13f7SAndroid Build Coastguard Worker InstCall(const InstCall &) = delete; 427*03ce13f7SAndroid Build Coastguard Worker InstCall &operator=(const InstCall &) = delete; 428*03ce13f7SAndroid Build Coastguard Worker 429*03ce13f7SAndroid Build Coastguard Worker public: 430*03ce13f7SAndroid Build Coastguard Worker static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 431*03ce13f7SAndroid Build Coastguard Worker Operand *CallTarget, bool HasTailCall, 432*03ce13f7SAndroid Build Coastguard Worker bool IsTargetHelperCall = false, 433*03ce13f7SAndroid Build Coastguard Worker bool IsVariadic = false) { 434*03ce13f7SAndroid Build Coastguard Worker /// Set HasSideEffects to true so that the call instruction can't be 435*03ce13f7SAndroid Build Coastguard Worker /// dead-code eliminated. 436*03ce13f7SAndroid Build Coastguard Worker constexpr bool HasSideEffects = true; 437*03ce13f7SAndroid Build Coastguard Worker constexpr InstKind Kind = Inst::Call; 438*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstCall>()) 439*03ce13f7SAndroid Build Coastguard Worker InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, 440*03ce13f7SAndroid Build Coastguard Worker IsTargetHelperCall, IsVariadic, HasSideEffects, Kind); 441*03ce13f7SAndroid Build Coastguard Worker } addArg(Operand * Arg)442*03ce13f7SAndroid Build Coastguard Worker void addArg(Operand *Arg) { addSource(Arg); } getCallTarget()443*03ce13f7SAndroid Build Coastguard Worker Operand *getCallTarget() const { return getSrc(0); } getArg(SizeT I)444*03ce13f7SAndroid Build Coastguard Worker Operand *getArg(SizeT I) const { return getSrc(I + 1); } getNumArgs()445*03ce13f7SAndroid Build Coastguard Worker SizeT getNumArgs() const { return getSrcSize() - 1; } isTailcall()446*03ce13f7SAndroid Build Coastguard Worker bool isTailcall() const { return HasTailCall; } isTargetHelperCall()447*03ce13f7SAndroid Build Coastguard Worker bool isTargetHelperCall() const { return IsTargetHelperCall; } isVariadic()448*03ce13f7SAndroid Build Coastguard Worker bool isVariadic() const { return IsVariadic; } isMemoryWrite()449*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return true; } 450*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)451*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } 452*03ce13f7SAndroid Build Coastguard Worker Type getReturnType() const; 453*03ce13f7SAndroid Build Coastguard Worker 454*03ce13f7SAndroid Build Coastguard Worker protected: InstCall(Cfg * Func,SizeT NumArgs,Variable * Dest,Operand * CallTarget,bool HasTailCall,bool IsTargetHelperCall,bool IsVariadic,bool HasSideEff,InstKind Kind)455*03ce13f7SAndroid Build Coastguard Worker InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 456*03ce13f7SAndroid Build Coastguard Worker bool HasTailCall, bool IsTargetHelperCall, bool IsVariadic, 457*03ce13f7SAndroid Build Coastguard Worker bool HasSideEff, InstKind Kind) 458*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), 459*03ce13f7SAndroid Build Coastguard Worker IsTargetHelperCall(IsTargetHelperCall), IsVariadic(IsVariadic) { 460*03ce13f7SAndroid Build Coastguard Worker HasSideEffects = HasSideEff; 461*03ce13f7SAndroid Build Coastguard Worker addSource(CallTarget); 462*03ce13f7SAndroid Build Coastguard Worker } 463*03ce13f7SAndroid Build Coastguard Worker 464*03ce13f7SAndroid Build Coastguard Worker private: 465*03ce13f7SAndroid Build Coastguard Worker const bool HasTailCall; 466*03ce13f7SAndroid Build Coastguard Worker const bool IsTargetHelperCall; 467*03ce13f7SAndroid Build Coastguard Worker const bool IsVariadic; 468*03ce13f7SAndroid Build Coastguard Worker }; 469*03ce13f7SAndroid Build Coastguard Worker 470*03ce13f7SAndroid Build Coastguard Worker /// Cast instruction (a.k.a. conversion operation). 471*03ce13f7SAndroid Build Coastguard Worker class InstCast : public InstHighLevel { 472*03ce13f7SAndroid Build Coastguard Worker InstCast() = delete; 473*03ce13f7SAndroid Build Coastguard Worker InstCast(const InstCast &) = delete; 474*03ce13f7SAndroid Build Coastguard Worker InstCast &operator=(const InstCast &) = delete; 475*03ce13f7SAndroid Build Coastguard Worker 476*03ce13f7SAndroid Build Coastguard Worker public: 477*03ce13f7SAndroid Build Coastguard Worker enum OpKind { 478*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str) tag, 479*03ce13f7SAndroid Build Coastguard Worker ICEINSTCAST_TABLE 480*03ce13f7SAndroid Build Coastguard Worker #undef X 481*03ce13f7SAndroid Build Coastguard Worker _num 482*03ce13f7SAndroid Build Coastguard Worker }; 483*03ce13f7SAndroid Build Coastguard Worker 484*03ce13f7SAndroid Build Coastguard Worker static const char *getCastName(OpKind Kind); 485*03ce13f7SAndroid Build Coastguard Worker create(Cfg * Func,OpKind CastKind,Variable * Dest,Operand * Source)486*03ce13f7SAndroid Build Coastguard Worker static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 487*03ce13f7SAndroid Build Coastguard Worker Operand *Source) { 488*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstCast>()) 489*03ce13f7SAndroid Build Coastguard Worker InstCast(Func, CastKind, Dest, Source); 490*03ce13f7SAndroid Build Coastguard Worker } getCastKind()491*03ce13f7SAndroid Build Coastguard Worker OpKind getCastKind() const { return CastKind; } isMemoryWrite()492*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 493*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)494*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } 495*03ce13f7SAndroid Build Coastguard Worker 496*03ce13f7SAndroid Build Coastguard Worker private: 497*03ce13f7SAndroid Build Coastguard Worker InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 498*03ce13f7SAndroid Build Coastguard Worker 499*03ce13f7SAndroid Build Coastguard Worker const OpKind CastKind; 500*03ce13f7SAndroid Build Coastguard Worker }; 501*03ce13f7SAndroid Build Coastguard Worker 502*03ce13f7SAndroid Build Coastguard Worker /// ExtractElement instruction. 503*03ce13f7SAndroid Build Coastguard Worker class InstExtractElement : public InstHighLevel { 504*03ce13f7SAndroid Build Coastguard Worker InstExtractElement() = delete; 505*03ce13f7SAndroid Build Coastguard Worker InstExtractElement(const InstExtractElement &) = delete; 506*03ce13f7SAndroid Build Coastguard Worker InstExtractElement &operator=(const InstExtractElement &) = delete; 507*03ce13f7SAndroid Build Coastguard Worker 508*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)509*03ce13f7SAndroid Build Coastguard Worker static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 510*03ce13f7SAndroid Build Coastguard Worker Operand *Source2) { 511*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstExtractElement>()) 512*03ce13f7SAndroid Build Coastguard Worker InstExtractElement(Func, Dest, Source1, Source2); 513*03ce13f7SAndroid Build Coastguard Worker } 514*03ce13f7SAndroid Build Coastguard Worker isMemoryWrite()515*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 516*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)517*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 518*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == ExtractElement; 519*03ce13f7SAndroid Build Coastguard Worker } 520*03ce13f7SAndroid Build Coastguard Worker 521*03ce13f7SAndroid Build Coastguard Worker private: 522*03ce13f7SAndroid Build Coastguard Worker InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 523*03ce13f7SAndroid Build Coastguard Worker Operand *Source2); 524*03ce13f7SAndroid Build Coastguard Worker }; 525*03ce13f7SAndroid Build Coastguard Worker 526*03ce13f7SAndroid Build Coastguard Worker /// Floating-point comparison instruction. The source operands are captured in 527*03ce13f7SAndroid Build Coastguard Worker /// getSrc(0) and getSrc(1). 528*03ce13f7SAndroid Build Coastguard Worker class InstFcmp : public InstHighLevel { 529*03ce13f7SAndroid Build Coastguard Worker InstFcmp() = delete; 530*03ce13f7SAndroid Build Coastguard Worker InstFcmp(const InstFcmp &) = delete; 531*03ce13f7SAndroid Build Coastguard Worker InstFcmp &operator=(const InstFcmp &) = delete; 532*03ce13f7SAndroid Build Coastguard Worker 533*03ce13f7SAndroid Build Coastguard Worker public: 534*03ce13f7SAndroid Build Coastguard Worker enum FCond { 535*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str) tag, 536*03ce13f7SAndroid Build Coastguard Worker ICEINSTFCMP_TABLE 537*03ce13f7SAndroid Build Coastguard Worker #undef X 538*03ce13f7SAndroid Build Coastguard Worker _num 539*03ce13f7SAndroid Build Coastguard Worker }; 540*03ce13f7SAndroid Build Coastguard Worker create(Cfg * Func,FCond Condition,Variable * Dest,Operand * Source1,Operand * Source2)541*03ce13f7SAndroid Build Coastguard Worker static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 542*03ce13f7SAndroid Build Coastguard Worker Operand *Source1, Operand *Source2) { 543*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstFcmp>()) 544*03ce13f7SAndroid Build Coastguard Worker InstFcmp(Func, Condition, Dest, Source1, Source2); 545*03ce13f7SAndroid Build Coastguard Worker } getCondition()546*03ce13f7SAndroid Build Coastguard Worker FCond getCondition() const { return Condition; } isMemoryWrite()547*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 548*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)549*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } 550*03ce13f7SAndroid Build Coastguard Worker 551*03ce13f7SAndroid Build Coastguard Worker private: 552*03ce13f7SAndroid Build Coastguard Worker InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 553*03ce13f7SAndroid Build Coastguard Worker Operand *Source2); 554*03ce13f7SAndroid Build Coastguard Worker 555*03ce13f7SAndroid Build Coastguard Worker const FCond Condition; 556*03ce13f7SAndroid Build Coastguard Worker }; 557*03ce13f7SAndroid Build Coastguard Worker 558*03ce13f7SAndroid Build Coastguard Worker /// Integer comparison instruction. The source operands are captured in 559*03ce13f7SAndroid Build Coastguard Worker /// getSrc(0) and getSrc(1). 560*03ce13f7SAndroid Build Coastguard Worker class InstIcmp : public InstHighLevel { 561*03ce13f7SAndroid Build Coastguard Worker InstIcmp() = delete; 562*03ce13f7SAndroid Build Coastguard Worker InstIcmp(const InstIcmp &) = delete; 563*03ce13f7SAndroid Build Coastguard Worker InstIcmp &operator=(const InstIcmp &) = delete; 564*03ce13f7SAndroid Build Coastguard Worker 565*03ce13f7SAndroid Build Coastguard Worker public: 566*03ce13f7SAndroid Build Coastguard Worker enum ICond { 567*03ce13f7SAndroid Build Coastguard Worker #define X(tag, inverse, str) tag, 568*03ce13f7SAndroid Build Coastguard Worker ICEINSTICMP_TABLE 569*03ce13f7SAndroid Build Coastguard Worker #undef X 570*03ce13f7SAndroid Build Coastguard Worker _num 571*03ce13f7SAndroid Build Coastguard Worker }; 572*03ce13f7SAndroid Build Coastguard Worker create(Cfg * Func,ICond Condition,Variable * Dest,Operand * Source1,Operand * Source2)573*03ce13f7SAndroid Build Coastguard Worker static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 574*03ce13f7SAndroid Build Coastguard Worker Operand *Source1, Operand *Source2) { 575*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstIcmp>()) 576*03ce13f7SAndroid Build Coastguard Worker InstIcmp(Func, Condition, Dest, Source1, Source2); 577*03ce13f7SAndroid Build Coastguard Worker } getCondition()578*03ce13f7SAndroid Build Coastguard Worker ICond getCondition() const { return Condition; } 579*03ce13f7SAndroid Build Coastguard Worker void reverseConditionAndOperands(); isMemoryWrite()580*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 581*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)582*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } 583*03ce13f7SAndroid Build Coastguard Worker 584*03ce13f7SAndroid Build Coastguard Worker private: 585*03ce13f7SAndroid Build Coastguard Worker InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 586*03ce13f7SAndroid Build Coastguard Worker Operand *Source2); 587*03ce13f7SAndroid Build Coastguard Worker 588*03ce13f7SAndroid Build Coastguard Worker ICond Condition; 589*03ce13f7SAndroid Build Coastguard Worker }; 590*03ce13f7SAndroid Build Coastguard Worker 591*03ce13f7SAndroid Build Coastguard Worker /// InsertElement instruction. 592*03ce13f7SAndroid Build Coastguard Worker class InstInsertElement : public InstHighLevel { 593*03ce13f7SAndroid Build Coastguard Worker InstInsertElement() = delete; 594*03ce13f7SAndroid Build Coastguard Worker InstInsertElement(const InstInsertElement &) = delete; 595*03ce13f7SAndroid Build Coastguard Worker InstInsertElement &operator=(const InstInsertElement &) = delete; 596*03ce13f7SAndroid Build Coastguard Worker 597*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2,Operand * Source3)598*03ce13f7SAndroid Build Coastguard Worker static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 599*03ce13f7SAndroid Build Coastguard Worker Operand *Source2, Operand *Source3) { 600*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstInsertElement>()) 601*03ce13f7SAndroid Build Coastguard Worker InstInsertElement(Func, Dest, Source1, Source2, Source3); 602*03ce13f7SAndroid Build Coastguard Worker } 603*03ce13f7SAndroid Build Coastguard Worker isMemoryWrite()604*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 605*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)606*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 607*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == InsertElement; 608*03ce13f7SAndroid Build Coastguard Worker } 609*03ce13f7SAndroid Build Coastguard Worker 610*03ce13f7SAndroid Build Coastguard Worker private: 611*03ce13f7SAndroid Build Coastguard Worker InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 612*03ce13f7SAndroid Build Coastguard Worker Operand *Source2, Operand *Source3); 613*03ce13f7SAndroid Build Coastguard Worker }; 614*03ce13f7SAndroid Build Coastguard Worker 615*03ce13f7SAndroid Build Coastguard Worker /// An intrinsic operation, representing either a sequence of instructions, 616*03ce13f7SAndroid Build Coastguard Worker /// or a single instruction. Availability of intrinsics is target-specific. 617*03ce13f7SAndroid Build Coastguard Worker class InstIntrinsic : public InstHighLevel { 618*03ce13f7SAndroid Build Coastguard Worker InstIntrinsic() = delete; 619*03ce13f7SAndroid Build Coastguard Worker InstIntrinsic(const InstIntrinsic &) = delete; 620*03ce13f7SAndroid Build Coastguard Worker InstIntrinsic &operator=(const InstIntrinsic &) = delete; 621*03ce13f7SAndroid Build Coastguard Worker 622*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,SizeT NumArgs,Variable * Dest,const Intrinsics::IntrinsicInfo & Info)623*03ce13f7SAndroid Build Coastguard Worker static InstIntrinsic *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 624*03ce13f7SAndroid Build Coastguard Worker const Intrinsics::IntrinsicInfo &Info) { 625*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstIntrinsic>()) 626*03ce13f7SAndroid Build Coastguard Worker InstIntrinsic(Func, NumArgs, Dest, Info); 627*03ce13f7SAndroid Build Coastguard Worker } addArg(Operand * Arg)628*03ce13f7SAndroid Build Coastguard Worker void addArg(Operand *Arg) { addSource(Arg); } getArg(SizeT I)629*03ce13f7SAndroid Build Coastguard Worker Operand *getArg(SizeT I) const { return getSrc(I); } getNumArgs()630*03ce13f7SAndroid Build Coastguard Worker SizeT getNumArgs() const { return getSrcSize(); } classof(const Inst * Instr)631*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 632*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == Intrinsic; 633*03ce13f7SAndroid Build Coastguard Worker } 634*03ce13f7SAndroid Build Coastguard Worker getIntrinsicInfo()635*03ce13f7SAndroid Build Coastguard Worker Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } getIntrinsicID()636*03ce13f7SAndroid Build Coastguard Worker Intrinsics::IntrinsicID getIntrinsicID() const { return Info.ID; } isMemoryWrite()637*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { 638*03ce13f7SAndroid Build Coastguard Worker return getIntrinsicInfo().IsMemoryWrite; 639*03ce13f7SAndroid Build Coastguard Worker } 640*03ce13f7SAndroid Build Coastguard Worker 641*03ce13f7SAndroid Build Coastguard Worker private: InstIntrinsic(Cfg * Func,SizeT NumArgs,Variable * Dest,const Intrinsics::IntrinsicInfo & Info)642*03ce13f7SAndroid Build Coastguard Worker InstIntrinsic(Cfg *Func, SizeT NumArgs, Variable *Dest, 643*03ce13f7SAndroid Build Coastguard Worker const Intrinsics::IntrinsicInfo &Info) 644*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Intrinsic, NumArgs, Dest), Info(Info) {} 645*03ce13f7SAndroid Build Coastguard Worker 646*03ce13f7SAndroid Build Coastguard Worker const Intrinsics::IntrinsicInfo Info; 647*03ce13f7SAndroid Build Coastguard Worker }; 648*03ce13f7SAndroid Build Coastguard Worker 649*03ce13f7SAndroid Build Coastguard Worker /// Load instruction. The source address is captured in getSrc(0). 650*03ce13f7SAndroid Build Coastguard Worker class InstLoad : public InstHighLevel { 651*03ce13f7SAndroid Build Coastguard Worker InstLoad() = delete; 652*03ce13f7SAndroid Build Coastguard Worker InstLoad(const InstLoad &) = delete; 653*03ce13f7SAndroid Build Coastguard Worker InstLoad &operator=(const InstLoad &) = delete; 654*03ce13f7SAndroid Build Coastguard Worker 655*03ce13f7SAndroid Build Coastguard Worker public: 656*03ce13f7SAndroid Build Coastguard Worker static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 657*03ce13f7SAndroid Build Coastguard Worker uint32_t Align = 1) { 658*03ce13f7SAndroid Build Coastguard Worker // TODO(kschimpf) Stop ignoring alignment specification. 659*03ce13f7SAndroid Build Coastguard Worker (void)Align; 660*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 661*03ce13f7SAndroid Build Coastguard Worker } isMemoryWrite()662*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 663*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)664*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } 665*03ce13f7SAndroid Build Coastguard Worker 666*03ce13f7SAndroid Build Coastguard Worker private: 667*03ce13f7SAndroid Build Coastguard Worker InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 668*03ce13f7SAndroid Build Coastguard Worker }; 669*03ce13f7SAndroid Build Coastguard Worker 670*03ce13f7SAndroid Build Coastguard Worker /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi 671*03ce13f7SAndroid Build Coastguard Worker /// source operand is getSrc(I). 672*03ce13f7SAndroid Build Coastguard Worker class InstPhi : public InstHighLevel { 673*03ce13f7SAndroid Build Coastguard Worker InstPhi() = delete; 674*03ce13f7SAndroid Build Coastguard Worker InstPhi(const InstPhi &) = delete; 675*03ce13f7SAndroid Build Coastguard Worker InstPhi &operator=(const InstPhi &) = delete; 676*03ce13f7SAndroid Build Coastguard Worker 677*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,SizeT MaxSrcs,Variable * Dest)678*03ce13f7SAndroid Build Coastguard Worker static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 679*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 680*03ce13f7SAndroid Build Coastguard Worker } 681*03ce13f7SAndroid Build Coastguard Worker void addArgument(Operand *Source, CfgNode *Label); 682*03ce13f7SAndroid Build Coastguard Worker Operand *getOperandForTarget(CfgNode *Target) const; 683*03ce13f7SAndroid Build Coastguard Worker void clearOperandForTarget(CfgNode *Target); getLabel(SizeT Index)684*03ce13f7SAndroid Build Coastguard Worker CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } setLabel(SizeT Index,CfgNode * Label)685*03ce13f7SAndroid Build Coastguard Worker void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } 686*03ce13f7SAndroid Build Coastguard Worker void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 687*03ce13f7SAndroid Build Coastguard Worker Liveness *Liveness); 688*03ce13f7SAndroid Build Coastguard Worker Inst *lower(Cfg *Func); isMemoryWrite()689*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 690*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)691*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } 692*03ce13f7SAndroid Build Coastguard Worker 693*03ce13f7SAndroid Build Coastguard Worker private: 694*03ce13f7SAndroid Build Coastguard Worker InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); destroy(Cfg * Func)695*03ce13f7SAndroid Build Coastguard Worker void destroy(Cfg *Func) override { Inst::destroy(Func); } 696*03ce13f7SAndroid Build Coastguard Worker 697*03ce13f7SAndroid Build Coastguard Worker /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, 698*03ce13f7SAndroid Build Coastguard Worker /// but the Phi instruction is created before InEdges[] is available, so it's 699*03ce13f7SAndroid Build Coastguard Worker /// more complicated to share the list. 700*03ce13f7SAndroid Build Coastguard Worker CfgVector<CfgNode *> Labels; 701*03ce13f7SAndroid Build Coastguard Worker }; 702*03ce13f7SAndroid Build Coastguard Worker 703*03ce13f7SAndroid Build Coastguard Worker /// Ret instruction. The return value is captured in getSrc(0), but if there is 704*03ce13f7SAndroid Build Coastguard Worker /// no return value (void-type function), then getSrcSize()==0 and 705*03ce13f7SAndroid Build Coastguard Worker /// hasRetValue()==false. 706*03ce13f7SAndroid Build Coastguard Worker class InstRet : public InstHighLevel { 707*03ce13f7SAndroid Build Coastguard Worker InstRet() = delete; 708*03ce13f7SAndroid Build Coastguard Worker InstRet(const InstRet &) = delete; 709*03ce13f7SAndroid Build Coastguard Worker InstRet &operator=(const InstRet &) = delete; 710*03ce13f7SAndroid Build Coastguard Worker 711*03ce13f7SAndroid Build Coastguard Worker public: 712*03ce13f7SAndroid Build Coastguard Worker static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 713*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 714*03ce13f7SAndroid Build Coastguard Worker } hasRetValue()715*03ce13f7SAndroid Build Coastguard Worker bool hasRetValue() const { return getSrcSize(); } getRetValue()716*03ce13f7SAndroid Build Coastguard Worker Operand *getRetValue() const { 717*03ce13f7SAndroid Build Coastguard Worker assert(hasRetValue()); 718*03ce13f7SAndroid Build Coastguard Worker return getSrc(0); 719*03ce13f7SAndroid Build Coastguard Worker } getTerminatorEdges()720*03ce13f7SAndroid Build Coastguard Worker NodeList getTerminatorEdges() const override { return NodeList(); } isMemoryWrite()721*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 722*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)723*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } 724*03ce13f7SAndroid Build Coastguard Worker 725*03ce13f7SAndroid Build Coastguard Worker private: 726*03ce13f7SAndroid Build Coastguard Worker InstRet(Cfg *Func, Operand *RetValue); 727*03ce13f7SAndroid Build Coastguard Worker }; 728*03ce13f7SAndroid Build Coastguard Worker 729*03ce13f7SAndroid Build Coastguard Worker /// Select instruction. The condition, true, and false operands are captured. 730*03ce13f7SAndroid Build Coastguard Worker class InstSelect : public InstHighLevel { 731*03ce13f7SAndroid Build Coastguard Worker InstSelect() = delete; 732*03ce13f7SAndroid Build Coastguard Worker InstSelect(const InstSelect &) = delete; 733*03ce13f7SAndroid Build Coastguard Worker InstSelect &operator=(const InstSelect &) = delete; 734*03ce13f7SAndroid Build Coastguard Worker 735*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,Variable * Dest,Operand * Condition,Operand * SourceTrue,Operand * SourceFalse)736*03ce13f7SAndroid Build Coastguard Worker static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 737*03ce13f7SAndroid Build Coastguard Worker Operand *SourceTrue, Operand *SourceFalse) { 738*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstSelect>()) 739*03ce13f7SAndroid Build Coastguard Worker InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 740*03ce13f7SAndroid Build Coastguard Worker } getCondition()741*03ce13f7SAndroid Build Coastguard Worker Operand *getCondition() const { return getSrc(0); } getTrueOperand()742*03ce13f7SAndroid Build Coastguard Worker Operand *getTrueOperand() const { return getSrc(1); } getFalseOperand()743*03ce13f7SAndroid Build Coastguard Worker Operand *getFalseOperand() const { return getSrc(2); } isMemoryWrite()744*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 745*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)746*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } 747*03ce13f7SAndroid Build Coastguard Worker 748*03ce13f7SAndroid Build Coastguard Worker private: 749*03ce13f7SAndroid Build Coastguard Worker InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 750*03ce13f7SAndroid Build Coastguard Worker Operand *Source2); 751*03ce13f7SAndroid Build Coastguard Worker }; 752*03ce13f7SAndroid Build Coastguard Worker 753*03ce13f7SAndroid Build Coastguard Worker /// Store instruction. The address operand is captured, along with the data 754*03ce13f7SAndroid Build Coastguard Worker /// operand to be stored into the address. 755*03ce13f7SAndroid Build Coastguard Worker class InstStore : public InstHighLevel { 756*03ce13f7SAndroid Build Coastguard Worker InstStore() = delete; 757*03ce13f7SAndroid Build Coastguard Worker InstStore(const InstStore &) = delete; 758*03ce13f7SAndroid Build Coastguard Worker InstStore &operator=(const InstStore &) = delete; 759*03ce13f7SAndroid Build Coastguard Worker 760*03ce13f7SAndroid Build Coastguard Worker public: 761*03ce13f7SAndroid Build Coastguard Worker static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 762*03ce13f7SAndroid Build Coastguard Worker uint32_t Align = 1) { 763*03ce13f7SAndroid Build Coastguard Worker // TODO(kschimpf) Stop ignoring alignment specification. 764*03ce13f7SAndroid Build Coastguard Worker (void)Align; 765*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 766*03ce13f7SAndroid Build Coastguard Worker } 767*03ce13f7SAndroid Build Coastguard Worker Variable *getRmwBeacon() const; 768*03ce13f7SAndroid Build Coastguard Worker void setRmwBeacon(Variable *Beacon); isMemoryWrite()769*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return true; } 770*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)771*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } 772*03ce13f7SAndroid Build Coastguard Worker 773*03ce13f7SAndroid Build Coastguard Worker private: 774*03ce13f7SAndroid Build Coastguard Worker InstStore(Cfg *Func, Operand *Data, Operand *Addr); 775*03ce13f7SAndroid Build Coastguard Worker }; 776*03ce13f7SAndroid Build Coastguard Worker 777*03ce13f7SAndroid Build Coastguard Worker /// Switch instruction. The single source operand is captured as getSrc(0). 778*03ce13f7SAndroid Build Coastguard Worker class InstSwitch : public InstHighLevel { 779*03ce13f7SAndroid Build Coastguard Worker InstSwitch() = delete; 780*03ce13f7SAndroid Build Coastguard Worker InstSwitch(const InstSwitch &) = delete; 781*03ce13f7SAndroid Build Coastguard Worker InstSwitch &operator=(const InstSwitch &) = delete; 782*03ce13f7SAndroid Build Coastguard Worker 783*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,SizeT NumCases,Operand * Source,CfgNode * LabelDefault)784*03ce13f7SAndroid Build Coastguard Worker static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 785*03ce13f7SAndroid Build Coastguard Worker CfgNode *LabelDefault) { 786*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstSwitch>()) 787*03ce13f7SAndroid Build Coastguard Worker InstSwitch(Func, NumCases, Source, LabelDefault); 788*03ce13f7SAndroid Build Coastguard Worker } getComparison()789*03ce13f7SAndroid Build Coastguard Worker Operand *getComparison() const { return getSrc(0); } getLabelDefault()790*03ce13f7SAndroid Build Coastguard Worker CfgNode *getLabelDefault() const { return LabelDefault; } getNumCases()791*03ce13f7SAndroid Build Coastguard Worker SizeT getNumCases() const { return NumCases; } getValue(SizeT I)792*03ce13f7SAndroid Build Coastguard Worker uint64_t getValue(SizeT I) const { 793*03ce13f7SAndroid Build Coastguard Worker assert(I < NumCases); 794*03ce13f7SAndroid Build Coastguard Worker return Values[I]; 795*03ce13f7SAndroid Build Coastguard Worker } getLabel(SizeT I)796*03ce13f7SAndroid Build Coastguard Worker CfgNode *getLabel(SizeT I) const { 797*03ce13f7SAndroid Build Coastguard Worker assert(I < NumCases); 798*03ce13f7SAndroid Build Coastguard Worker return Labels[I]; 799*03ce13f7SAndroid Build Coastguard Worker } 800*03ce13f7SAndroid Build Coastguard Worker void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 801*03ce13f7SAndroid Build Coastguard Worker NodeList getTerminatorEdges() const override; 802*03ce13f7SAndroid Build Coastguard Worker bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; isMemoryWrite()803*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 804*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)805*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } 806*03ce13f7SAndroid Build Coastguard Worker 807*03ce13f7SAndroid Build Coastguard Worker private: 808*03ce13f7SAndroid Build Coastguard Worker InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); destroy(Cfg * Func)809*03ce13f7SAndroid Build Coastguard Worker void destroy(Cfg *Func) override { 810*03ce13f7SAndroid Build Coastguard Worker Func->deallocateArrayOf<uint64_t>(Values); 811*03ce13f7SAndroid Build Coastguard Worker Func->deallocateArrayOf<CfgNode *>(Labels); 812*03ce13f7SAndroid Build Coastguard Worker Inst::destroy(Func); 813*03ce13f7SAndroid Build Coastguard Worker } 814*03ce13f7SAndroid Build Coastguard Worker 815*03ce13f7SAndroid Build Coastguard Worker CfgNode *LabelDefault; 816*03ce13f7SAndroid Build Coastguard Worker SizeT NumCases; /// not including the default case 817*03ce13f7SAndroid Build Coastguard Worker uint64_t *Values; /// size is NumCases 818*03ce13f7SAndroid Build Coastguard Worker CfgNode **Labels; /// size is NumCases 819*03ce13f7SAndroid Build Coastguard Worker }; 820*03ce13f7SAndroid Build Coastguard Worker 821*03ce13f7SAndroid Build Coastguard Worker /// Unreachable instruction. This is a terminator instruction with no operands. 822*03ce13f7SAndroid Build Coastguard Worker class InstUnreachable : public InstHighLevel { 823*03ce13f7SAndroid Build Coastguard Worker InstUnreachable() = delete; 824*03ce13f7SAndroid Build Coastguard Worker InstUnreachable(const InstUnreachable &) = delete; 825*03ce13f7SAndroid Build Coastguard Worker InstUnreachable &operator=(const InstUnreachable &) = delete; 826*03ce13f7SAndroid Build Coastguard Worker 827*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func)828*03ce13f7SAndroid Build Coastguard Worker static InstUnreachable *create(Cfg *Func) { 829*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 830*03ce13f7SAndroid Build Coastguard Worker } getTerminatorEdges()831*03ce13f7SAndroid Build Coastguard Worker NodeList getTerminatorEdges() const override { return NodeList(); } isMemoryWrite()832*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 833*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)834*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 835*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == Unreachable; 836*03ce13f7SAndroid Build Coastguard Worker } 837*03ce13f7SAndroid Build Coastguard Worker 838*03ce13f7SAndroid Build Coastguard Worker private: 839*03ce13f7SAndroid Build Coastguard Worker explicit InstUnreachable(Cfg *Func); 840*03ce13f7SAndroid Build Coastguard Worker }; 841*03ce13f7SAndroid Build Coastguard Worker 842*03ce13f7SAndroid Build Coastguard Worker /// FakeDef instruction. This creates a fake definition of a variable, which is 843*03ce13f7SAndroid Build Coastguard Worker /// how we represent the case when an instruction produces multiple results. 844*03ce13f7SAndroid Build Coastguard Worker /// This doesn't happen with high-level ICE instructions, but might with lowered 845*03ce13f7SAndroid Build Coastguard Worker /// instructions. For example, this would be a way to represent condition flags 846*03ce13f7SAndroid Build Coastguard Worker /// being modified by an instruction. 847*03ce13f7SAndroid Build Coastguard Worker /// 848*03ce13f7SAndroid Build Coastguard Worker /// It's generally useful to set the optional source operand to be the dest 849*03ce13f7SAndroid Build Coastguard Worker /// variable of the instruction that actually produces the FakeDef dest. 850*03ce13f7SAndroid Build Coastguard Worker /// Otherwise, the original instruction could be dead-code eliminated if its 851*03ce13f7SAndroid Build Coastguard Worker /// dest operand is unused, and therefore the FakeDef dest wouldn't be properly 852*03ce13f7SAndroid Build Coastguard Worker /// initialized. 853*03ce13f7SAndroid Build Coastguard Worker class InstFakeDef : public InstHighLevel { 854*03ce13f7SAndroid Build Coastguard Worker InstFakeDef() = delete; 855*03ce13f7SAndroid Build Coastguard Worker InstFakeDef(const InstFakeDef &) = delete; 856*03ce13f7SAndroid Build Coastguard Worker InstFakeDef &operator=(const InstFakeDef &) = delete; 857*03ce13f7SAndroid Build Coastguard Worker 858*03ce13f7SAndroid Build Coastguard Worker public: 859*03ce13f7SAndroid Build Coastguard Worker static InstFakeDef *create(Cfg *Func, Variable *Dest, 860*03ce13f7SAndroid Build Coastguard Worker Variable *Src = nullptr) { 861*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 862*03ce13f7SAndroid Build Coastguard Worker } 863*03ce13f7SAndroid Build Coastguard Worker void emit(const Cfg *Func) const override; emitIAS(const Cfg *)864*03ce13f7SAndroid Build Coastguard Worker void emitIAS(const Cfg * /* Func */) const override {} isMemoryWrite()865*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 866*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)867*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } 868*03ce13f7SAndroid Build Coastguard Worker 869*03ce13f7SAndroid Build Coastguard Worker private: 870*03ce13f7SAndroid Build Coastguard Worker InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 871*03ce13f7SAndroid Build Coastguard Worker }; 872*03ce13f7SAndroid Build Coastguard Worker 873*03ce13f7SAndroid Build Coastguard Worker /// FakeUse instruction. This creates a fake use of a variable, to keep the 874*03ce13f7SAndroid Build Coastguard Worker /// instruction that produces that variable from being dead-code eliminated. 875*03ce13f7SAndroid Build Coastguard Worker /// This is useful in a variety of lowering situations. The FakeUse instruction 876*03ce13f7SAndroid Build Coastguard Worker /// has no dest, so it can itself never be dead-code eliminated. A weight can 877*03ce13f7SAndroid Build Coastguard Worker /// be provided to provide extra bias to the register allocator - for simplicity 878*03ce13f7SAndroid Build Coastguard Worker /// of implementation, weight=N is handled by holding N copies of the variable 879*03ce13f7SAndroid Build Coastguard Worker /// as source operands. 880*03ce13f7SAndroid Build Coastguard Worker class InstFakeUse : public InstHighLevel { 881*03ce13f7SAndroid Build Coastguard Worker InstFakeUse() = delete; 882*03ce13f7SAndroid Build Coastguard Worker InstFakeUse(const InstFakeUse &) = delete; 883*03ce13f7SAndroid Build Coastguard Worker InstFakeUse &operator=(const InstFakeUse &) = delete; 884*03ce13f7SAndroid Build Coastguard Worker 885*03ce13f7SAndroid Build Coastguard Worker public: 886*03ce13f7SAndroid Build Coastguard Worker static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { 887*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); 888*03ce13f7SAndroid Build Coastguard Worker } 889*03ce13f7SAndroid Build Coastguard Worker void emit(const Cfg *Func) const override; emitIAS(const Cfg *)890*03ce13f7SAndroid Build Coastguard Worker void emitIAS(const Cfg * /* Func */) const override {} isMemoryWrite()891*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 892*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)893*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } 894*03ce13f7SAndroid Build Coastguard Worker 895*03ce13f7SAndroid Build Coastguard Worker private: 896*03ce13f7SAndroid Build Coastguard Worker InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); 897*03ce13f7SAndroid Build Coastguard Worker }; 898*03ce13f7SAndroid Build Coastguard Worker 899*03ce13f7SAndroid Build Coastguard Worker /// FakeKill instruction. This "kills" a set of variables by modeling a trivial 900*03ce13f7SAndroid Build Coastguard Worker /// live range at this instruction for each (implicit) variable. The primary use 901*03ce13f7SAndroid Build Coastguard Worker /// is to indicate that scratch registers are killed after a call, so that the 902*03ce13f7SAndroid Build Coastguard Worker /// register allocator won't assign a scratch register to a variable whose live 903*03ce13f7SAndroid Build Coastguard Worker /// range spans a call. 904*03ce13f7SAndroid Build Coastguard Worker /// 905*03ce13f7SAndroid Build Coastguard Worker /// The FakeKill instruction also holds a pointer to the instruction that kills 906*03ce13f7SAndroid Build Coastguard Worker /// the set of variables, so that if that linked instruction gets dead-code 907*03ce13f7SAndroid Build Coastguard Worker /// eliminated, the FakeKill instruction will as well. 908*03ce13f7SAndroid Build Coastguard Worker class InstFakeKill : public InstHighLevel { 909*03ce13f7SAndroid Build Coastguard Worker InstFakeKill() = delete; 910*03ce13f7SAndroid Build Coastguard Worker InstFakeKill(const InstFakeKill &) = delete; 911*03ce13f7SAndroid Build Coastguard Worker InstFakeKill &operator=(const InstFakeKill &) = delete; 912*03ce13f7SAndroid Build Coastguard Worker 913*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,const Inst * Linked)914*03ce13f7SAndroid Build Coastguard Worker static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 915*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 916*03ce13f7SAndroid Build Coastguard Worker } getLinked()917*03ce13f7SAndroid Build Coastguard Worker const Inst *getLinked() const { return Linked; } 918*03ce13f7SAndroid Build Coastguard Worker void emit(const Cfg *Func) const override; emitIAS(const Cfg *)919*03ce13f7SAndroid Build Coastguard Worker void emitIAS(const Cfg * /* Func */) const override {} isMemoryWrite()920*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 921*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)922*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 923*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == FakeKill; 924*03ce13f7SAndroid Build Coastguard Worker } 925*03ce13f7SAndroid Build Coastguard Worker 926*03ce13f7SAndroid Build Coastguard Worker private: 927*03ce13f7SAndroid Build Coastguard Worker InstFakeKill(Cfg *Func, const Inst *Linked); 928*03ce13f7SAndroid Build Coastguard Worker 929*03ce13f7SAndroid Build Coastguard Worker /// This instruction is ignored if Linked->isDeleted() is true. 930*03ce13f7SAndroid Build Coastguard Worker const Inst *Linked; 931*03ce13f7SAndroid Build Coastguard Worker }; 932*03ce13f7SAndroid Build Coastguard Worker 933*03ce13f7SAndroid Build Coastguard Worker /// ShuffleVector instruction. This represents a shuffle operation on vector 934*03ce13f7SAndroid Build Coastguard Worker /// types. This instruction is not part of the PNaCl bitcode: it is generated 935*03ce13f7SAndroid Build Coastguard Worker /// by Subzero when it matches the pattern used by pnacl-clang when compiling 936*03ce13f7SAndroid Build Coastguard Worker /// to bitcode. 937*03ce13f7SAndroid Build Coastguard Worker class InstShuffleVector : public InstHighLevel { 938*03ce13f7SAndroid Build Coastguard Worker InstShuffleVector() = delete; 939*03ce13f7SAndroid Build Coastguard Worker InstShuffleVector(const InstShuffleVector &) = delete; 940*03ce13f7SAndroid Build Coastguard Worker InstShuffleVector &operator=(const InstShuffleVector &) = delete; 941*03ce13f7SAndroid Build Coastguard Worker 942*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1)943*03ce13f7SAndroid Build Coastguard Worker static InstShuffleVector *create(Cfg *Func, Variable *Dest, Operand *Src0, 944*03ce13f7SAndroid Build Coastguard Worker Operand *Src1) { 945*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstShuffleVector>()) 946*03ce13f7SAndroid Build Coastguard Worker InstShuffleVector(Func, Dest, Src0, Src1); 947*03ce13f7SAndroid Build Coastguard Worker } 948*03ce13f7SAndroid Build Coastguard Worker getNumIndexes()949*03ce13f7SAndroid Build Coastguard Worker SizeT getNumIndexes() const { return NumIndexes; } 950*03ce13f7SAndroid Build Coastguard Worker addIndex(ConstantInteger32 * Index)951*03ce13f7SAndroid Build Coastguard Worker void addIndex(ConstantInteger32 *Index) { 952*03ce13f7SAndroid Build Coastguard Worker assert(CurrentIndex < NumIndexes); 953*03ce13f7SAndroid Build Coastguard Worker Indexes[CurrentIndex++] = Index; 954*03ce13f7SAndroid Build Coastguard Worker } 955*03ce13f7SAndroid Build Coastguard Worker getIndex(SizeT Pos)956*03ce13f7SAndroid Build Coastguard Worker ConstantInteger32 *getIndex(SizeT Pos) const { 957*03ce13f7SAndroid Build Coastguard Worker assert(Pos < NumIndexes); 958*03ce13f7SAndroid Build Coastguard Worker return Indexes[Pos]; 959*03ce13f7SAndroid Build Coastguard Worker } 960*03ce13f7SAndroid Build Coastguard Worker getIndexValue(SizeT Pos)961*03ce13f7SAndroid Build Coastguard Worker int32_t getIndexValue(SizeT Pos) const { return getIndex(Pos)->getValue(); } 962*03ce13f7SAndroid Build Coastguard Worker indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3)963*03ce13f7SAndroid Build Coastguard Worker bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3) const { 964*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT ExpectedNumElements = 4; 965*03ce13f7SAndroid Build Coastguard Worker assert(ExpectedNumElements == getNumIndexes()); 966*03ce13f7SAndroid Build Coastguard Worker (void)ExpectedNumElements; 967*03ce13f7SAndroid Build Coastguard Worker 968*03ce13f7SAndroid Build Coastguard Worker return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 969*03ce13f7SAndroid Build Coastguard Worker getIndexValue(2) == i2 && getIndexValue(3) == i3; 970*03ce13f7SAndroid Build Coastguard Worker } 971*03ce13f7SAndroid Build Coastguard Worker indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3,int32_t i4,int32_t i5,int32_t i6,int32_t i7)972*03ce13f7SAndroid Build Coastguard Worker bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4, 973*03ce13f7SAndroid Build Coastguard Worker int32_t i5, int32_t i6, int32_t i7) const { 974*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT ExpectedNumElements = 8; 975*03ce13f7SAndroid Build Coastguard Worker assert(ExpectedNumElements == getNumIndexes()); 976*03ce13f7SAndroid Build Coastguard Worker (void)ExpectedNumElements; 977*03ce13f7SAndroid Build Coastguard Worker 978*03ce13f7SAndroid Build Coastguard Worker return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 979*03ce13f7SAndroid Build Coastguard Worker getIndexValue(2) == i2 && getIndexValue(3) == i3 && 980*03ce13f7SAndroid Build Coastguard Worker getIndexValue(4) == i4 && getIndexValue(5) == i5 && 981*03ce13f7SAndroid Build Coastguard Worker getIndexValue(6) == i6 && getIndexValue(7) == i7; 982*03ce13f7SAndroid Build Coastguard Worker } 983*03ce13f7SAndroid Build Coastguard Worker indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3,int32_t i4,int32_t i5,int32_t i6,int32_t i7,int32_t i8,int32_t i9,int32_t i10,int32_t i11,int32_t i12,int32_t i13,int32_t i14,int32_t i15)984*03ce13f7SAndroid Build Coastguard Worker bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4, 985*03ce13f7SAndroid Build Coastguard Worker int32_t i5, int32_t i6, int32_t i7, int32_t i8, int32_t i9, 986*03ce13f7SAndroid Build Coastguard Worker int32_t i10, int32_t i11, int32_t i12, int32_t i13, 987*03ce13f7SAndroid Build Coastguard Worker int32_t i14, int32_t i15) const { 988*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT ExpectedNumElements = 16; 989*03ce13f7SAndroid Build Coastguard Worker assert(ExpectedNumElements == getNumIndexes()); 990*03ce13f7SAndroid Build Coastguard Worker (void)ExpectedNumElements; 991*03ce13f7SAndroid Build Coastguard Worker 992*03ce13f7SAndroid Build Coastguard Worker return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 993*03ce13f7SAndroid Build Coastguard Worker getIndexValue(2) == i2 && getIndexValue(3) == i3 && 994*03ce13f7SAndroid Build Coastguard Worker getIndexValue(4) == i4 && getIndexValue(5) == i5 && 995*03ce13f7SAndroid Build Coastguard Worker getIndexValue(6) == i6 && getIndexValue(7) == i7 && 996*03ce13f7SAndroid Build Coastguard Worker getIndexValue(8) == i8 && getIndexValue(9) == i9 && 997*03ce13f7SAndroid Build Coastguard Worker getIndexValue(10) == i10 && getIndexValue(11) == i11 && 998*03ce13f7SAndroid Build Coastguard Worker getIndexValue(12) == i12 && getIndexValue(13) == i13 && 999*03ce13f7SAndroid Build Coastguard Worker getIndexValue(14) == i14 && getIndexValue(15) == i15; 1000*03ce13f7SAndroid Build Coastguard Worker } 1001*03ce13f7SAndroid Build Coastguard Worker isMemoryWrite()1002*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 1003*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)1004*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 1005*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == ShuffleVector; 1006*03ce13f7SAndroid Build Coastguard Worker } 1007*03ce13f7SAndroid Build Coastguard Worker 1008*03ce13f7SAndroid Build Coastguard Worker private: 1009*03ce13f7SAndroid Build Coastguard Worker InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1); 1010*03ce13f7SAndroid Build Coastguard Worker destroy(Cfg * Func)1011*03ce13f7SAndroid Build Coastguard Worker void destroy(Cfg *Func) override { 1012*03ce13f7SAndroid Build Coastguard Worker Func->deallocateArrayOf<ConstantInteger32 *>(Indexes); 1013*03ce13f7SAndroid Build Coastguard Worker Inst::destroy(Func); 1014*03ce13f7SAndroid Build Coastguard Worker } 1015*03ce13f7SAndroid Build Coastguard Worker 1016*03ce13f7SAndroid Build Coastguard Worker ConstantInteger32 **Indexes; 1017*03ce13f7SAndroid Build Coastguard Worker SizeT CurrentIndex = 0; 1018*03ce13f7SAndroid Build Coastguard Worker const SizeT NumIndexes; 1019*03ce13f7SAndroid Build Coastguard Worker }; 1020*03ce13f7SAndroid Build Coastguard Worker 1021*03ce13f7SAndroid Build Coastguard Worker /// JumpTable instruction. This represents a jump table that will be stored in 1022*03ce13f7SAndroid Build Coastguard Worker /// the .rodata section. This is used to track and repoint the target CfgNodes 1023*03ce13f7SAndroid Build Coastguard Worker /// which may change, for example due to splitting for phi lowering. 1024*03ce13f7SAndroid Build Coastguard Worker class InstJumpTable : public InstHighLevel { 1025*03ce13f7SAndroid Build Coastguard Worker InstJumpTable() = delete; 1026*03ce13f7SAndroid Build Coastguard Worker InstJumpTable(const InstJumpTable &) = delete; 1027*03ce13f7SAndroid Build Coastguard Worker InstJumpTable &operator=(const InstJumpTable &) = delete; 1028*03ce13f7SAndroid Build Coastguard Worker 1029*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func,SizeT NumTargets,CfgNode * Default)1030*03ce13f7SAndroid Build Coastguard Worker static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 1031*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstJumpTable>()) 1032*03ce13f7SAndroid Build Coastguard Worker InstJumpTable(Func, NumTargets, Default); 1033*03ce13f7SAndroid Build Coastguard Worker } addTarget(SizeT TargetIndex,CfgNode * Target)1034*03ce13f7SAndroid Build Coastguard Worker void addTarget(SizeT TargetIndex, CfgNode *Target) { 1035*03ce13f7SAndroid Build Coastguard Worker assert(TargetIndex < NumTargets); 1036*03ce13f7SAndroid Build Coastguard Worker Targets[TargetIndex] = Target; 1037*03ce13f7SAndroid Build Coastguard Worker } 1038*03ce13f7SAndroid Build Coastguard Worker bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; getId()1039*03ce13f7SAndroid Build Coastguard Worker SizeT getId() const { return Id; } getNumTargets()1040*03ce13f7SAndroid Build Coastguard Worker SizeT getNumTargets() const { return NumTargets; } getTarget(SizeT I)1041*03ce13f7SAndroid Build Coastguard Worker CfgNode *getTarget(SizeT I) const { 1042*03ce13f7SAndroid Build Coastguard Worker assert(I < NumTargets); 1043*03ce13f7SAndroid Build Coastguard Worker return Targets[I]; 1044*03ce13f7SAndroid Build Coastguard Worker } isMemoryWrite()1045*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 1046*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)1047*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 1048*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == JumpTable; 1049*03ce13f7SAndroid Build Coastguard Worker } 1050*03ce13f7SAndroid Build Coastguard Worker // Creates a JumpTableData struct (used for ELF emission) that represents this 1051*03ce13f7SAndroid Build Coastguard Worker // InstJumpTable. 1052*03ce13f7SAndroid Build Coastguard Worker JumpTableData toJumpTableData(Assembler *Asm) const; 1053*03ce13f7SAndroid Build Coastguard Worker 1054*03ce13f7SAndroid Build Coastguard Worker // InstJumpTable is just a placeholder for the switch targets, and it does not 1055*03ce13f7SAndroid Build Coastguard Worker // need to emit any code, so we redefine emit and emitIAS to do nothing. emit(const Cfg *)1056*03ce13f7SAndroid Build Coastguard Worker void emit(const Cfg *) const override {} emitIAS(const Cfg *)1057*03ce13f7SAndroid Build Coastguard Worker void emitIAS(const Cfg * /* Func */) const override {} 1058*03ce13f7SAndroid Build Coastguard Worker getName()1059*03ce13f7SAndroid Build Coastguard Worker const std::string getName() const { 1060*03ce13f7SAndroid Build Coastguard Worker assert(Name.hasStdString()); 1061*03ce13f7SAndroid Build Coastguard Worker return Name.toString(); 1062*03ce13f7SAndroid Build Coastguard Worker } 1063*03ce13f7SAndroid Build Coastguard Worker getSectionName()1064*03ce13f7SAndroid Build Coastguard Worker std::string getSectionName() const { 1065*03ce13f7SAndroid Build Coastguard Worker return JumpTableData::createSectionName(FuncName); 1066*03ce13f7SAndroid Build Coastguard Worker } 1067*03ce13f7SAndroid Build Coastguard Worker 1068*03ce13f7SAndroid Build Coastguard Worker private: 1069*03ce13f7SAndroid Build Coastguard Worker InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); destroy(Cfg * Func)1070*03ce13f7SAndroid Build Coastguard Worker void destroy(Cfg *Func) override { 1071*03ce13f7SAndroid Build Coastguard Worker Func->deallocateArrayOf<CfgNode *>(Targets); 1072*03ce13f7SAndroid Build Coastguard Worker Inst::destroy(Func); 1073*03ce13f7SAndroid Build Coastguard Worker } 1074*03ce13f7SAndroid Build Coastguard Worker 1075*03ce13f7SAndroid Build Coastguard Worker const SizeT Id; 1076*03ce13f7SAndroid Build Coastguard Worker const SizeT NumTargets; 1077*03ce13f7SAndroid Build Coastguard Worker CfgNode **Targets; 1078*03ce13f7SAndroid Build Coastguard Worker GlobalString Name; // This JumpTable's name in the output. 1079*03ce13f7SAndroid Build Coastguard Worker GlobalString FuncName; 1080*03ce13f7SAndroid Build Coastguard Worker }; 1081*03ce13f7SAndroid Build Coastguard Worker 1082*03ce13f7SAndroid Build Coastguard Worker /// This instruction inserts an unconditional breakpoint. 1083*03ce13f7SAndroid Build Coastguard Worker /// 1084*03ce13f7SAndroid Build Coastguard Worker /// On x86, this assembles into an INT 3 instruction. 1085*03ce13f7SAndroid Build Coastguard Worker /// 1086*03ce13f7SAndroid Build Coastguard Worker /// This instruction is primarily meant for debugging the code generator. 1087*03ce13f7SAndroid Build Coastguard Worker class InstBreakpoint : public InstHighLevel { 1088*03ce13f7SAndroid Build Coastguard Worker public: 1089*03ce13f7SAndroid Build Coastguard Worker InstBreakpoint() = delete; 1090*03ce13f7SAndroid Build Coastguard Worker InstBreakpoint(const InstBreakpoint &) = delete; 1091*03ce13f7SAndroid Build Coastguard Worker InstBreakpoint &operator=(const InstBreakpoint &) = delete; 1092*03ce13f7SAndroid Build Coastguard Worker 1093*03ce13f7SAndroid Build Coastguard Worker explicit InstBreakpoint(Cfg *Func); isMemoryWrite()1094*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { return false; } 1095*03ce13f7SAndroid Build Coastguard Worker 1096*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func)1097*03ce13f7SAndroid Build Coastguard Worker static InstBreakpoint *create(Cfg *Func) { 1098*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func); 1099*03ce13f7SAndroid Build Coastguard Worker } 1100*03ce13f7SAndroid Build Coastguard Worker classof(const Inst * Instr)1101*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { 1102*03ce13f7SAndroid Build Coastguard Worker return Instr->getKind() == Breakpoint; 1103*03ce13f7SAndroid Build Coastguard Worker } 1104*03ce13f7SAndroid Build Coastguard Worker }; 1105*03ce13f7SAndroid Build Coastguard Worker 1106*03ce13f7SAndroid Build Coastguard Worker /// The Target instruction is the base class for all target-specific 1107*03ce13f7SAndroid Build Coastguard Worker /// instructions. 1108*03ce13f7SAndroid Build Coastguard Worker class InstTarget : public Inst { 1109*03ce13f7SAndroid Build Coastguard Worker InstTarget() = delete; 1110*03ce13f7SAndroid Build Coastguard Worker InstTarget(const InstTarget &) = delete; 1111*03ce13f7SAndroid Build Coastguard Worker InstTarget &operator=(const InstTarget &) = delete; 1112*03ce13f7SAndroid Build Coastguard Worker 1113*03ce13f7SAndroid Build Coastguard Worker public: getEmitInstCount()1114*03ce13f7SAndroid Build Coastguard Worker uint32_t getEmitInstCount() const override { return 1; } isMemoryWrite()1115*03ce13f7SAndroid Build Coastguard Worker bool isMemoryWrite() const override { 1116*03ce13f7SAndroid Build Coastguard Worker return true; // conservative answer 1117*03ce13f7SAndroid Build Coastguard Worker } 1118*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const override; classof(const Inst * Instr)1119*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } 1120*03ce13f7SAndroid Build Coastguard Worker 1121*03ce13f7SAndroid Build Coastguard Worker protected: InstTarget(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)1122*03ce13f7SAndroid Build Coastguard Worker InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 1123*03ce13f7SAndroid Build Coastguard Worker : Inst(Func, Kind, MaxSrcs, Dest) { 1124*03ce13f7SAndroid Build Coastguard Worker assert(Kind >= Target); 1125*03ce13f7SAndroid Build Coastguard Worker assert(Kind <= Target_Max); 1126*03ce13f7SAndroid Build Coastguard Worker } 1127*03ce13f7SAndroid Build Coastguard Worker }; 1128*03ce13f7SAndroid Build Coastguard Worker 1129*03ce13f7SAndroid Build Coastguard Worker bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 1130*03ce13f7SAndroid Build Coastguard Worker 1131*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 1132*03ce13f7SAndroid Build Coastguard Worker 1133*03ce13f7SAndroid Build Coastguard Worker #ifdef PNACL_LLVM 1134*03ce13f7SAndroid Build Coastguard Worker namespace llvm { 1135*03ce13f7SAndroid Build Coastguard Worker 1136*03ce13f7SAndroid Build Coastguard Worker /// Override the default ilist traits so that Inst's private ctor and deleted 1137*03ce13f7SAndroid Build Coastguard Worker /// dtor aren't invoked. 1138*03ce13f7SAndroid Build Coastguard Worker template <> 1139*03ce13f7SAndroid Build Coastguard Worker struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 1140*03ce13f7SAndroid Build Coastguard Worker Ice::Inst *createSentinel() const { 1141*03ce13f7SAndroid Build Coastguard Worker return static_cast<Ice::Inst *>(&Sentinel); 1142*03ce13f7SAndroid Build Coastguard Worker } 1143*03ce13f7SAndroid Build Coastguard Worker static void destroySentinel(Ice::Inst *) {} 1144*03ce13f7SAndroid Build Coastguard Worker Ice::Inst *provideInitialHead() const { return createSentinel(); } 1145*03ce13f7SAndroid Build Coastguard Worker Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 1146*03ce13f7SAndroid Build Coastguard Worker static void noteHead(Ice::Inst *, Ice::Inst *) {} 1147*03ce13f7SAndroid Build Coastguard Worker void deleteNode(Ice::Inst *) {} 1148*03ce13f7SAndroid Build Coastguard Worker 1149*03ce13f7SAndroid Build Coastguard Worker private: 1150*03ce13f7SAndroid Build Coastguard Worker mutable ilist_half_node<Ice::Inst> Sentinel; 1151*03ce13f7SAndroid Build Coastguard Worker }; 1152*03ce13f7SAndroid Build Coastguard Worker 1153*03ce13f7SAndroid Build Coastguard Worker } // end of namespace llvm 1154*03ce13f7SAndroid Build Coastguard Worker #endif // PNACL_LLVM 1155*03ce13f7SAndroid Build Coastguard Worker 1156*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 1157*03ce13f7SAndroid Build Coastguard Worker 1158*03ce13f7SAndroid Build Coastguard Worker inline InstList::iterator instToIterator(Inst *Instr) { 1159*03ce13f7SAndroid Build Coastguard Worker #ifdef PNACL_LLVM 1160*03ce13f7SAndroid Build Coastguard Worker return Instr; 1161*03ce13f7SAndroid Build Coastguard Worker #else // !PNACL_LLVM 1162*03ce13f7SAndroid Build Coastguard Worker return Instr->getIterator(); 1163*03ce13f7SAndroid Build Coastguard Worker #endif // !PNACL_LLVM 1164*03ce13f7SAndroid Build Coastguard Worker } 1165*03ce13f7SAndroid Build Coastguard Worker 1166*03ce13f7SAndroid Build Coastguard Worker inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; } 1167*03ce13f7SAndroid Build Coastguard Worker 1168*03ce13f7SAndroid Build Coastguard Worker inline const Inst *iteratorToInst(InstList::const_iterator Iter) { 1169*03ce13f7SAndroid Build Coastguard Worker return &*Iter; 1170*03ce13f7SAndroid Build Coastguard Worker } 1171*03ce13f7SAndroid Build Coastguard Worker 1172*03ce13f7SAndroid Build Coastguard Worker inline InstList::iterator 1173*03ce13f7SAndroid Build Coastguard Worker reverseToForwardIterator(InstList::reverse_iterator RI) { 1174*03ce13f7SAndroid Build Coastguard Worker #ifdef PNACL_LLVM 1175*03ce13f7SAndroid Build Coastguard Worker return RI.base(); 1176*03ce13f7SAndroid Build Coastguard Worker #else // !PNACL_LLVM 1177*03ce13f7SAndroid Build Coastguard Worker return ++RI.getReverse(); 1178*03ce13f7SAndroid Build Coastguard Worker #endif // !PNACL_LLVM 1179*03ce13f7SAndroid Build Coastguard Worker } 1180*03ce13f7SAndroid Build Coastguard Worker 1181*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 1182*03ce13f7SAndroid Build Coastguard Worker 1183*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEINST_H 1184