blob: 72422c97b2e7af2ef2b0e8275b253888be0f35fa [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- 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// This file declares the Inst class and its target-independent
11// subclasses, which represent the high-level Vanilla ICE instructions
12// and map roughly 1:1 to LLVM instructions.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICEINST_H
17#define SUBZERO_SRC_ICEINST_H
18
19#include "IceDefs.h"
20#include "IceInst.def"
Jan Voung3bd9f1a2014-06-18 10:50:57 -070021#include "IceIntrinsics.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070022#include "IceTypes.h"
23
24// TODO: The Cfg structure, and instructions in particular, need to be
25// validated for things like valid operand types, valid branch
26// targets, proper ordering of Phi and non-Phi instructions, etc.
27// Most of the validity checking will be done in the bitcode reader.
28// We need a list of everything that should be validated, and tests
29// for each.
30
31namespace Ice {
32
Jim Stichnothb56c8f42014-09-26 09:28:46 -070033// Base instruction class for ICE. Inst has two subclasses:
34// InstHighLevel and InstTarget. High-level ICE instructions inherit
35// from InstHighLevel, and low-level (target-specific) ICE
36// instructions inherit from InstTarget.
Jim Stichnoth607e9f02014-11-06 13:32:05 -080037class Inst : public llvm::ilist_node<Inst> {
Jim Stichnoth7b451a92014-10-15 14:39:23 -070038 Inst(const Inst &) = delete;
39 Inst &operator=(const Inst &) = delete;
40
Jim Stichnothf7c9a142014-04-29 10:52:43 -070041public:
42 enum InstKind {
43 // Arbitrary (alphabetical) order, except put Unreachable first.
44 Unreachable,
45 Alloca,
46 Arithmetic,
47 Assign, // not part of LLVM/PNaCl bitcode
48 Br,
49 Call,
50 Cast,
Matt Wala49889232014-07-18 12:45:09 -070051 ExtractElement,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070052 Fcmp,
53 Icmp,
Jan Voung3bd9f1a2014-06-18 10:50:57 -070054 IntrinsicCall,
Matt Wala49889232014-07-18 12:45:09 -070055 InsertElement,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056 Load,
57 Phi,
58 Ret,
59 Select,
60 Store,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070061 Switch,
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -080062 BundleLock, // not part of LLVM/PNaCl bitcode
63 BundleUnlock, // not part of LLVM/PNaCl bitcode
64 FakeDef, // not part of LLVM/PNaCl bitcode
65 FakeUse, // not part of LLVM/PNaCl bitcode
66 FakeKill, // not part of LLVM/PNaCl bitcode
67 Target // target-specific low-level ICE
68 // Anything >= Target is an InstTarget subclass.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070069 };
70 InstKind getKind() const { return Kind; }
71
Jim Stichnothd97c7df2014-06-04 11:57:08 -070072 InstNumberT getNumber() const { return Number; }
73 void renumber(Cfg *Func);
Jim Stichnothe5b73e62014-12-15 09:58:51 -080074 enum {
75 NumberDeleted = -1,
76 NumberSentinel = 0,
77 NumberInitial = 2,
78 NumberExtended = NumberInitial - 1
79 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -070080
81 bool isDeleted() const { return Deleted; }
82 void setDeleted() { Deleted = true; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070083 void deleteIfDead();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070084
85 bool hasSideEffects() const { return HasSideEffects; }
86
Jim Stichnoth47752552014-10-13 17:15:08 -070087 bool isDestNonKillable() const { return IsDestNonKillable; }
88 void setDestNonKillable() { IsDestNonKillable = true; }
89
Jim Stichnothf7c9a142014-04-29 10:52:43 -070090 Variable *getDest() const { return Dest; }
91
92 SizeT getSrcSize() const { return NumSrcs; }
93 Operand *getSrc(SizeT I) const {
94 assert(I < getSrcSize());
95 return Srcs[I];
96 }
97
Jim Stichnothd97c7df2014-06-04 11:57:08 -070098 bool isLastUse(const Operand *Src) const;
99
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700100 // Returns a list of out-edges corresponding to a terminator
101 // instruction, which is the last instruction of the block.
102 virtual NodeList getTerminatorEdges() const {
103 // All valid terminator instructions override this method. For
104 // the default implementation, we assert in case some CfgNode
105 // is constructed without a terminator instruction at the end.
106 llvm_unreachable(
107 "getTerminatorEdges() called on a non-terminator instruction");
108 return NodeList();
109 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700110 virtual bool isUnconditionalBranch() const { return false; }
111 // If the instruction is a branch-type instruction with OldNode as a
112 // target, repoint it to NewNode and return true, otherwise return
113 // false. Only repoint one instance, even if the instruction has
114 // multiple instances of OldNode as a target.
115 virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
116 (void)OldNode;
117 (void)NewNode;
118 return false;
119 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700120
Jim Stichnothad403532014-09-25 12:44:17 -0700121 virtual bool isSimpleAssign() const { return false; }
122
Jim Stichnoth47752552014-10-13 17:15:08 -0700123 void livenessLightweight(Cfg *Func, LivenessBV &Live);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700124 // Calculates liveness for this instruction. Returns true if this
125 // instruction is (tentatively) still live and should be retained,
126 // and false if this instruction is (tentatively) dead and should be
127 // deleted. The decision is tentative until the liveness dataflow
128 // algorithm has converged, and then a separate pass permanently
129 // deletes dead instructions.
130 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
Jim Stichnoth47752552014-10-13 17:15:08 -0700131 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
Jim Stichnoth18735602014-09-16 19:59:35 -0700132
133 // Get the number of native instructions that this instruction
134 // ultimately emits. By default, high-level instructions don't
135 // result in any native instructions, and a target-specific
136 // instruction results in a single native instruction.
137 virtual uint32_t getEmitInstCount() const { return 0; }
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800138 // TODO(stichnot): Change Inst back to abstract once the g++ build
139 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++
140 // because the resize(size_t, Ice::Inst) method is incorrectly
141 // declared and thus doesn't allow the abstract class Ice::Inst.
142 // The method should be declared resize(size_t, const Ice::Inst &).
143 // virtual void emit(const Cfg *Func) const = 0;
144 // virtual void emitIAS(const Cfg *Func) const = 0;
145 virtual void emit(const Cfg *) const {
146 llvm_unreachable("emit on abstract class");
147 }
148 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700149 virtual void dump(const Cfg *Func) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700150 virtual void dumpExtras(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700151 void dumpDecorated(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700152 void emitSources(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700153 void dumpSources(const Cfg *Func) const;
154 void dumpDest(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700155 virtual bool isRedundantAssign() const { return false; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700156
157 virtual ~Inst() {}
158
159protected:
160 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
161 void addSource(Operand *Src) {
162 assert(Src);
163 assert(NumSrcs < MaxSrcs);
164 Srcs[NumSrcs++] = Src;
165 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700166 void setLastUse(SizeT VarIndex) {
167 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
168 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
169 }
170 void resetLastUses() { LiveRangesEnded = 0; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700171 // The destroy() method lets the instruction cleanly release any
172 // memory that was allocated via the Cfg's allocator.
173 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
174
175 const InstKind Kind;
176 // Number is the instruction number for describing live ranges.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700177 InstNumberT Number;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700178 // Deleted means irrevocably deleted.
179 bool Deleted;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700180 // Dead means pending deletion after liveness analysis converges.
181 bool Dead;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700182 // HasSideEffects means the instruction is something like a function
183 // call or a volatile load that can't be removed even if its Dest
184 // variable is not live.
185 bool HasSideEffects;
Jim Stichnoth47752552014-10-13 17:15:08 -0700186 // IsDestNonKillable means that liveness analysis shouldn't consider
187 // this instruction to kill the Dest variable. This is used when
188 // lowering produces two assignments to the same variable.
189 bool IsDestNonKillable;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700190
191 Variable *Dest;
192 const SizeT MaxSrcs; // only used for assert
193 SizeT NumSrcs;
194 Operand **Srcs;
195
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700196 // LiveRangesEnded marks which Variables' live ranges end in this
197 // instruction. An instruction can have an arbitrary number of
198 // source operands (e.g. a call instruction), and each source
199 // operand can contain 0 or 1 Variable (and target-specific operands
200 // could contain more than 1 Variable). All the variables in an
201 // instruction are conceptually flattened and each variable is
202 // mapped to one bit position of the LiveRangesEnded bit vector.
203 // Only the first CHAR_BIT * sizeof(LREndedBits) variables are
204 // tracked this way.
205 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
206 LREndedBits LiveRangesEnded;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700207};
208
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700209class InstHighLevel : public Inst {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700210 InstHighLevel(const InstHighLevel &) = delete;
211 InstHighLevel &operator=(const InstHighLevel &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700212
213protected:
214 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
215 : Inst(Func, Kind, MaxSrcs, Dest) {}
216 void emit(const Cfg * /*Func*/) const override {
217 llvm_unreachable("emit() called on a non-lowered instruction");
218 }
219 void emitIAS(const Cfg * /*Func*/) const override {
220 llvm_unreachable("emitIAS() called on a non-lowered instruction");
221 }
222 ~InstHighLevel() override {}
223};
224
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700225// Alloca instruction. This captures the size in bytes as getSrc(0),
226// and the required alignment in bytes. The alignment must be either
227// 0 (no alignment required) or a power of 2.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700228class InstAlloca : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700229 InstAlloca(const InstAlloca &) = delete;
230 InstAlloca &operator=(const InstAlloca &) = delete;
231
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700232public:
233 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
234 uint32_t AlignInBytes, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800235 return new (Func->allocate<InstAlloca>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700236 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
237 }
238 uint32_t getAlignInBytes() const { return AlignInBytes; }
239 Operand *getSizeInBytes() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700240 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700241 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
242
243private:
244 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
245 Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700246 ~InstAlloca() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700247 const uint32_t AlignInBytes;
248};
249
250// Binary arithmetic instruction. The source operands are captured in
251// getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700252class InstArithmetic : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700253 InstArithmetic(const InstArithmetic &) = delete;
254 InstArithmetic &operator=(const InstArithmetic &) = delete;
255
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700256public:
257 enum OpKind {
258#define X(tag, str, commutative) tag,
259 ICEINSTARITHMETIC_TABLE
260#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700261 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700262 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700263
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700264 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
265 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800266 return new (Func->allocate<InstArithmetic>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700267 InstArithmetic(Func, Op, Dest, Source1, Source2);
268 }
269 OpKind getOp() const { return Op; }
Karl Schimpfd6064a12014-08-27 15:34:58 -0700270 static const char *getOpName(OpKind Op);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700271 bool isCommutative() const;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700272 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700273 static bool classof(const Inst *Inst) {
274 return Inst->getKind() == Arithmetic;
275 }
276
277private:
278 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
279 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700280 ~InstArithmetic() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700281
282 const OpKind Op;
283};
284
285// Assignment instruction. The source operand is captured in
286// getSrc(0). This is not part of the LLVM bitcode, but is a useful
287// abstraction for some of the lowering. E.g., if Phi instruction
288// lowering happens before target lowering, or for representing an
289// Inttoptr instruction, or as an intermediate step for lowering a
290// Load instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700291class InstAssign : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700292 InstAssign(const InstAssign &) = delete;
293 InstAssign &operator=(const InstAssign &) = delete;
294
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700295public:
296 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800297 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700298 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700299 bool isSimpleAssign() const override { return true; }
300 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700301 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
302
303private:
304 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700305 ~InstAssign() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700306};
307
308// Branch instruction. This represents both conditional and
309// unconditional branches.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700310class InstBr : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700311 InstBr(const InstBr &) = delete;
312 InstBr &operator=(const InstBr &) = delete;
313
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700314public:
315 // Create a conditional branch. If TargetTrue==TargetFalse, it is
316 // optimized to an unconditional branch.
317 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
318 CfgNode *TargetFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800319 return new (Func->allocate<InstBr>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700320 InstBr(Func, Source, TargetTrue, TargetFalse);
321 }
322 // Create an unconditional branch.
323 static InstBr *create(Cfg *Func, CfgNode *Target) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800324 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700325 }
Jim Stichnothae953202014-12-20 06:17:49 -0800326 bool isUnconditional() const { return getTargetTrue() == nullptr; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700327 Operand *getCondition() const {
328 assert(!isUnconditional());
329 return getSrc(0);
330 }
331 CfgNode *getTargetTrue() const { return TargetTrue; }
332 CfgNode *getTargetFalse() const { return TargetFalse; }
333 CfgNode *getTargetUnconditional() const {
334 assert(isUnconditional());
335 return getTargetFalse();
336 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700337 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700338 bool isUnconditionalBranch() const override { return isUnconditional(); }
339 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700340 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700341 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
342
343private:
344 // Conditional branch
345 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
346 // Unconditional branch
347 InstBr(Cfg *Func, CfgNode *Target);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700348 ~InstBr() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700349
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700350 CfgNode *TargetFalse; // Doubles as unconditional branch target
Jim Stichnothae953202014-12-20 06:17:49 -0800351 CfgNode *TargetTrue; // nullptr if unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700352};
353
354// Call instruction. The call target is captured as getSrc(0), and
355// arg I is captured as getSrc(I+1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700356class InstCall : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700357 InstCall(const InstCall &) = delete;
358 InstCall &operator=(const InstCall &) = delete;
359
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700360public:
361 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700362 Operand *CallTarget, bool HasTailCall) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700363 // Set HasSideEffects to true so that the call instruction can't be
364 // dead-code eliminated. IntrinsicCalls can override this if the
365 // particular intrinsic is deletable and has no side-effects.
366 const bool HasSideEffects = true;
367 const InstKind Kind = Inst::Call;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800368 return new (Func->allocate<InstCall>()) InstCall(
Karl Schimpf8df26f32014-09-19 09:33:26 -0700369 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700370 }
371 void addArg(Operand *Arg) { addSource(Arg); }
372 Operand *getCallTarget() const { return getSrc(0); }
373 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
374 SizeT getNumArgs() const { return getSrcSize() - 1; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700375 bool isTailcall() const { return HasTailCall; }
Jan Voung3ce1a992015-02-03 08:27:44 -0800376 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700377 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700378 Type getReturnType() const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700379
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700380protected:
381 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700382 bool HasTailCall, bool HasSideEff, InstKind Kind)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700383 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700384 HasSideEffects = HasSideEff;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700385 addSource(CallTarget);
386 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700387 ~InstCall() override {}
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700388
389private:
Karl Schimpf8df26f32014-09-19 09:33:26 -0700390 bool HasTailCall;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700391};
392
393// Cast instruction (a.k.a. conversion operation).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700394class InstCast : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700395 InstCast(const InstCast &) = delete;
396 InstCast &operator=(const InstCast &) = delete;
397
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700398public:
399 enum OpKind {
400#define X(tag, str) tag,
401 ICEINSTCAST_TABLE
402#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700403 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700404 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700405
Karl Schimpfbf170372014-12-15 10:16:31 -0800406 static const char *getCastName(OpKind Kind);
407
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700408 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
409 Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800410 return new (Func->allocate<InstCast>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700411 InstCast(Func, CastKind, Dest, Source);
412 }
413 OpKind getCastKind() const { return CastKind; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700414 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700415 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
416
417private:
418 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700419 ~InstCast() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700420 const OpKind CastKind;
421};
422
Matt Wala49889232014-07-18 12:45:09 -0700423// ExtractElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700424class InstExtractElement : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700425 InstExtractElement(const InstExtractElement &) = delete;
426 InstExtractElement &operator=(const InstExtractElement &) = delete;
427
Matt Wala49889232014-07-18 12:45:09 -0700428public:
429 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
430 Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800431 return new (Func->allocate<InstExtractElement>())
Matt Wala49889232014-07-18 12:45:09 -0700432 InstExtractElement(Func, Dest, Source1, Source2);
433 }
434
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700435 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700436 static bool classof(const Inst *Inst) {
437 return Inst->getKind() == ExtractElement;
438 }
439
440private:
441 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
442 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700443 ~InstExtractElement() override {}
Matt Wala49889232014-07-18 12:45:09 -0700444};
445
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700446// Floating-point comparison instruction. The source operands are
447// captured in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700448class InstFcmp : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700449 InstFcmp(const InstFcmp &) = delete;
450 InstFcmp &operator=(const InstFcmp &) = delete;
451
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700452public:
453 enum FCond {
454#define X(tag, str) tag,
455 ICEINSTFCMP_TABLE
456#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700457 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700458 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700459
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700460 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
461 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800462 return new (Func->allocate<InstFcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700463 InstFcmp(Func, Condition, Dest, Source1, Source2);
464 }
465 FCond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700466 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700467 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
468
469private:
470 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
471 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700472 ~InstFcmp() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700473 const FCond Condition;
474};
475
476// Integer comparison instruction. The source operands are captured
477// in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700478class InstIcmp : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700479 InstIcmp(const InstIcmp &) = delete;
480 InstIcmp &operator=(const InstIcmp &) = delete;
481
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700482public:
483 enum ICond {
484#define X(tag, str) tag,
485 ICEINSTICMP_TABLE
486#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700487 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700488 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700489
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700490 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
491 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800492 return new (Func->allocate<InstIcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700493 InstIcmp(Func, Condition, Dest, Source1, Source2);
494 }
495 ICond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700496 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700497 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
498
499private:
500 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
501 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700502 ~InstIcmp() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700503 const ICond Condition;
504};
505
Matt Wala49889232014-07-18 12:45:09 -0700506// InsertElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700507class InstInsertElement : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700508 InstInsertElement(const InstInsertElement &) = delete;
509 InstInsertElement &operator=(const InstInsertElement &) = delete;
510
Matt Wala49889232014-07-18 12:45:09 -0700511public:
512 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
513 Operand *Source2, Operand *Source3) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800514 return new (Func->allocate<InstInsertElement>())
Matt Wala49889232014-07-18 12:45:09 -0700515 InstInsertElement(Func, Dest, Source1, Source2, Source3);
516 }
517
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700518 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700519 static bool classof(const Inst *Inst) {
520 return Inst->getKind() == InsertElement;
521 }
522
523private:
524 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
525 Operand *Source2, Operand *Source3);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700526 ~InstInsertElement() override {}
Matt Wala49889232014-07-18 12:45:09 -0700527};
528
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700529// Call to an intrinsic function. The call target is captured as getSrc(0),
530// and arg I is captured as getSrc(I+1).
531class InstIntrinsicCall : public InstCall {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700532 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
533 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
534
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700535public:
536 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
537 Operand *CallTarget,
538 const Intrinsics::IntrinsicInfo &Info) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800539 return new (Func->allocate<InstIntrinsicCall>())
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700540 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
541 }
542 static bool classof(const Inst *Inst) {
543 return Inst->getKind() == IntrinsicCall;
544 }
545
546 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
547
548private:
549 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
550 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
Karl Schimpf8df26f32014-09-19 09:33:26 -0700551 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700552 Inst::IntrinsicCall),
553 Info(Info) {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700554 ~InstIntrinsicCall() override {}
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700555 const Intrinsics::IntrinsicInfo Info;
556};
557
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700558// Load instruction. The source address is captured in getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700559class InstLoad : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700560 InstLoad(const InstLoad &) = delete;
561 InstLoad &operator=(const InstLoad &) = delete;
562
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700563public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700564 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
Jim Stichnothc4554d72014-09-30 16:49:38 -0700565 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700566 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700567 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800568 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700569 }
570 Operand *getSourceAddress() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700571 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700572 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
573
574private:
575 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700576 ~InstLoad() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700577};
578
579// Phi instruction. For incoming edge I, the node is Labels[I] and
580// the Phi source operand is getSrc(I).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700581class InstPhi : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700582 InstPhi(const InstPhi &) = delete;
583 InstPhi &operator=(const InstPhi &) = delete;
584
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700585public:
586 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800587 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700588 }
589 void addArgument(Operand *Source, CfgNode *Label);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700590 Operand *getOperandForTarget(CfgNode *Target) const;
Jim Stichnoth98712a32014-10-24 10:59:02 -0700591 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700592 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700593 Liveness *Liveness);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700594 Inst *lower(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700595 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700596 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
597
598private:
599 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700600 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700601 Func->deallocateArrayOf<CfgNode *>(Labels);
602 Inst::destroy(Func);
603 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700604 ~InstPhi() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700605
606 // Labels[] duplicates the InEdges[] information in the enclosing
607 // CfgNode, but the Phi instruction is created before InEdges[]
608 // is available, so it's more complicated to share the list.
609 CfgNode **Labels;
610};
611
612// Ret instruction. The return value is captured in getSrc(0), but if
613// there is no return value (void-type function), then
614// getSrcSize()==0 and hasRetValue()==false.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700615class InstRet : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700616 InstRet(const InstRet &) = delete;
617 InstRet &operator=(const InstRet &) = delete;
618
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700619public:
Jim Stichnothae953202014-12-20 06:17:49 -0800620 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800621 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700622 }
623 bool hasRetValue() const { return getSrcSize(); }
624 Operand *getRetValue() const {
625 assert(hasRetValue());
626 return getSrc(0);
627 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700628 NodeList getTerminatorEdges() const override { return NodeList(); }
629 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700630 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
631
632private:
633 InstRet(Cfg *Func, Operand *RetValue);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700634 ~InstRet() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700635};
636
637// Select instruction. The condition, true, and false operands are captured.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700638class InstSelect : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700639 InstSelect(const InstSelect &) = delete;
640 InstSelect &operator=(const InstSelect &) = delete;
641
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700642public:
643 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
644 Operand *SourceTrue, Operand *SourceFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800645 return new (Func->allocate<InstSelect>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700646 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
647 }
648 Operand *getCondition() const { return getSrc(0); }
649 Operand *getTrueOperand() const { return getSrc(1); }
650 Operand *getFalseOperand() const { return getSrc(2); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700651 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700652 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
653
654private:
655 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
656 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700657 ~InstSelect() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700658};
659
660// Store instruction. The address operand is captured, along with the
661// data operand to be stored into the address.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700662class InstStore : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700663 InstStore(const InstStore &) = delete;
664 InstStore &operator=(const InstStore &) = delete;
665
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700666public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700667 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
668 uint32_t align = 1) {
669 // TODO(kschimpf) Stop ignoring alignment specification.
670 (void)align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800671 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700672 }
673 Operand *getAddr() const { return getSrc(1); }
674 Operand *getData() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700675 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700676 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
677
678private:
679 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700680 ~InstStore() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700681};
682
683// Switch instruction. The single source operand is captured as
684// getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700685class InstSwitch : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700686 InstSwitch(const InstSwitch &) = delete;
687 InstSwitch &operator=(const InstSwitch &) = delete;
688
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700689public:
690 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
691 CfgNode *LabelDefault) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800692 return new (Func->allocate<InstSwitch>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700693 InstSwitch(Func, NumCases, Source, LabelDefault);
694 }
695 Operand *getComparison() const { return getSrc(0); }
696 CfgNode *getLabelDefault() const { return LabelDefault; }
697 SizeT getNumCases() const { return NumCases; }
698 uint64_t getValue(SizeT I) const {
699 assert(I < NumCases);
700 return Values[I];
701 }
702 CfgNode *getLabel(SizeT I) const {
703 assert(I < NumCases);
704 return Labels[I];
705 }
706 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700707 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700708 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700709 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700710 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
711
712private:
713 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700714 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700715 Func->deallocateArrayOf<uint64_t>(Values);
716 Func->deallocateArrayOf<CfgNode *>(Labels);
717 Inst::destroy(Func);
718 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700719 ~InstSwitch() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700720
721 CfgNode *LabelDefault;
722 SizeT NumCases; // not including the default case
723 uint64_t *Values; // size is NumCases
724 CfgNode **Labels; // size is NumCases
725};
726
727// Unreachable instruction. This is a terminator instruction with no
728// operands.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700729class InstUnreachable : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700730 InstUnreachable(const InstUnreachable &) = delete;
731 InstUnreachable &operator=(const InstUnreachable &) = delete;
732
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700733public:
734 static InstUnreachable *create(Cfg *Func) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800735 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700736 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700737 NodeList getTerminatorEdges() const override { return NodeList(); }
738 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700739 static bool classof(const Inst *Inst) {
740 return Inst->getKind() == Unreachable;
741 }
742
743private:
744 InstUnreachable(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700745 ~InstUnreachable() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700746};
747
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800748// BundleLock instruction. There are no operands. Contains an option
749// indicating whether align_to_end is specified.
750class InstBundleLock : public InstHighLevel {
751 InstBundleLock(const InstBundleLock &) = delete;
752 InstBundleLock &operator=(const InstBundleLock &) = delete;
753
754public:
755 enum Option { Opt_None, Opt_AlignToEnd };
756 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
757 return new (Func->allocate<InstBundleLock>())
758 InstBundleLock(Func, BundleOption);
759 }
760 void emit(const Cfg *Func) const override;
761 void emitIAS(const Cfg * /* Func */) const override {}
762 void dump(const Cfg *Func) const override;
763 Option getOption() const { return BundleOption; }
764 static bool classof(const Inst *Inst) {
765 return Inst->getKind() == BundleLock;
766 }
767
768private:
769 Option BundleOption;
770 InstBundleLock(Cfg *Func, Option BundleOption);
771 ~InstBundleLock() override {}
772};
773
774// BundleUnlock instruction. There are no operands.
775class InstBundleUnlock : public InstHighLevel {
776 InstBundleUnlock(const InstBundleUnlock &) = delete;
777 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
778
779public:
780 static InstBundleUnlock *create(Cfg *Func) {
781 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
782 }
783 void emit(const Cfg *Func) const override;
784 void emitIAS(const Cfg * /* Func */) const override {}
785 void dump(const Cfg *Func) const override;
786 static bool classof(const Inst *Inst) {
787 return Inst->getKind() == BundleUnlock;
788 }
789
790private:
791 explicit InstBundleUnlock(Cfg *Func);
792 ~InstBundleUnlock() override {}
793};
794
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700795// FakeDef instruction. This creates a fake definition of a variable,
796// which is how we represent the case when an instruction produces
797// multiple results. This doesn't happen with high-level ICE
798// instructions, but might with lowered instructions. For example,
799// this would be a way to represent condition flags being modified by
800// an instruction.
801//
802// It's generally useful to set the optional source operand to be the
803// dest variable of the instruction that actually produces the FakeDef
804// dest. Otherwise, the original instruction could be dead-code
805// eliminated if its dest operand is unused, and therefore the FakeDef
806// dest wouldn't be properly initialized.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700807class InstFakeDef : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700808 InstFakeDef(const InstFakeDef &) = delete;
809 InstFakeDef &operator=(const InstFakeDef &) = delete;
810
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700811public:
Jim Stichnothae953202014-12-20 06:17:49 -0800812 static InstFakeDef *create(Cfg *Func, Variable *Dest,
813 Variable *Src = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800814 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700815 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700816 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700817 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700818 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700819 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
820
821private:
822 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700823 ~InstFakeDef() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700824};
825
826// FakeUse instruction. This creates a fake use of a variable, to
827// keep the instruction that produces that variable from being
828// dead-code eliminated. This is useful in a variety of lowering
829// situations. The FakeUse instruction has no dest, so it can itself
830// never be dead-code eliminated.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700831class InstFakeUse : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700832 InstFakeUse(const InstFakeUse &) = delete;
833 InstFakeUse &operator=(const InstFakeUse &) = delete;
834
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700835public:
836 static InstFakeUse *create(Cfg *Func, Variable *Src) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800837 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700838 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700839 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700840 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700841 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700842 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
843
844private:
845 InstFakeUse(Cfg *Func, Variable *Src);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700846 ~InstFakeUse() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700847};
848
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800849// FakeKill instruction. This "kills" a set of variables by modeling
850// a trivial live range at this instruction for each (implicit)
851// variable. The primary use is to indicate that scratch registers
852// are killed after a call, so that the register allocator won't
853// assign a scratch register to a variable whose live range spans a
854// call.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700855//
856// The FakeKill instruction also holds a pointer to the instruction
857// that kills the set of variables, so that if that linked instruction
858// gets dead-code eliminated, the FakeKill instruction will as well.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700859class InstFakeKill : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700860 InstFakeKill(const InstFakeKill &) = delete;
861 InstFakeKill &operator=(const InstFakeKill &) = delete;
862
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700863public:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800864 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800865 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700866 }
867 const Inst *getLinked() const { return Linked; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700868 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700869 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700870 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700871 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
872
873private:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800874 InstFakeKill(Cfg *Func, const Inst *Linked);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700875 ~InstFakeKill() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700876
877 // This instruction is ignored if Linked->isDeleted() is true.
878 const Inst *Linked;
879};
880
881// The Target instruction is the base class for all target-specific
882// instructions.
883class InstTarget : public Inst {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700884 InstTarget(const InstTarget &) = delete;
885 InstTarget &operator=(const InstTarget &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700886
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700887public:
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700888 uint32_t getEmitInstCount() const override { return 1; }
889 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700890 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
891
892protected:
893 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
894 : Inst(Func, Kind, MaxSrcs, Dest) {
895 assert(Kind >= Target);
896 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700897 ~InstTarget() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700898};
899
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700900} // end of namespace Ice
901
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800902namespace llvm {
903
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800904// Override the default ilist traits so that Inst's private ctor and
905// deleted dtor aren't invoked.
906template <>
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800907struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800908 Ice::Inst *createSentinel() const {
909 return static_cast<Ice::Inst *>(&Sentinel);
910 }
911 static void destroySentinel(Ice::Inst *) {}
912 Ice::Inst *provideInitialHead() const { return createSentinel(); }
913 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
914 static void noteHead(Ice::Inst *, Ice::Inst *) {}
915 void deleteNode(Ice::Inst *) {}
916
917private:
918 mutable ilist_half_node<Ice::Inst> Sentinel;
919};
920
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800921} // end of namespace llvm
922
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700923#endif // SUBZERO_SRC_ICEINST_H