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 getIndexValue(SizeT Pos)1000 int32_t getIndexValue(SizeT Pos) const { return getIndex(Pos)->getValue(); } 1001 indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3)1002 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3) const { 1003 static constexpr SizeT ExpectedNumElements = 4; 1004 assert(ExpectedNumElements == getNumIndexes()); 1005 (void)ExpectedNumElements; 1006 1007 return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 1008 getIndexValue(2) == i2 && getIndexValue(3) == i3; 1009 } 1010 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)1011 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4, 1012 int32_t i5, int32_t i6, int32_t i7) const { 1013 static constexpr SizeT ExpectedNumElements = 8; 1014 assert(ExpectedNumElements == getNumIndexes()); 1015 (void)ExpectedNumElements; 1016 1017 return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 1018 getIndexValue(2) == i2 && getIndexValue(3) == i3 && 1019 getIndexValue(4) == i4 && getIndexValue(5) == i5 && 1020 getIndexValue(6) == i6 && getIndexValue(7) == i7; 1021 } 1022 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)1023 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4, 1024 int32_t i5, int32_t i6, int32_t i7, int32_t i8, int32_t i9, 1025 int32_t i10, int32_t i11, int32_t i12, int32_t i13, 1026 int32_t i14, int32_t i15) const { 1027 static constexpr SizeT ExpectedNumElements = 16; 1028 assert(ExpectedNumElements == getNumIndexes()); 1029 (void)ExpectedNumElements; 1030 1031 return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 1032 getIndexValue(2) == i2 && getIndexValue(3) == i3 && 1033 getIndexValue(4) == i4 && getIndexValue(5) == i5 && 1034 getIndexValue(6) == i6 && getIndexValue(7) == i7 && 1035 getIndexValue(8) == i8 && getIndexValue(9) == i9 && 1036 getIndexValue(10) == i10 && getIndexValue(11) == i11 && 1037 getIndexValue(12) == i12 && getIndexValue(13) == i13 && 1038 getIndexValue(14) == i14 && getIndexValue(15) == i15; 1039 } 1040 isMemoryWrite()1041 bool isMemoryWrite() const override { return false; } 1042 void dump(const Cfg *Func) const override; classof(const Inst * Instr)1043 static bool classof(const Inst *Instr) { 1044 return Instr->getKind() == ShuffleVector; 1045 } 1046 1047 private: 1048 InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1); 1049 destroy(Cfg * Func)1050 void destroy(Cfg *Func) override { 1051 Func->deallocateArrayOf<ConstantInteger32 *>(Indexes); 1052 Inst::destroy(Func); 1053 } 1054 1055 ConstantInteger32 **Indexes; 1056 SizeT CurrentIndex = 0; 1057 const SizeT NumIndexes; 1058 }; 1059 1060 /// JumpTable instruction. This represents a jump table that will be stored in 1061 /// the .rodata section. This is used to track and repoint the target CfgNodes 1062 /// which may change, for example due to splitting for phi lowering. 1063 class InstJumpTable : public InstHighLevel { 1064 InstJumpTable() = delete; 1065 InstJumpTable(const InstJumpTable &) = delete; 1066 InstJumpTable &operator=(const InstJumpTable &) = delete; 1067 1068 public: create(Cfg * Func,SizeT NumTargets,CfgNode * Default)1069 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 1070 return new (Func->allocate<InstJumpTable>()) 1071 InstJumpTable(Func, NumTargets, Default); 1072 } addTarget(SizeT TargetIndex,CfgNode * Target)1073 void addTarget(SizeT TargetIndex, CfgNode *Target) { 1074 assert(TargetIndex < NumTargets); 1075 Targets[TargetIndex] = Target; 1076 } 1077 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; getId()1078 SizeT getId() const { return Id; } getNumTargets()1079 SizeT getNumTargets() const { return NumTargets; } getTarget(SizeT I)1080 CfgNode *getTarget(SizeT I) const { 1081 assert(I < NumTargets); 1082 return Targets[I]; 1083 } isMemoryWrite()1084 bool isMemoryWrite() const override { return false; } 1085 void dump(const Cfg *Func) const override; classof(const Inst * Instr)1086 static bool classof(const Inst *Instr) { 1087 return Instr->getKind() == JumpTable; 1088 } 1089 // Creates a JumpTableData struct (used for ELF emission) that represents this 1090 // InstJumpTable. 1091 JumpTableData toJumpTableData(Assembler *Asm) const; 1092 1093 // InstJumpTable is just a placeholder for the switch targets, and it does not 1094 // need to emit any code, so we redefine emit and emitIAS to do nothing. emit(const Cfg *)1095 void emit(const Cfg *) const override {} emitIAS(const Cfg *)1096 void emitIAS(const Cfg * /* Func */) const override {} 1097 getName()1098 const std::string getName() const { 1099 assert(Name.hasStdString()); 1100 return Name.toString(); 1101 } 1102 getSectionName()1103 std::string getSectionName() const { 1104 return JumpTableData::createSectionName(FuncName); 1105 } 1106 1107 private: 1108 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); destroy(Cfg * Func)1109 void destroy(Cfg *Func) override { 1110 Func->deallocateArrayOf<CfgNode *>(Targets); 1111 Inst::destroy(Func); 1112 } 1113 1114 const SizeT Id; 1115 const SizeT NumTargets; 1116 CfgNode **Targets; 1117 GlobalString Name; // This JumpTable's name in the output. 1118 GlobalString FuncName; 1119 }; 1120 1121 /// This instruction inserts an unconditional breakpoint. 1122 /// 1123 /// On x86, this assembles into an INT 3 instruction. 1124 /// 1125 /// This instruction is primarily meant for debugging the code generator. 1126 class InstBreakpoint : public InstHighLevel { 1127 public: 1128 InstBreakpoint() = delete; 1129 InstBreakpoint(const InstBreakpoint &) = delete; 1130 InstBreakpoint &operator=(const InstBreakpoint &) = delete; 1131 1132 explicit InstBreakpoint(Cfg *Func); isMemoryWrite()1133 bool isMemoryWrite() const override { return false; } 1134 1135 public: create(Cfg * Func)1136 static InstBreakpoint *create(Cfg *Func) { 1137 return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func); 1138 } 1139 classof(const Inst * Instr)1140 static bool classof(const Inst *Instr) { 1141 return Instr->getKind() == Breakpoint; 1142 } 1143 }; 1144 1145 /// The Target instruction is the base class for all target-specific 1146 /// instructions. 1147 class InstTarget : public Inst { 1148 InstTarget() = delete; 1149 InstTarget(const InstTarget &) = delete; 1150 InstTarget &operator=(const InstTarget &) = delete; 1151 1152 public: getEmitInstCount()1153 uint32_t getEmitInstCount() const override { return 1; } isMemoryWrite()1154 bool isMemoryWrite() const override { 1155 return true; // conservative answer 1156 } 1157 void dump(const Cfg *Func) const override; classof(const Inst * Instr)1158 static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } 1159 1160 protected: InstTarget(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)1161 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 1162 : Inst(Func, Kind, MaxSrcs, Dest) { 1163 assert(Kind >= Target); 1164 assert(Kind <= Target_Max); 1165 } 1166 }; 1167 1168 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 1169 1170 } // end of namespace Ice 1171 1172 #ifdef PNACL_LLVM 1173 namespace llvm { 1174 1175 /// Override the default ilist traits so that Inst's private ctor and deleted 1176 /// dtor aren't invoked. 1177 template <> 1178 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 1179 Ice::Inst *createSentinel() const { 1180 return static_cast<Ice::Inst *>(&Sentinel); 1181 } 1182 static void destroySentinel(Ice::Inst *) {} 1183 Ice::Inst *provideInitialHead() const { return createSentinel(); } 1184 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 1185 static void noteHead(Ice::Inst *, Ice::Inst *) {} 1186 void deleteNode(Ice::Inst *) {} 1187 1188 private: 1189 mutable ilist_half_node<Ice::Inst> Sentinel; 1190 }; 1191 1192 } // end of namespace llvm 1193 #endif // PNACL_LLVM 1194 1195 namespace Ice { 1196 1197 inline InstList::iterator instToIterator(Inst *Instr) { 1198 #ifdef PNACL_LLVM 1199 return Instr; 1200 #else // !PNACL_LLVM 1201 return Instr->getIterator(); 1202 #endif // !PNACL_LLVM 1203 } 1204 1205 inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; } 1206 1207 inline const Inst *iteratorToInst(InstList::const_iterator Iter) { 1208 return &*Iter; 1209 } 1210 1211 inline InstList::iterator 1212 reverseToForwardIterator(InstList::reverse_iterator RI) { 1213 #ifdef PNACL_LLVM 1214 return RI.base(); 1215 #else // !PNACL_LLVM 1216 return ++RI.getReverse(); 1217 #endif // !PNACL_LLVM 1218 } 1219 1220 } // end of namespace Ice 1221 1222 #endif // SUBZERO_SRC_ICEINST_H 1223