1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===//
3 // The Subzero Code Generator
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Declares the Inst class and its target-independent subclasses.
13 /// These represent the high-level Vanilla ICE instructions and map roughly 1:1
14 /// to LLVM instructions.
16 //===----------------------------------------------------------------------===//
18 #ifndef SUBZERO_SRC_ICEINST_H
19 #define SUBZERO_SRC_ICEINST_H
23 #include "IceInst.def"
24 #include "IceIntrinsics.h"
25 #include "IceOperand.h"
26 #include "IceSwitchLowering.h"
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.
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> {
42 Inst(const Inst &) = delete;
43 Inst &operator=(const Inst &) = delete;
47 // Arbitrary (alphabetical) order, except put Unreachable first.
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.
79 Target_Max = std::numeric_limits<uint8_t>::max(),
81 static_assert(Target <= Target_Max, "Must not be above max.");
82 InstKind getKind() const { return Kind; }
83 virtual const char *getInstName() const;
85 InstNumberT getNumber() const { return Number; }
86 void renumber(Cfg *Func);
91 NumberExtended = NumberInitial - 1
94 bool isDeleted() const { return Deleted; }
95 void setDeleted() { Deleted = true; }
96 void setDead(bool Value = true) { Dead = Value; }
99 bool hasSideEffects() const { return HasSideEffects; }
101 bool isDestRedefined() const { return IsDestRedefined; }
102 void setDestRedefined() { IsDestRedefined = true; }
104 Variable *getDest() const { return Dest; }
106 SizeT getSrcSize() const { return NumSrcs; }
107 Operand *getSrc(SizeT I) const {
108 assert(I < getSrcSize());
112 bool isLastUse(const Operand *Src) const;
113 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
115 /// Returns a list of out-edges corresponding to a terminator instruction,
116 /// which is the last instruction of the block. The list must not contain
118 virtual NodeList getTerminatorEdges() const {
119 // All valid terminator instructions override this method. For the default
120 // implementation, we assert in case some CfgNode is constructed without a
121 // terminator instruction at the end.
123 "getTerminatorEdges() called on a non-terminator instruction");
126 virtual bool isUnconditionalBranch() const { return false; }
127 /// If the instruction is a branch-type instruction with OldNode as a target,
128 /// repoint it to NewNode and return true, otherwise return false. Repoint all
129 /// instances of OldNode as a target.
130 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
136 /// Returns true if the instruction is equivalent to a simple
137 /// "var_dest=var_src" assignment where the dest and src are both variables.
138 virtual bool isVarAssign() const { return false; }
140 /// Returns true if the instruction has a possible side effect of changing
141 /// memory, in which case a memory load should not be reordered with respect
142 /// to this instruction. It should really be pure virtual, but we can't
143 /// because of g++ and llvm::ilist<>, so we implement it as
144 /// report_fatal_error().
145 virtual bool isMemoryWrite() const;
147 void livenessLightweight(Cfg *Func, LivenessBV &Live);
148 /// Calculates liveness for this instruction. Returns true if this instruction
149 /// is (tentatively) still live and should be retained, and false if this
150 /// instruction is (tentatively) dead and should be deleted. The decision is
151 /// tentative until the liveness dataflow algorithm has converged, and then a
152 /// separate pass permanently deletes dead instructions.
153 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
154 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
156 /// Get the number of native instructions that this instruction ultimately
157 /// emits. By default, high-level instructions don't result in any native
158 /// instructions, and a target-specific instruction results in a single native
160 virtual uint32_t getEmitInstCount() const { return 0; }
161 // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
162 // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
163 // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
164 // allow the abstract class Ice::Inst. The method should be declared
165 // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
166 // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
167 virtual void emit(const Cfg *) const {
168 llvm_unreachable("emit on abstract class");
170 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
171 virtual void dump(const Cfg *Func) const;
172 virtual void dumpExtras(const Cfg *Func) const;
173 void dumpDecorated(const Cfg *Func) const;
174 void emitSources(const Cfg *Func) const;
175 void dumpSources(const Cfg *Func) const;
176 void dumpDest(const Cfg *Func) const;
177 virtual bool isRedundantAssign() const { return false; }
179 virtual ~Inst() = default;
182 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
183 void addSource(Operand *Src) {
185 assert(NumSrcs < MaxSrcs);
186 Srcs[NumSrcs++] = Src;
188 void setLastUse(SizeT VarIndex) {
189 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
190 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
192 void resetLastUses() { LiveRangesEnded = 0; }
193 /// The destroy() method lets the instruction cleanly release any memory that
194 /// was allocated via the Cfg's allocator.
195 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
198 /// Number is the instruction number for describing live ranges.
200 /// Deleted means irrevocably deleted.
201 bool Deleted = false;
202 /// Dead means one of two things depending on context: (1) pending deletion
203 /// after liveness analysis converges, or (2) marked for deletion during
204 /// lowering due to a folded bool operation.
206 /// HasSideEffects means the instruction is something like a function call or
207 /// a volatile load that can't be removed even if its Dest variable is not
209 bool HasSideEffects = false;
210 /// IsDestRedefined indicates that this instruction is not the first
211 /// definition of Dest in the basic block. The effect is that liveness
212 /// analysis shouldn't consider this instruction to be the start of Dest's
213 /// live range; rather, there is some other instruction earlier in the basic
214 /// block with the same Dest. This is maintained because liveness analysis
215 /// has an invariant (primarily for performance reasons) that any Variable's
216 /// live range recorded in a basic block has at most one start and at most one
218 bool IsDestRedefined = false;
221 const SizeT MaxSrcs; // only used for assert
225 /// LiveRangesEnded marks which Variables' live ranges end in this
226 /// instruction. An instruction can have an arbitrary number of source
227 /// operands (e.g. a call instruction), and each source operand can contain 0
228 /// or 1 Variable (and target-specific operands could contain more than 1
229 /// Variable). All the variables in an instruction are conceptually flattened
230 /// and each variable is mapped to one bit position of the LiveRangesEnded bit
231 /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
232 /// tracked this way.
233 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
234 LREndedBits LiveRangesEnded;
237 class InstHighLevel : public Inst {
238 InstHighLevel() = delete;
239 InstHighLevel(const InstHighLevel &) = delete;
240 InstHighLevel &operator=(const InstHighLevel &) = delete;
243 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
244 : Inst(Func, Kind, MaxSrcs, Dest) {}
245 void emit(const Cfg * /*Func*/) const override {
246 llvm_unreachable("emit() called on a non-lowered instruction");
248 void emitIAS(const Cfg * /*Func*/) const override {
249 llvm_unreachable("emitIAS() called on a non-lowered instruction");
253 /// Alloca instruction. This captures the size in bytes as getSrc(0), and the
254 /// required alignment in bytes. The alignment must be either 0 (no alignment
255 /// required) or a power of 2.
256 class InstAlloca : public InstHighLevel {
257 InstAlloca() = delete;
258 InstAlloca(const InstAlloca &) = delete;
259 InstAlloca &operator=(const InstAlloca &) = delete;
262 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
263 uint32_t AlignInBytes) {
264 return new (Func->allocate<InstAlloca>())
265 InstAlloca(Func, Dest, ByteCount, AlignInBytes);
267 uint32_t getAlignInBytes() const { return AlignInBytes; }
268 Operand *getSizeInBytes() const { return getSrc(0); }
269 bool getKnownFrameOffset() const { return KnownFrameOffset; }
270 void setKnownFrameOffset() { KnownFrameOffset = true; }
271 bool isMemoryWrite() const override { return false; }
272 void dump(const Cfg *Func) const override;
273 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
276 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
277 uint32_t AlignInBytes);
279 const uint32_t AlignInBytes;
280 bool KnownFrameOffset = false;
283 /// Binary arithmetic instruction. The source operands are captured in getSrc(0)
285 class InstArithmetic : public InstHighLevel {
286 InstArithmetic() = delete;
287 InstArithmetic(const InstArithmetic &) = delete;
288 InstArithmetic &operator=(const InstArithmetic &) = delete;
292 #define X(tag, str, commutative) tag,
293 ICEINSTARITHMETIC_TABLE
298 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
299 Operand *Source1, Operand *Source2) {
300 return new (Func->allocate<InstArithmetic>())
301 InstArithmetic(Func, Op, Dest, Source1, Source2);
303 OpKind getOp() const { return Op; }
305 virtual const char *getInstName() const override;
307 static const char *getOpName(OpKind Op);
308 bool isCommutative() const;
309 bool isMemoryWrite() const override { return false; }
310 void dump(const Cfg *Func) const override;
311 static bool classof(const Inst *Instr) {
312 return Instr->getKind() == Arithmetic;
316 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
322 /// Assignment instruction. The source operand is captured in getSrc(0). This is
323 /// not part of the LLVM bitcode, but is a useful abstraction for some of the
324 /// lowering. E.g., if Phi instruction lowering happens before target lowering,
325 /// or for representing an Inttoptr instruction, or as an intermediate step for
326 /// lowering a Load instruction.
327 class InstAssign : public InstHighLevel {
328 InstAssign() = delete;
329 InstAssign(const InstAssign &) = delete;
330 InstAssign &operator=(const InstAssign &) = delete;
333 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
334 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
336 bool isVarAssign() const override;
337 bool isMemoryWrite() const override { return false; }
338 void dump(const Cfg *Func) const override;
339 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
342 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
345 /// Branch instruction. This represents both conditional and unconditional
347 class InstBr : public InstHighLevel {
349 InstBr(const InstBr &) = delete;
350 InstBr &operator=(const InstBr &) = delete;
353 /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
354 /// to an unconditional branch.
355 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
356 CfgNode *TargetFalse) {
357 return new (Func->allocate<InstBr>())
358 InstBr(Func, Source, TargetTrue, TargetFalse);
360 /// Create an unconditional branch.
361 static InstBr *create(Cfg *Func, CfgNode *Target) {
362 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
364 bool isUnconditional() const { return getTargetTrue() == nullptr; }
365 Operand *getCondition() const {
366 assert(!isUnconditional());
369 CfgNode *getTargetTrue() const { return TargetTrue; }
370 CfgNode *getTargetFalse() const { return TargetFalse; }
371 CfgNode *getTargetUnconditional() const {
372 assert(isUnconditional());
373 return getTargetFalse();
375 NodeList getTerminatorEdges() const override;
376 bool isUnconditionalBranch() const override { return isUnconditional(); }
377 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
378 bool isMemoryWrite() const override { return false; }
379 void dump(const Cfg *Func) const override;
380 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
383 /// Conditional branch
384 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
385 /// Unconditional branch
386 InstBr(Cfg *Func, CfgNode *Target);
388 CfgNode *TargetFalse; /// Doubles as unconditional branch target
389 CfgNode *TargetTrue; /// nullptr if unconditional branch
392 /// Call instruction. The call target is captured as getSrc(0), and arg I is
393 /// captured as getSrc(I+1).
394 class InstCall : public InstHighLevel {
396 InstCall(const InstCall &) = delete;
397 InstCall &operator=(const InstCall &) = delete;
400 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
401 Operand *CallTarget, bool HasTailCall,
402 bool IsTargetHelperCall = false) {
403 /// Set HasSideEffects to true so that the call instruction can't be
404 /// dead-code eliminated. IntrinsicCalls can override this if the particular
405 /// intrinsic is deletable and has no side-effects.
406 constexpr bool HasSideEffects = true;
407 constexpr InstKind Kind = Inst::Call;
408 return new (Func->allocate<InstCall>())
409 InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
410 IsTargetHelperCall, HasSideEffects, Kind);
412 void addArg(Operand *Arg) { addSource(Arg); }
413 Operand *getCallTarget() const { return getSrc(0); }
414 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
415 SizeT getNumArgs() const { return getSrcSize() - 1; }
416 bool isTailcall() const { return HasTailCall; }
417 bool isTargetHelperCall() const { return IsTargetHelperCall; }
418 bool isMemoryWrite() const override { return true; }
419 void dump(const Cfg *Func) const override;
420 static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
421 Type getReturnType() const;
424 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
425 bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
427 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
428 IsTargetHelperCall(IsTargetHelperCall) {
429 HasSideEffects = HasSideEff;
430 addSource(CallTarget);
434 const bool HasTailCall;
435 const bool IsTargetHelperCall;
438 /// Cast instruction (a.k.a. conversion operation).
439 class InstCast : public InstHighLevel {
441 InstCast(const InstCast &) = delete;
442 InstCast &operator=(const InstCast &) = delete;
446 #define X(tag, str) tag,
452 static const char *getCastName(OpKind Kind);
454 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
456 return new (Func->allocate<InstCast>())
457 InstCast(Func, CastKind, Dest, Source);
459 OpKind getCastKind() const { return CastKind; }
460 bool isMemoryWrite() const override { return false; }
461 void dump(const Cfg *Func) const override;
462 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
465 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
467 const OpKind CastKind;
470 /// ExtractElement instruction.
471 class InstExtractElement : public InstHighLevel {
472 InstExtractElement() = delete;
473 InstExtractElement(const InstExtractElement &) = delete;
474 InstExtractElement &operator=(const InstExtractElement &) = delete;
477 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
479 return new (Func->allocate<InstExtractElement>())
480 InstExtractElement(Func, Dest, Source1, Source2);
483 bool isMemoryWrite() const override { return false; }
484 void dump(const Cfg *Func) const override;
485 static bool classof(const Inst *Instr) {
486 return Instr->getKind() == ExtractElement;
490 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
494 /// Floating-point comparison instruction. The source operands are captured in
495 /// getSrc(0) and getSrc(1).
496 class InstFcmp : public InstHighLevel {
498 InstFcmp(const InstFcmp &) = delete;
499 InstFcmp &operator=(const InstFcmp &) = delete;
503 #define X(tag, str) tag,
509 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
510 Operand *Source1, Operand *Source2) {
511 return new (Func->allocate<InstFcmp>())
512 InstFcmp(Func, Condition, Dest, Source1, Source2);
514 FCond getCondition() const { return Condition; }
515 bool isMemoryWrite() const override { return false; }
516 void dump(const Cfg *Func) const override;
517 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
520 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
523 const FCond Condition;
526 /// Integer comparison instruction. The source operands are captured in
527 /// getSrc(0) and getSrc(1).
528 class InstIcmp : public InstHighLevel {
530 InstIcmp(const InstIcmp &) = delete;
531 InstIcmp &operator=(const InstIcmp &) = delete;
535 #define X(tag, str) tag,
541 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
542 Operand *Source1, Operand *Source2) {
543 return new (Func->allocate<InstIcmp>())
544 InstIcmp(Func, Condition, Dest, Source1, Source2);
546 ICond getCondition() const { return Condition; }
547 bool isMemoryWrite() const override { return false; }
548 void dump(const Cfg *Func) const override;
549 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
552 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
555 const ICond Condition;
558 /// InsertElement instruction.
559 class InstInsertElement : public InstHighLevel {
560 InstInsertElement() = delete;
561 InstInsertElement(const InstInsertElement &) = delete;
562 InstInsertElement &operator=(const InstInsertElement &) = delete;
565 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
566 Operand *Source2, Operand *Source3) {
567 return new (Func->allocate<InstInsertElement>())
568 InstInsertElement(Func, Dest, Source1, Source2, Source3);
571 bool isMemoryWrite() const override { return false; }
572 void dump(const Cfg *Func) const override;
573 static bool classof(const Inst *Instr) {
574 return Instr->getKind() == InsertElement;
578 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
579 Operand *Source2, Operand *Source3);
582 /// Call to an intrinsic function. The call target is captured as getSrc(0), and
583 /// arg I is captured as getSrc(I+1).
584 class InstIntrinsicCall : public InstCall {
585 InstIntrinsicCall() = delete;
586 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
587 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
590 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
592 const Intrinsics::IntrinsicInfo &Info) {
593 return new (Func->allocate<InstIntrinsicCall>())
594 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
596 static bool classof(const Inst *Instr) {
597 return Instr->getKind() == IntrinsicCall;
600 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
601 bool isMemoryWrite() const override {
602 return getIntrinsicInfo().IsMemoryWrite;
606 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
607 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
608 : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
609 Info.HasSideEffects, Inst::IntrinsicCall),
612 const Intrinsics::IntrinsicInfo Info;
615 /// Load instruction. The source address is captured in getSrc(0).
616 class InstLoad : public InstHighLevel {
618 InstLoad(const InstLoad &) = delete;
619 InstLoad &operator=(const InstLoad &) = delete;
622 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
623 uint32_t Align = 1) {
624 // TODO(kschimpf) Stop ignoring alignment specification.
626 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
628 Operand *getSourceAddress() const { return getSrc(0); }
629 bool isMemoryWrite() const override { return false; }
630 void dump(const Cfg *Func) const override;
631 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
634 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
637 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
638 /// source operand is getSrc(I).
639 class InstPhi : public InstHighLevel {
641 InstPhi(const InstPhi &) = delete;
642 InstPhi &operator=(const InstPhi &) = delete;
645 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
646 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
648 void addArgument(Operand *Source, CfgNode *Label);
649 Operand *getOperandForTarget(CfgNode *Target) const;
650 void clearOperandForTarget(CfgNode *Target);
651 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
652 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
653 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
655 Inst *lower(Cfg *Func);
656 bool isMemoryWrite() const override { return false; }
657 void dump(const Cfg *Func) const override;
658 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
661 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
662 void destroy(Cfg *Func) override {
663 Func->deallocateArrayOf<CfgNode *>(Labels);
667 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
668 /// but the Phi instruction is created before InEdges[] is available, so it's
669 /// more complicated to share the list.
673 /// Ret instruction. The return value is captured in getSrc(0), but if there is
674 /// no return value (void-type function), then getSrcSize()==0 and
675 /// hasRetValue()==false.
676 class InstRet : public InstHighLevel {
678 InstRet(const InstRet &) = delete;
679 InstRet &operator=(const InstRet &) = delete;
682 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
683 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
685 bool hasRetValue() const { return getSrcSize(); }
686 Operand *getRetValue() const {
687 assert(hasRetValue());
690 NodeList getTerminatorEdges() const override { return NodeList(); }
691 bool isMemoryWrite() const override { return false; }
692 void dump(const Cfg *Func) const override;
693 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
696 InstRet(Cfg *Func, Operand *RetValue);
699 /// Select instruction. The condition, true, and false operands are captured.
700 class InstSelect : public InstHighLevel {
701 InstSelect() = delete;
702 InstSelect(const InstSelect &) = delete;
703 InstSelect &operator=(const InstSelect &) = delete;
706 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
707 Operand *SourceTrue, Operand *SourceFalse) {
708 return new (Func->allocate<InstSelect>())
709 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
711 Operand *getCondition() const { return getSrc(0); }
712 Operand *getTrueOperand() const { return getSrc(1); }
713 Operand *getFalseOperand() const { return getSrc(2); }
714 bool isMemoryWrite() const override { return false; }
715 void dump(const Cfg *Func) const override;
716 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
719 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
723 /// Store instruction. The address operand is captured, along with the data
724 /// operand to be stored into the address.
725 class InstStore : public InstHighLevel {
726 InstStore() = delete;
727 InstStore(const InstStore &) = delete;
728 InstStore &operator=(const InstStore &) = delete;
731 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
732 uint32_t Align = 1) {
733 // TODO(kschimpf) Stop ignoring alignment specification.
735 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
737 Operand *getAddr() const { return getSrc(1); }
738 Operand *getData() const { return getSrc(0); }
739 Variable *getRmwBeacon() const;
740 void setRmwBeacon(Variable *Beacon);
741 bool isMemoryWrite() const override { return true; }
742 void dump(const Cfg *Func) const override;
743 static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
746 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
749 /// Switch instruction. The single source operand is captured as getSrc(0).
750 class InstSwitch : public InstHighLevel {
751 InstSwitch() = delete;
752 InstSwitch(const InstSwitch &) = delete;
753 InstSwitch &operator=(const InstSwitch &) = delete;
756 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
757 CfgNode *LabelDefault) {
758 return new (Func->allocate<InstSwitch>())
759 InstSwitch(Func, NumCases, Source, LabelDefault);
761 Operand *getComparison() const { return getSrc(0); }
762 CfgNode *getLabelDefault() const { return LabelDefault; }
763 SizeT getNumCases() const { return NumCases; }
764 uint64_t getValue(SizeT I) const {
765 assert(I < NumCases);
768 CfgNode *getLabel(SizeT I) const {
769 assert(I < NumCases);
772 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
773 NodeList getTerminatorEdges() const override;
774 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
775 bool isMemoryWrite() const override { return false; }
776 void dump(const Cfg *Func) const override;
777 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
780 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
781 void destroy(Cfg *Func) override {
782 Func->deallocateArrayOf<uint64_t>(Values);
783 Func->deallocateArrayOf<CfgNode *>(Labels);
787 CfgNode *LabelDefault;
788 SizeT NumCases; /// not including the default case
789 uint64_t *Values; /// size is NumCases
790 CfgNode **Labels; /// size is NumCases
793 /// Unreachable instruction. This is a terminator instruction with no operands.
794 class InstUnreachable : public InstHighLevel {
795 InstUnreachable() = delete;
796 InstUnreachable(const InstUnreachable &) = delete;
797 InstUnreachable &operator=(const InstUnreachable &) = delete;
800 static InstUnreachable *create(Cfg *Func) {
801 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
803 NodeList getTerminatorEdges() const override { return NodeList(); }
804 bool isMemoryWrite() const override { return false; }
805 void dump(const Cfg *Func) const override;
806 static bool classof(const Inst *Instr) {
807 return Instr->getKind() == Unreachable;
811 explicit InstUnreachable(Cfg *Func);
814 /// BundleLock instruction. There are no operands. Contains an option
815 /// indicating whether align_to_end is specified.
816 class InstBundleLock : public InstHighLevel {
817 InstBundleLock() = delete;
818 InstBundleLock(const InstBundleLock &) = delete;
819 InstBundleLock &operator=(const InstBundleLock &) = delete;
822 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
823 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
824 return new (Func->allocate<InstBundleLock>())
825 InstBundleLock(Func, BundleOption);
827 void emit(const Cfg *Func) const override;
828 void emitIAS(const Cfg * /* Func */) const override {}
829 bool isMemoryWrite() const override { return false; }
830 void dump(const Cfg *Func) const override;
831 Option getOption() const { return BundleOption; }
832 static bool classof(const Inst *Instr) {
833 return Instr->getKind() == BundleLock;
838 InstBundleLock(Cfg *Func, Option BundleOption);
841 /// BundleUnlock instruction. There are no operands.
842 class InstBundleUnlock : public InstHighLevel {
843 InstBundleUnlock() = delete;
844 InstBundleUnlock(const InstBundleUnlock &) = delete;
845 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
848 static InstBundleUnlock *create(Cfg *Func) {
849 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
851 void emit(const Cfg *Func) const override;
852 void emitIAS(const Cfg * /* Func */) const override {}
853 bool isMemoryWrite() const override { return false; }
854 void dump(const Cfg *Func) const override;
855 static bool classof(const Inst *Instr) {
856 return Instr->getKind() == BundleUnlock;
860 explicit InstBundleUnlock(Cfg *Func);
863 /// FakeDef instruction. This creates a fake definition of a variable, which is
864 /// how we represent the case when an instruction produces multiple results.
865 /// This doesn't happen with high-level ICE instructions, but might with lowered
866 /// instructions. For example, this would be a way to represent condition flags
867 /// being modified by an instruction.
869 /// It's generally useful to set the optional source operand to be the dest
870 /// variable of the instruction that actually produces the FakeDef dest.
871 /// Otherwise, the original instruction could be dead-code eliminated if its
872 /// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
874 class InstFakeDef : public InstHighLevel {
875 InstFakeDef() = delete;
876 InstFakeDef(const InstFakeDef &) = delete;
877 InstFakeDef &operator=(const InstFakeDef &) = delete;
880 static InstFakeDef *create(Cfg *Func, Variable *Dest,
881 Variable *Src = nullptr) {
882 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
884 void emit(const Cfg *Func) const override;
885 void emitIAS(const Cfg * /* Func */) const override {}
886 bool isMemoryWrite() const override { return false; }
887 void dump(const Cfg *Func) const override;
888 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
891 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
894 /// FakeUse instruction. This creates a fake use of a variable, to keep the
895 /// instruction that produces that variable from being dead-code eliminated.
896 /// This is useful in a variety of lowering situations. The FakeUse instruction
897 /// has no dest, so it can itself never be dead-code eliminated. A weight can
898 /// be provided to provide extra bias to the register allocator - for simplicity
899 /// of implementation, weight=N is handled by holding N copies of the variable
900 /// as source operands.
901 class InstFakeUse : public InstHighLevel {
902 InstFakeUse() = delete;
903 InstFakeUse(const InstFakeUse &) = delete;
904 InstFakeUse &operator=(const InstFakeUse &) = delete;
907 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
908 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
910 void emit(const Cfg *Func) const override;
911 void emitIAS(const Cfg * /* Func */) const override {}
912 bool isMemoryWrite() const override { return false; }
913 void dump(const Cfg *Func) const override;
914 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
917 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
920 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial
921 /// live range at this instruction for each (implicit) variable. The primary use
922 /// is to indicate that scratch registers are killed after a call, so that the
923 /// register allocator won't assign a scratch register to a variable whose live
924 /// range spans a call.
926 /// The FakeKill instruction also holds a pointer to the instruction that kills
927 /// the set of variables, so that if that linked instruction gets dead-code
928 /// eliminated, the FakeKill instruction will as well.
929 class InstFakeKill : public InstHighLevel {
930 InstFakeKill() = delete;
931 InstFakeKill(const InstFakeKill &) = delete;
932 InstFakeKill &operator=(const InstFakeKill &) = delete;
935 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
936 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
938 const Inst *getLinked() const { return Linked; }
939 void emit(const Cfg *Func) const override;
940 void emitIAS(const Cfg * /* Func */) const override {}
941 bool isMemoryWrite() const override { return false; }
942 void dump(const Cfg *Func) const override;
943 static bool classof(const Inst *Instr) {
944 return Instr->getKind() == FakeKill;
948 InstFakeKill(Cfg *Func, const Inst *Linked);
950 /// This instruction is ignored if Linked->isDeleted() is true.
954 /// ShuffleVector instruction. This represents a shuffle operation on vector
955 /// types. This instruction is not part of the PNaCl bitcode: it is generated
956 /// by Subzero when it matches the pattern used by pnacl-clang when compiling
958 class InstShuffleVector : public InstHighLevel {
959 InstShuffleVector() = delete;
960 InstShuffleVector(const InstShuffleVector &) = delete;
961 InstShuffleVector &operator=(const InstShuffleVector &) = delete;
964 static InstShuffleVector *create(Cfg *Func, Variable *Dest, Variable *Src0,
966 return new (Func->allocate<InstShuffleVector>())
967 InstShuffleVector(Func, Dest, Src0, Src1);
970 SizeT getNumIndexes() const { return NumIndexes; }
972 void addIndex(ConstantInteger32 *Index) {
973 assert(CurrentIndex < NumIndexes);
974 Indexes[CurrentIndex++] = Index;
977 ConstantInteger32 *getIndex(SizeT Pos) const {
978 assert(Pos < NumIndexes);
982 bool isMemoryWrite() const override { return false; }
983 void dump(const Cfg *Func) const override;
984 static bool classof(const Inst *Instr) {
985 return Instr->getKind() == ShuffleVector;
989 InstShuffleVector(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1);
991 void destroy(Cfg *Func) override {
992 Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
996 ConstantInteger32 **Indexes;
997 SizeT CurrentIndex = 0;
998 const SizeT NumIndexes;
1001 /// JumpTable instruction. This represents a jump table that will be stored in
1002 /// the .rodata section. This is used to track and repoint the target CfgNodes
1003 /// which may change, for example due to splitting for phi lowering.
1004 class InstJumpTable : public InstHighLevel {
1005 InstJumpTable() = delete;
1006 InstJumpTable(const InstJumpTable &) = delete;
1007 InstJumpTable &operator=(const InstJumpTable &) = delete;
1010 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
1011 return new (Func->allocate<InstJumpTable>())
1012 InstJumpTable(Func, NumTargets, Default);
1014 void addTarget(SizeT TargetIndex, CfgNode *Target) {
1015 assert(TargetIndex < NumTargets);
1016 Targets[TargetIndex] = Target;
1018 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
1019 SizeT getId() const { return Id; }
1020 SizeT getNumTargets() const { return NumTargets; }
1021 CfgNode *getTarget(SizeT I) const {
1022 assert(I < NumTargets);
1025 bool isMemoryWrite() const override { return false; }
1026 void dump(const Cfg *Func) const override;
1027 static bool classof(const Inst *Instr) {
1028 return Instr->getKind() == JumpTable;
1030 // Creates a JumpTableData struct (used for ELF emission) that represents this
1032 JumpTableData toJumpTableData(Assembler *Asm) const;
1034 // InstJumpTable is just a placeholder for the switch targets, and it does not
1035 // need to emit any code, so we redefine emit and emitIAS to do nothing.
1036 void emit(const Cfg *) const override {}
1037 void emitIAS(const Cfg * /* Func */) const override {}
1039 const std::string getName() const {
1040 assert(Name.hasStdString());
1041 return Name.toString();
1044 std::string getSectionName() const {
1045 return JumpTableData::createSectionName(FuncName);
1049 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
1050 void destroy(Cfg *Func) override {
1051 Func->deallocateArrayOf<CfgNode *>(Targets);
1052 Inst::destroy(Func);
1056 const SizeT NumTargets;
1058 GlobalString Name; // This JumpTable's name in the output.
1059 GlobalString FuncName;
1062 /// This instruction inserts an unconditional breakpoint.
1064 /// On x86, this assembles into an INT 3 instruction.
1066 /// This instruction is primarily meant for debugging the code generator.
1067 class InstBreakpoint : public InstHighLevel {
1069 InstBreakpoint() = delete;
1070 InstBreakpoint(const InstBreakpoint &) = delete;
1071 InstBreakpoint &operator=(const InstBreakpoint &) = delete;
1073 explicit InstBreakpoint(Cfg *Func);
1074 bool isMemoryWrite() const override { return false; }
1077 static InstBreakpoint *create(Cfg *Func) {
1078 return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
1081 static bool classof(const Inst *Instr) {
1082 return Instr->getKind() == Breakpoint;
1086 /// The Target instruction is the base class for all target-specific
1088 class InstTarget : public Inst {
1089 InstTarget() = delete;
1090 InstTarget(const InstTarget &) = delete;
1091 InstTarget &operator=(const InstTarget &) = delete;
1094 uint32_t getEmitInstCount() const override { return 1; }
1095 bool isMemoryWrite() const override {
1096 return true; // conservative answer
1098 void dump(const Cfg *Func) const override;
1099 static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
1102 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
1103 : Inst(Func, Kind, MaxSrcs, Dest) {
1104 assert(Kind >= Target);
1105 assert(Kind <= Target_Max);
1109 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
1111 } // end of namespace Ice
1115 /// Override the default ilist traits so that Inst's private ctor and deleted
1116 /// dtor aren't invoked.
1118 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
1119 Ice::Inst *createSentinel() const {
1120 return static_cast<Ice::Inst *>(&Sentinel);
1122 static void destroySentinel(Ice::Inst *) {}
1123 Ice::Inst *provideInitialHead() const { return createSentinel(); }
1124 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
1125 static void noteHead(Ice::Inst *, Ice::Inst *) {}
1126 void deleteNode(Ice::Inst *) {}
1129 mutable ilist_half_node<Ice::Inst> Sentinel;
1132 } // end of namespace llvm
1136 inline InstList::iterator instToIterator(Inst *Instr) {
1139 #else // !PNACL_LLVM
1140 return Instr->getIterator();
1141 #endif // !PNACL_LLVM
1144 inline Inst *iteratorToInst(InstList::iterator Iter) {
1148 inline const Inst *iteratorToInst(InstList::const_iterator Iter) {
1152 } // end of namespace Ice
1154 #endif // SUBZERO_SRC_ICEINST_H