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