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