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 /// This file declares the Inst class and its target-independent
12 /// subclasses, which represent the high-level Vanilla ICE instructions
13 /// and map roughly 1:1 to LLVM instructions.
15 //===----------------------------------------------------------------------===//
17 #ifndef SUBZERO_SRC_ICEINST_H
18 #define SUBZERO_SRC_ICEINST_H
22 #include "IceInst.def"
23 #include "IceIntrinsics.h"
26 // TODO: The Cfg structure, and instructions in particular, need to be
27 // validated for things like valid operand types, valid branch targets, proper
28 // ordering of Phi and non-Phi instructions, etc. Most of the validity checking
29 // will be done in the bitcode reader. We need a list of everything that should
30 // be validated, and tests for each.
34 /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
35 /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
36 /// low-level (target-specific) ICE instructions inherit from InstTarget.
37 class Inst : public llvm::ilist_node<Inst> {
39 Inst(const Inst &) = delete;
40 Inst &operator=(const Inst &) = delete;
44 // Arbitrary (alphabetical) order, except put Unreachable first.
62 Assign, // not part of LLVM/PNaCl bitcode
63 BundleLock, // not part of LLVM/PNaCl bitcode
64 BundleUnlock, // not part of LLVM/PNaCl bitcode
65 FakeDef, // not part of LLVM/PNaCl bitcode
66 FakeUse, // not part of LLVM/PNaCl bitcode
67 FakeKill, // not part of LLVM/PNaCl bitcode
68 JumpTable, // not part of LLVM/PNaCl bitcode
69 // Anything >= Target is an InstTarget subclass. Note that the value-spaces
70 // are shared across targets. To avoid confusion over the definition of
71 // shared values, an object specific to one target should never be passed
72 // to a different target.
74 Target_Max = std::numeric_limits<uint8_t>::max(),
76 static_assert(Target <= Target_Max, "Must not be above max.");
77 InstKind getKind() const { return Kind; }
79 InstNumberT getNumber() const { return Number; }
80 void renumber(Cfg *Func);
85 NumberExtended = NumberInitial - 1
88 bool isDeleted() const { return Deleted; }
89 void setDeleted() { Deleted = true; }
90 void setDead(bool Value = true) { Dead = Value; }
93 bool hasSideEffects() const { return HasSideEffects; }
95 bool isDestRedefined() const { return IsDestRedefined; }
96 void setDestRedefined() { IsDestRedefined = true; }
98 Variable *getDest() const { return Dest; }
100 SizeT getSrcSize() const { return NumSrcs; }
101 Operand *getSrc(SizeT I) const {
102 assert(I < getSrcSize());
106 bool isLastUse(const Operand *Src) const;
107 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
109 /// Returns a list of out-edges corresponding to a terminator instruction,
110 /// which is the last instruction of the block. The list must not contain
112 virtual NodeList getTerminatorEdges() const {
113 // All valid terminator instructions override this method. For the default
114 // implementation, we assert in case some CfgNode is constructed without a
115 // terminator instruction at the end.
117 "getTerminatorEdges() called on a non-terminator instruction");
120 virtual bool isUnconditionalBranch() const { return false; }
121 /// If the instruction is a branch-type instruction with OldNode as a target,
122 /// repoint it to NewNode and return true, otherwise return false. Repoint all
123 /// instances of OldNode as a target.
124 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
130 virtual bool isSimpleAssign() const { return false; }
132 void livenessLightweight(Cfg *Func, LivenessBV &Live);
133 /// Calculates liveness for this instruction. Returns true if this instruction
134 /// is (tentatively) still live and should be retained, and false if this
135 /// instruction is (tentatively) dead and should be deleted. The decision is
136 /// tentative until the liveness dataflow algorithm has converged, and then a
137 /// separate pass permanently deletes dead instructions.
138 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
139 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
141 /// Get the number of native instructions that this instruction ultimately
142 /// emits. By default, high-level instructions don't result in any native
143 /// instructions, and a target-specific instruction results in a single native
145 virtual uint32_t getEmitInstCount() const { return 0; }
146 // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
147 // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
148 // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
149 // allow the abstract class Ice::Inst. The method should be declared
150 // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
151 // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
152 virtual void emit(const Cfg *) const {
153 llvm_unreachable("emit on abstract class");
155 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
156 virtual void dump(const Cfg *Func) const;
157 virtual void dumpExtras(const Cfg *Func) const;
158 void dumpDecorated(const Cfg *Func) const;
159 void emitSources(const Cfg *Func) const;
160 void dumpSources(const Cfg *Func) const;
161 void dumpDest(const Cfg *Func) const;
162 virtual bool isRedundantAssign() const { return false; }
167 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
168 void addSource(Operand *Src) {
170 assert(NumSrcs < MaxSrcs);
171 Srcs[NumSrcs++] = Src;
173 void setLastUse(SizeT VarIndex) {
174 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
175 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
177 void resetLastUses() { LiveRangesEnded = 0; }
178 /// The destroy() method lets the instruction cleanly release any memory that
179 /// was allocated via the Cfg's allocator.
180 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
183 /// Number is the instruction number for describing live ranges.
185 /// Deleted means irrevocably deleted.
186 bool Deleted = false;
187 /// Dead means one of two things depending on context: (1) pending deletion
188 /// after liveness analysis converges, or (2) marked for deletion during
189 /// lowering due to a folded bool operation.
191 /// HasSideEffects means the instruction is something like a function call or
192 /// a volatile load that can't be removed even if its Dest variable is not
194 bool HasSideEffects = false;
195 /// IsDestRedefined indicates that this instruction is not the first
196 /// definition of Dest in the basic block. The effect is that liveness
197 /// analysis shouldn't consider this instruction to be the start of Dest's
198 /// live range; rather, there is some other instruction earlier in the basic
199 /// block with the same Dest. This is maintained because liveness analysis
200 /// has an invariant (primarily for performance reasons) that any Variable's
201 /// live range recorded in a basic block has at most one start and at most one
203 bool IsDestRedefined = false;
206 const SizeT MaxSrcs; // only used for assert
210 /// LiveRangesEnded marks which Variables' live ranges end in this
211 /// instruction. An instruction can have an arbitrary number of source
212 /// operands (e.g. a call instruction), and each source operand can contain 0
213 /// or 1 Variable (and target-specific operands could contain more than 1
214 /// Variable). All the variables in an instruction are conceptually flattened
215 /// and each variable is mapped to one bit position of the LiveRangesEnded bit
216 /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
217 /// tracked this way.
218 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
219 LREndedBits LiveRangesEnded;
222 class InstHighLevel : public Inst {
223 InstHighLevel() = delete;
224 InstHighLevel(const InstHighLevel &) = delete;
225 InstHighLevel &operator=(const InstHighLevel &) = delete;
228 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
229 : Inst(Func, Kind, MaxSrcs, Dest) {}
230 void emit(const Cfg * /*Func*/) const override {
231 llvm_unreachable("emit() called on a non-lowered instruction");
233 void emitIAS(const Cfg * /*Func*/) const override {
234 llvm_unreachable("emitIAS() called on a non-lowered instruction");
238 /// Alloca instruction. This captures the size in bytes as getSrc(0), and the
239 /// required alignment in bytes. The alignment must be either 0 (no alignment
240 /// required) or a power of 2.
241 class InstAlloca : public InstHighLevel {
242 InstAlloca() = delete;
243 InstAlloca(const InstAlloca &) = delete;
244 InstAlloca &operator=(const InstAlloca &) = delete;
247 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
248 uint32_t AlignInBytes, Variable *Dest) {
249 return new (Func->allocate<InstAlloca>())
250 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
252 uint32_t getAlignInBytes() const { return AlignInBytes; }
253 Operand *getSizeInBytes() const { return getSrc(0); }
254 bool getKnownFrameOffset() const { return KnownFrameOffset; }
255 void setKnownFrameOffset() { KnownFrameOffset = true; }
256 void dump(const Cfg *Func) const override;
257 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
260 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
263 const uint32_t AlignInBytes;
264 bool KnownFrameOffset = false;
267 /// Binary arithmetic instruction. The source operands are captured in getSrc(0)
269 class InstArithmetic : public InstHighLevel {
270 InstArithmetic() = delete;
271 InstArithmetic(const InstArithmetic &) = delete;
272 InstArithmetic &operator=(const InstArithmetic &) = delete;
276 #define X(tag, str, commutative) tag,
277 ICEINSTARITHMETIC_TABLE
282 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
283 Operand *Source1, Operand *Source2) {
284 return new (Func->allocate<InstArithmetic>())
285 InstArithmetic(Func, Op, Dest, Source1, Source2);
287 OpKind getOp() const { return Op; }
288 static const char *getOpName(OpKind Op);
289 bool isCommutative() const;
290 void dump(const Cfg *Func) const override;
291 static bool classof(const Inst *Inst) {
292 return Inst->getKind() == Arithmetic;
296 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
302 /// Assignment instruction. The source operand is captured in getSrc(0). This is
303 /// not part of the LLVM bitcode, but is a useful abstraction for some of the
304 /// lowering. E.g., if Phi instruction lowering happens before target lowering,
305 /// or for representing an Inttoptr instruction, or as an intermediate step for
306 /// lowering a Load instruction.
307 class InstAssign : public InstHighLevel {
308 InstAssign() = delete;
309 InstAssign(const InstAssign &) = delete;
310 InstAssign &operator=(const InstAssign &) = delete;
313 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
314 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
316 bool isSimpleAssign() const override { return true; }
317 void dump(const Cfg *Func) const override;
318 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
321 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
324 /// Branch instruction. This represents both conditional and unconditional
326 class InstBr : public InstHighLevel {
328 InstBr(const InstBr &) = delete;
329 InstBr &operator=(const InstBr &) = delete;
332 /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
333 /// to an unconditional branch.
334 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
335 CfgNode *TargetFalse) {
336 return new (Func->allocate<InstBr>())
337 InstBr(Func, Source, TargetTrue, TargetFalse);
339 /// Create an unconditional branch.
340 static InstBr *create(Cfg *Func, CfgNode *Target) {
341 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
343 bool isUnconditional() const { return getTargetTrue() == nullptr; }
344 Operand *getCondition() const {
345 assert(!isUnconditional());
348 CfgNode *getTargetTrue() const { return TargetTrue; }
349 CfgNode *getTargetFalse() const { return TargetFalse; }
350 CfgNode *getTargetUnconditional() const {
351 assert(isUnconditional());
352 return getTargetFalse();
354 NodeList getTerminatorEdges() const override;
355 bool isUnconditionalBranch() const override { return isUnconditional(); }
356 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
357 void dump(const Cfg *Func) const override;
358 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
361 /// Conditional branch
362 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
363 /// Unconditional branch
364 InstBr(Cfg *Func, CfgNode *Target);
366 CfgNode *TargetFalse; /// Doubles as unconditional branch target
367 CfgNode *TargetTrue; /// nullptr if unconditional branch
370 /// Call instruction. The call target is captured as getSrc(0), and arg I is
371 /// captured as getSrc(I+1).
372 class InstCall : public InstHighLevel {
374 InstCall(const InstCall &) = delete;
375 InstCall &operator=(const InstCall &) = delete;
378 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
379 Operand *CallTarget, bool HasTailCall) {
380 /// Set HasSideEffects to true so that the call instruction can't be
381 /// dead-code eliminated. IntrinsicCalls can override this if the particular
382 /// intrinsic is deletable and has no side-effects.
383 const bool HasSideEffects = true;
384 const InstKind Kind = Inst::Call;
385 return new (Func->allocate<InstCall>()) InstCall(
386 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
388 void addArg(Operand *Arg) { addSource(Arg); }
389 Operand *getCallTarget() const { return getSrc(0); }
390 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
391 SizeT getNumArgs() const { return getSrcSize() - 1; }
392 bool isTailcall() const { return HasTailCall; }
393 void dump(const Cfg *Func) const override;
394 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
395 Type getReturnType() const;
398 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
399 bool HasTailCall, bool HasSideEff, InstKind Kind)
400 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
401 HasSideEffects = HasSideEff;
402 addSource(CallTarget);
409 /// Cast instruction (a.k.a. conversion operation).
410 class InstCast : public InstHighLevel {
412 InstCast(const InstCast &) = delete;
413 InstCast &operator=(const InstCast &) = delete;
417 #define X(tag, str) tag,
423 static const char *getCastName(OpKind Kind);
425 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
427 return new (Func->allocate<InstCast>())
428 InstCast(Func, CastKind, Dest, Source);
430 OpKind getCastKind() const { return CastKind; }
431 void dump(const Cfg *Func) const override;
432 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
435 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
437 const OpKind CastKind;
440 /// ExtractElement instruction.
441 class InstExtractElement : public InstHighLevel {
442 InstExtractElement() = delete;
443 InstExtractElement(const InstExtractElement &) = delete;
444 InstExtractElement &operator=(const InstExtractElement &) = delete;
447 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
449 return new (Func->allocate<InstExtractElement>())
450 InstExtractElement(Func, Dest, Source1, Source2);
453 void dump(const Cfg *Func) const override;
454 static bool classof(const Inst *Inst) {
455 return Inst->getKind() == ExtractElement;
459 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
463 /// Floating-point comparison instruction. The source operands are captured in
464 /// getSrc(0) and getSrc(1).
465 class InstFcmp : public InstHighLevel {
467 InstFcmp(const InstFcmp &) = delete;
468 InstFcmp &operator=(const InstFcmp &) = delete;
472 #define X(tag, str) tag,
478 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
479 Operand *Source1, Operand *Source2) {
480 return new (Func->allocate<InstFcmp>())
481 InstFcmp(Func, Condition, Dest, Source1, Source2);
483 FCond getCondition() const { return Condition; }
484 void dump(const Cfg *Func) const override;
485 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
488 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
491 const FCond Condition;
494 /// Integer comparison instruction. The source operands are captured in
495 /// getSrc(0) and getSrc(1).
496 class InstIcmp : public InstHighLevel {
498 InstIcmp(const InstIcmp &) = delete;
499 InstIcmp &operator=(const InstIcmp &) = delete;
503 #define X(tag, str) tag,
509 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
510 Operand *Source1, Operand *Source2) {
511 return new (Func->allocate<InstIcmp>())
512 InstIcmp(Func, Condition, Dest, Source1, Source2);
514 ICond getCondition() const { return Condition; }
515 void dump(const Cfg *Func) const override;
516 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
519 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
522 const ICond Condition;
525 /// InsertElement instruction.
526 class InstInsertElement : public InstHighLevel {
527 InstInsertElement() = delete;
528 InstInsertElement(const InstInsertElement &) = delete;
529 InstInsertElement &operator=(const InstInsertElement &) = delete;
532 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
533 Operand *Source2, Operand *Source3) {
534 return new (Func->allocate<InstInsertElement>())
535 InstInsertElement(Func, Dest, Source1, Source2, Source3);
538 void dump(const Cfg *Func) const override;
539 static bool classof(const Inst *Inst) {
540 return Inst->getKind() == InsertElement;
544 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
545 Operand *Source2, Operand *Source3);
548 /// Call to an intrinsic function. The call target is captured as getSrc(0), and
549 /// arg I is captured as getSrc(I+1).
550 class InstIntrinsicCall : public InstCall {
551 InstIntrinsicCall() = delete;
552 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
553 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
556 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
558 const Intrinsics::IntrinsicInfo &Info) {
559 return new (Func->allocate<InstIntrinsicCall>())
560 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
562 static bool classof(const Inst *Inst) {
563 return Inst->getKind() == IntrinsicCall;
566 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
569 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
570 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
571 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
572 Inst::IntrinsicCall),
575 const Intrinsics::IntrinsicInfo Info;
578 /// Load instruction. The source address is captured in getSrc(0).
579 class InstLoad : public InstHighLevel {
581 InstLoad(const InstLoad &) = delete;
582 InstLoad &operator=(const InstLoad &) = delete;
585 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
586 uint32_t Align = 1) {
587 // TODO(kschimpf) Stop ignoring alignment specification.
589 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
591 Operand *getSourceAddress() const { return getSrc(0); }
592 void dump(const Cfg *Func) const override;
593 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
596 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
599 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
600 /// source operand is getSrc(I).
601 class InstPhi : public InstHighLevel {
603 InstPhi(const InstPhi &) = delete;
604 InstPhi &operator=(const InstPhi &) = delete;
607 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
608 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
610 void addArgument(Operand *Source, CfgNode *Label);
611 Operand *getOperandForTarget(CfgNode *Target) const;
612 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
613 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
615 Inst *lower(Cfg *Func);
616 void dump(const Cfg *Func) const override;
617 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
620 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
621 void destroy(Cfg *Func) override {
622 Func->deallocateArrayOf<CfgNode *>(Labels);
626 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
627 /// but the Phi instruction is created before InEdges[] is available, so it's
628 /// more complicated to share the list.
632 /// Ret instruction. The return value is captured in getSrc(0), but if there is
633 /// no return value (void-type function), then getSrcSize()==0 and
634 /// hasRetValue()==false.
635 class InstRet : public InstHighLevel {
637 InstRet(const InstRet &) = delete;
638 InstRet &operator=(const InstRet &) = delete;
641 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
642 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
644 bool hasRetValue() const { return getSrcSize(); }
645 Operand *getRetValue() const {
646 assert(hasRetValue());
649 NodeList getTerminatorEdges() const override { return NodeList(); }
650 void dump(const Cfg *Func) const override;
651 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
654 InstRet(Cfg *Func, Operand *RetValue);
657 /// Select instruction. The condition, true, and false operands are captured.
658 class InstSelect : public InstHighLevel {
659 InstSelect() = delete;
660 InstSelect(const InstSelect &) = delete;
661 InstSelect &operator=(const InstSelect &) = delete;
664 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
665 Operand *SourceTrue, Operand *SourceFalse) {
666 return new (Func->allocate<InstSelect>())
667 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
669 Operand *getCondition() const { return getSrc(0); }
670 Operand *getTrueOperand() const { return getSrc(1); }
671 Operand *getFalseOperand() const { return getSrc(2); }
672 void dump(const Cfg *Func) const override;
673 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
676 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
680 /// Store instruction. The address operand is captured, along with the data
681 /// operand to be stored into the address.
682 class InstStore : public InstHighLevel {
683 InstStore() = delete;
684 InstStore(const InstStore &) = delete;
685 InstStore &operator=(const InstStore &) = delete;
688 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
689 uint32_t Align = 1) {
690 // TODO(kschimpf) Stop ignoring alignment specification.
692 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
694 Operand *getAddr() const { return getSrc(1); }
695 Operand *getData() const { return getSrc(0); }
696 Variable *getRmwBeacon() const;
697 void setRmwBeacon(Variable *Beacon);
698 void dump(const Cfg *Func) const override;
699 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
702 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
705 /// Switch instruction. The single source operand is captured as getSrc(0).
706 class InstSwitch : public InstHighLevel {
707 InstSwitch() = delete;
708 InstSwitch(const InstSwitch &) = delete;
709 InstSwitch &operator=(const InstSwitch &) = delete;
712 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
713 CfgNode *LabelDefault) {
714 return new (Func->allocate<InstSwitch>())
715 InstSwitch(Func, NumCases, Source, LabelDefault);
717 Operand *getComparison() const { return getSrc(0); }
718 CfgNode *getLabelDefault() const { return LabelDefault; }
719 SizeT getNumCases() const { return NumCases; }
720 uint64_t getValue(SizeT I) const {
721 assert(I < NumCases);
724 CfgNode *getLabel(SizeT I) const {
725 assert(I < NumCases);
728 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
729 NodeList getTerminatorEdges() const override;
730 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
731 void dump(const Cfg *Func) const override;
732 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
735 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
736 void destroy(Cfg *Func) override {
737 Func->deallocateArrayOf<uint64_t>(Values);
738 Func->deallocateArrayOf<CfgNode *>(Labels);
742 CfgNode *LabelDefault;
743 SizeT NumCases; /// not including the default case
744 uint64_t *Values; /// size is NumCases
745 CfgNode **Labels; /// size is NumCases
748 /// Unreachable instruction. This is a terminator instruction with no operands.
749 class InstUnreachable : public InstHighLevel {
750 InstUnreachable() = delete;
751 InstUnreachable(const InstUnreachable &) = delete;
752 InstUnreachable &operator=(const InstUnreachable &) = delete;
755 static InstUnreachable *create(Cfg *Func) {
756 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
758 NodeList getTerminatorEdges() const override { return NodeList(); }
759 void dump(const Cfg *Func) const override;
760 static bool classof(const Inst *Inst) {
761 return Inst->getKind() == Unreachable;
765 explicit InstUnreachable(Cfg *Func);
768 /// BundleLock instruction. There are no operands. Contains an option
769 /// indicating whether align_to_end is specified.
770 class InstBundleLock : public InstHighLevel {
771 InstBundleLock() = delete;
772 InstBundleLock(const InstBundleLock &) = delete;
773 InstBundleLock &operator=(const InstBundleLock &) = delete;
776 enum Option { Opt_None, Opt_AlignToEnd };
777 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
778 return new (Func->allocate<InstBundleLock>())
779 InstBundleLock(Func, BundleOption);
781 void emit(const Cfg *Func) const override;
782 void emitIAS(const Cfg * /* Func */) const override {}
783 void dump(const Cfg *Func) const override;
784 Option getOption() const { return BundleOption; }
785 static bool classof(const Inst *Inst) {
786 return Inst->getKind() == BundleLock;
791 InstBundleLock(Cfg *Func, Option BundleOption);
794 /// BundleUnlock instruction. There are no operands.
795 class InstBundleUnlock : public InstHighLevel {
796 InstBundleUnlock() = delete;
797 InstBundleUnlock(const InstBundleUnlock &) = delete;
798 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
801 static InstBundleUnlock *create(Cfg *Func) {
802 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
804 void emit(const Cfg *Func) const override;
805 void emitIAS(const Cfg * /* Func */) const override {}
806 void dump(const Cfg *Func) const override;
807 static bool classof(const Inst *Inst) {
808 return Inst->getKind() == BundleUnlock;
812 explicit InstBundleUnlock(Cfg *Func);
815 /// FakeDef instruction. This creates a fake definition of a variable, which is
816 /// how we represent the case when an instruction produces multiple results.
817 /// This doesn't happen with high-level ICE instructions, but might with lowered
818 /// instructions. For example, this would be a way to represent condition flags
819 /// being modified by an instruction.
821 /// It's generally useful to set the optional source operand to be the dest
822 /// variable of the instruction that actually produces the FakeDef dest.
823 /// Otherwise, the original instruction could be dead-code eliminated if its
824 /// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
826 class InstFakeDef : public InstHighLevel {
827 InstFakeDef() = delete;
828 InstFakeDef(const InstFakeDef &) = delete;
829 InstFakeDef &operator=(const InstFakeDef &) = delete;
832 static InstFakeDef *create(Cfg *Func, Variable *Dest,
833 Variable *Src = nullptr) {
834 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
836 void emit(const Cfg *Func) const override;
837 void emitIAS(const Cfg * /* Func */) const override {}
838 void dump(const Cfg *Func) const override;
839 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
842 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
845 /// FakeUse instruction. This creates a fake use of a variable, to keep the
846 /// instruction that produces that variable from being dead-code eliminated.
847 /// This is useful in a variety of lowering situations. The FakeUse instruction
848 /// has no dest, so it can itself never be dead-code eliminated.
849 class InstFakeUse : public InstHighLevel {
850 InstFakeUse() = delete;
851 InstFakeUse(const InstFakeUse &) = delete;
852 InstFakeUse &operator=(const InstFakeUse &) = delete;
855 static InstFakeUse *create(Cfg *Func, Variable *Src) {
856 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
858 void emit(const Cfg *Func) const override;
859 void emitIAS(const Cfg * /* Func */) const override {}
860 void dump(const Cfg *Func) const override;
861 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
864 InstFakeUse(Cfg *Func, Variable *Src);
867 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial
868 /// live range at this instruction for each (implicit) variable. The primary use
869 /// is to indicate that scratch registers are killed after a call, so that the
870 /// register allocator won't assign a scratch register to a variable whose live
871 /// range spans a call.
873 /// The FakeKill instruction also holds a pointer to the instruction that kills
874 /// the set of variables, so that if that linked instruction gets dead-code
875 /// eliminated, the FakeKill instruction will as well.
876 class InstFakeKill : public InstHighLevel {
877 InstFakeKill() = delete;
878 InstFakeKill(const InstFakeKill &) = delete;
879 InstFakeKill &operator=(const InstFakeKill &) = delete;
882 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
883 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
885 const Inst *getLinked() const { return Linked; }
886 void emit(const Cfg *Func) const override;
887 void emitIAS(const Cfg * /* Func */) const override {}
888 void dump(const Cfg *Func) const override;
889 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
892 InstFakeKill(Cfg *Func, const Inst *Linked);
894 /// This instruction is ignored if Linked->isDeleted() is true.
898 /// JumpTable instruction. This represents a jump table that will be stored in
899 /// the .rodata section. This is used to track and repoint the target CfgNodes
900 /// which may change, for example due to splitting for phi lowering.
901 class InstJumpTable : public InstHighLevel {
902 InstJumpTable() = delete;
903 InstJumpTable(const InstJumpTable &) = delete;
904 InstJumpTable &operator=(const InstJumpTable &) = delete;
907 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
908 return new (Func->allocate<InstJumpTable>())
909 InstJumpTable(Func, NumTargets, Default);
911 void addTarget(SizeT TargetIndex, CfgNode *Target) {
912 assert(TargetIndex < NumTargets);
913 Targets[TargetIndex] = Target;
915 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
916 SizeT getId() const { return Id; }
917 SizeT getNumTargets() const { return NumTargets; }
918 CfgNode *getTarget(SizeT I) const {
919 assert(I < NumTargets);
922 void dump(const Cfg *Func) const override;
923 static bool classof(const Inst *Inst) { return Inst->getKind() == JumpTable; }
925 static IceString makeName(const IceString &FuncName, SizeT Id) {
926 return ".L" + FuncName + "$jumptable$__" + std::to_string(Id);
930 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
931 void destroy(Cfg *Func) override {
932 Func->deallocateArrayOf<CfgNode *>(Targets);
937 const SizeT NumTargets;
941 /// The Target instruction is the base class for all target-specific
943 class InstTarget : public Inst {
944 InstTarget() = delete;
945 InstTarget(const InstTarget &) = delete;
946 InstTarget &operator=(const InstTarget &) = delete;
949 uint32_t getEmitInstCount() const override { return 1; }
950 void dump(const Cfg *Func) const override;
951 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
954 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
955 : Inst(Func, Kind, MaxSrcs, Dest) {
956 assert(Kind >= Target);
957 assert(Kind <= Target_Max);
961 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
963 } // end of namespace Ice
967 /// Override the default ilist traits so that Inst's private ctor and deleted
968 /// dtor aren't invoked.
970 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
971 Ice::Inst *createSentinel() const {
972 return static_cast<Ice::Inst *>(&Sentinel);
974 static void destroySentinel(Ice::Inst *) {}
975 Ice::Inst *provideInitialHead() const { return createSentinel(); }
976 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
977 static void noteHead(Ice::Inst *, Ice::Inst *) {}
978 void deleteNode(Ice::Inst *) {}
981 mutable ilist_half_node<Ice::Inst> Sentinel;
984 } // end of namespace llvm
986 #endif // SUBZERO_SRC_ICEINST_H