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