blob: 8dd77eca231f8d9bd2309c4f054636e5a5896653 [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,
62 FakeDef, // not part of LLVM/PNaCl bitcode
63 FakeUse, // not part of LLVM/PNaCl bitcode
64 FakeKill, // not part of LLVM/PNaCl bitcode
65 Target // target-specific low-level ICE
66 // Anything >= Target is an InstTarget subclass.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067 };
68 InstKind getKind() const { return Kind; }
69
Jim Stichnothd97c7df2014-06-04 11:57:08 -070070 InstNumberT getNumber() const { return Number; }
71 void renumber(Cfg *Func);
Jim Stichnothe5b73e62014-12-15 09:58:51 -080072 enum {
73 NumberDeleted = -1,
74 NumberSentinel = 0,
75 NumberInitial = 2,
76 NumberExtended = NumberInitial - 1
77 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -070078
79 bool isDeleted() const { return Deleted; }
80 void setDeleted() { Deleted = true; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070081 void deleteIfDead();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070082
83 bool hasSideEffects() const { return HasSideEffects; }
84
Jim Stichnoth47752552014-10-13 17:15:08 -070085 bool isDestNonKillable() const { return IsDestNonKillable; }
86 void setDestNonKillable() { IsDestNonKillable = true; }
87
Jim Stichnothf7c9a142014-04-29 10:52:43 -070088 Variable *getDest() const { return Dest; }
89
90 SizeT getSrcSize() const { return NumSrcs; }
91 Operand *getSrc(SizeT I) const {
92 assert(I < getSrcSize());
93 return Srcs[I];
94 }
95
Jim Stichnothd97c7df2014-06-04 11:57:08 -070096 bool isLastUse(const Operand *Src) const;
97
Jim Stichnothf7c9a142014-04-29 10:52:43 -070098 // Returns a list of out-edges corresponding to a terminator
99 // instruction, which is the last instruction of the block.
100 virtual NodeList getTerminatorEdges() const {
101 // All valid terminator instructions override this method. For
102 // the default implementation, we assert in case some CfgNode
103 // is constructed without a terminator instruction at the end.
104 llvm_unreachable(
105 "getTerminatorEdges() called on a non-terminator instruction");
106 return NodeList();
107 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700108 virtual bool isUnconditionalBranch() const { return false; }
109 // If the instruction is a branch-type instruction with OldNode as a
110 // target, repoint it to NewNode and return true, otherwise return
111 // false. Only repoint one instance, even if the instruction has
112 // multiple instances of OldNode as a target.
113 virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
114 (void)OldNode;
115 (void)NewNode;
116 return false;
117 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700118
Jim Stichnothad403532014-09-25 12:44:17 -0700119 virtual bool isSimpleAssign() const { return false; }
120
Jim Stichnoth47752552014-10-13 17:15:08 -0700121 void livenessLightweight(Cfg *Func, LivenessBV &Live);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700122 // Calculates liveness for this instruction. Returns true if this
123 // instruction is (tentatively) still live and should be retained,
124 // and false if this instruction is (tentatively) dead and should be
125 // deleted. The decision is tentative until the liveness dataflow
126 // algorithm has converged, and then a separate pass permanently
127 // deletes dead instructions.
128 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
Jim Stichnoth47752552014-10-13 17:15:08 -0700129 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
Jim Stichnoth18735602014-09-16 19:59:35 -0700130
131 // Get the number of native instructions that this instruction
132 // ultimately emits. By default, high-level instructions don't
133 // result in any native instructions, and a target-specific
134 // instruction results in a single native instruction.
135 virtual uint32_t getEmitInstCount() const { return 0; }
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800136 // TODO(stichnot): Change Inst back to abstract once the g++ build
137 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++
138 // because the resize(size_t, Ice::Inst) method is incorrectly
139 // declared and thus doesn't allow the abstract class Ice::Inst.
140 // The method should be declared resize(size_t, const Ice::Inst &).
141 // virtual void emit(const Cfg *Func) const = 0;
142 // virtual void emitIAS(const Cfg *Func) const = 0;
143 virtual void emit(const Cfg *) const {
144 llvm_unreachable("emit on abstract class");
145 }
146 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700147 virtual void dump(const Cfg *Func) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700148 virtual void dumpExtras(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700149 void dumpDecorated(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700150 void emitSources(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700151 void dumpSources(const Cfg *Func) const;
152 void dumpDest(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700153 virtual bool isRedundantAssign() const { return false; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700154
155 virtual ~Inst() {}
156
157protected:
158 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
159 void addSource(Operand *Src) {
160 assert(Src);
161 assert(NumSrcs < MaxSrcs);
162 Srcs[NumSrcs++] = Src;
163 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700164 void setLastUse(SizeT VarIndex) {
165 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
166 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
167 }
168 void resetLastUses() { LiveRangesEnded = 0; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700169 // The destroy() method lets the instruction cleanly release any
170 // memory that was allocated via the Cfg's allocator.
171 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
172
173 const InstKind Kind;
174 // Number is the instruction number for describing live ranges.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700175 InstNumberT Number;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700176 // Deleted means irrevocably deleted.
177 bool Deleted;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700178 // Dead means pending deletion after liveness analysis converges.
179 bool Dead;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700180 // HasSideEffects means the instruction is something like a function
181 // call or a volatile load that can't be removed even if its Dest
182 // variable is not live.
183 bool HasSideEffects;
Jim Stichnoth47752552014-10-13 17:15:08 -0700184 // IsDestNonKillable means that liveness analysis shouldn't consider
185 // this instruction to kill the Dest variable. This is used when
186 // lowering produces two assignments to the same variable.
187 bool IsDestNonKillable;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700188
189 Variable *Dest;
190 const SizeT MaxSrcs; // only used for assert
191 SizeT NumSrcs;
192 Operand **Srcs;
193
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700194 // LiveRangesEnded marks which Variables' live ranges end in this
195 // instruction. An instruction can have an arbitrary number of
196 // source operands (e.g. a call instruction), and each source
197 // operand can contain 0 or 1 Variable (and target-specific operands
198 // could contain more than 1 Variable). All the variables in an
199 // instruction are conceptually flattened and each variable is
200 // mapped to one bit position of the LiveRangesEnded bit vector.
201 // Only the first CHAR_BIT * sizeof(LREndedBits) variables are
202 // tracked this way.
203 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
204 LREndedBits LiveRangesEnded;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700205};
206
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700207class InstHighLevel : public Inst {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700208 InstHighLevel(const InstHighLevel &) = delete;
209 InstHighLevel &operator=(const InstHighLevel &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700210
211protected:
212 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
213 : Inst(Func, Kind, MaxSrcs, Dest) {}
214 void emit(const Cfg * /*Func*/) const override {
215 llvm_unreachable("emit() called on a non-lowered instruction");
216 }
217 void emitIAS(const Cfg * /*Func*/) const override {
218 llvm_unreachable("emitIAS() called on a non-lowered instruction");
219 }
220 ~InstHighLevel() override {}
221};
222
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700223// Alloca instruction. This captures the size in bytes as getSrc(0),
224// and the required alignment in bytes. The alignment must be either
225// 0 (no alignment required) or a power of 2.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700226class InstAlloca : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700227 InstAlloca(const InstAlloca &) = delete;
228 InstAlloca &operator=(const InstAlloca &) = delete;
229
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700230public:
231 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
232 uint32_t AlignInBytes, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800233 return new (Func->allocate<InstAlloca>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700234 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
235 }
236 uint32_t getAlignInBytes() const { return AlignInBytes; }
237 Operand *getSizeInBytes() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700238 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700239 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
240
241private:
242 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
243 Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700244 ~InstAlloca() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700245 const uint32_t AlignInBytes;
246};
247
248// Binary arithmetic instruction. The source operands are captured in
249// getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700250class InstArithmetic : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700251 InstArithmetic(const InstArithmetic &) = delete;
252 InstArithmetic &operator=(const InstArithmetic &) = delete;
253
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700254public:
255 enum OpKind {
256#define X(tag, str, commutative) tag,
257 ICEINSTARITHMETIC_TABLE
258#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700259 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700260 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700261
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700262 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
263 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800264 return new (Func->allocate<InstArithmetic>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700265 InstArithmetic(Func, Op, Dest, Source1, Source2);
266 }
267 OpKind getOp() const { return Op; }
Karl Schimpfd6064a12014-08-27 15:34:58 -0700268 static const char *getOpName(OpKind Op);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700269 bool isCommutative() const;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700270 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700271 static bool classof(const Inst *Inst) {
272 return Inst->getKind() == Arithmetic;
273 }
274
275private:
276 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
277 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700278 ~InstArithmetic() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700279
280 const OpKind Op;
281};
282
283// Assignment instruction. The source operand is captured in
284// getSrc(0). This is not part of the LLVM bitcode, but is a useful
285// abstraction for some of the lowering. E.g., if Phi instruction
286// lowering happens before target lowering, or for representing an
287// Inttoptr instruction, or as an intermediate step for lowering a
288// Load instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700289class InstAssign : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700290 InstAssign(const InstAssign &) = delete;
291 InstAssign &operator=(const InstAssign &) = delete;
292
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700293public:
294 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800295 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700296 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700297 bool isSimpleAssign() const override { return true; }
298 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700299 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
300
301private:
302 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700303 ~InstAssign() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700304};
305
306// Branch instruction. This represents both conditional and
307// unconditional branches.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700308class InstBr : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700309 InstBr(const InstBr &) = delete;
310 InstBr &operator=(const InstBr &) = delete;
311
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700312public:
313 // Create a conditional branch. If TargetTrue==TargetFalse, it is
314 // optimized to an unconditional branch.
315 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
316 CfgNode *TargetFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800317 return new (Func->allocate<InstBr>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700318 InstBr(Func, Source, TargetTrue, TargetFalse);
319 }
320 // Create an unconditional branch.
321 static InstBr *create(Cfg *Func, CfgNode *Target) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800322 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700323 }
Jim Stichnothae953202014-12-20 06:17:49 -0800324 bool isUnconditional() const { return getTargetTrue() == nullptr; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700325 Operand *getCondition() const {
326 assert(!isUnconditional());
327 return getSrc(0);
328 }
329 CfgNode *getTargetTrue() const { return TargetTrue; }
330 CfgNode *getTargetFalse() const { return TargetFalse; }
331 CfgNode *getTargetUnconditional() const {
332 assert(isUnconditional());
333 return getTargetFalse();
334 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700335 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700336 bool isUnconditionalBranch() const override { return isUnconditional(); }
337 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700338 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700339 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
340
341private:
342 // Conditional branch
343 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
344 // Unconditional branch
345 InstBr(Cfg *Func, CfgNode *Target);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700346 ~InstBr() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700347
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700348 CfgNode *TargetFalse; // Doubles as unconditional branch target
Jim Stichnothae953202014-12-20 06:17:49 -0800349 CfgNode *TargetTrue; // nullptr if unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700350};
351
352// Call instruction. The call target is captured as getSrc(0), and
353// arg I is captured as getSrc(I+1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700354class InstCall : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700355 InstCall(const InstCall &) = delete;
356 InstCall &operator=(const InstCall &) = delete;
357
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700358public:
359 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700360 Operand *CallTarget, bool HasTailCall) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700361 // Set HasSideEffects to true so that the call instruction can't be
362 // dead-code eliminated. IntrinsicCalls can override this if the
363 // particular intrinsic is deletable and has no side-effects.
364 const bool HasSideEffects = true;
365 const InstKind Kind = Inst::Call;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800366 return new (Func->allocate<InstCall>()) InstCall(
Karl Schimpf8df26f32014-09-19 09:33:26 -0700367 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700368 }
369 void addArg(Operand *Arg) { addSource(Arg); }
370 Operand *getCallTarget() const { return getSrc(0); }
371 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
372 SizeT getNumArgs() const { return getSrcSize() - 1; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700373 bool isTailcall() const { return HasTailCall; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700374 void dump(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700375 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700376 Type getReturnType() const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700377
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700378protected:
379 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700380 bool HasTailCall, bool HasSideEff, InstKind Kind)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700381 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700382 HasSideEffects = HasSideEff;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700383 addSource(CallTarget);
384 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700385 ~InstCall() override {}
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700386
387private:
Karl Schimpf8df26f32014-09-19 09:33:26 -0700388 bool HasTailCall;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700389};
390
391// Cast instruction (a.k.a. conversion operation).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700392class InstCast : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700393 InstCast(const InstCast &) = delete;
394 InstCast &operator=(const InstCast &) = delete;
395
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700396public:
397 enum OpKind {
398#define X(tag, str) tag,
399 ICEINSTCAST_TABLE
400#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700401 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700402 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700403
Karl Schimpfbf170372014-12-15 10:16:31 -0800404 static const char *getCastName(OpKind Kind);
405
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700406 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
407 Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800408 return new (Func->allocate<InstCast>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700409 InstCast(Func, CastKind, Dest, Source);
410 }
411 OpKind getCastKind() const { return CastKind; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700412 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700413 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
414
415private:
416 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700417 ~InstCast() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700418 const OpKind CastKind;
419};
420
Matt Wala49889232014-07-18 12:45:09 -0700421// ExtractElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700422class InstExtractElement : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700423 InstExtractElement(const InstExtractElement &) = delete;
424 InstExtractElement &operator=(const InstExtractElement &) = delete;
425
Matt Wala49889232014-07-18 12:45:09 -0700426public:
427 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
428 Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800429 return new (Func->allocate<InstExtractElement>())
Matt Wala49889232014-07-18 12:45:09 -0700430 InstExtractElement(Func, Dest, Source1, Source2);
431 }
432
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700433 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700434 static bool classof(const Inst *Inst) {
435 return Inst->getKind() == ExtractElement;
436 }
437
438private:
439 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
440 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700441 ~InstExtractElement() override {}
Matt Wala49889232014-07-18 12:45:09 -0700442};
443
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700444// Floating-point comparison instruction. The source operands are
445// captured in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700446class InstFcmp : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700447 InstFcmp(const InstFcmp &) = delete;
448 InstFcmp &operator=(const InstFcmp &) = delete;
449
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700450public:
451 enum FCond {
452#define X(tag, str) tag,
453 ICEINSTFCMP_TABLE
454#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700455 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700456 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700457
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700458 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
459 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800460 return new (Func->allocate<InstFcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700461 InstFcmp(Func, Condition, Dest, Source1, Source2);
462 }
463 FCond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700464 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700465 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
466
467private:
468 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
469 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700470 ~InstFcmp() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700471 const FCond Condition;
472};
473
474// Integer comparison instruction. The source operands are captured
475// in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700476class InstIcmp : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700477 InstIcmp(const InstIcmp &) = delete;
478 InstIcmp &operator=(const InstIcmp &) = delete;
479
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700480public:
481 enum ICond {
482#define X(tag, str) tag,
483 ICEINSTICMP_TABLE
484#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700485 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700486 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700487
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700488 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
489 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800490 return new (Func->allocate<InstIcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700491 InstIcmp(Func, Condition, Dest, Source1, Source2);
492 }
493 ICond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700494 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700495 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
496
497private:
498 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
499 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700500 ~InstIcmp() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700501 const ICond Condition;
502};
503
Matt Wala49889232014-07-18 12:45:09 -0700504// InsertElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700505class InstInsertElement : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700506 InstInsertElement(const InstInsertElement &) = delete;
507 InstInsertElement &operator=(const InstInsertElement &) = delete;
508
Matt Wala49889232014-07-18 12:45:09 -0700509public:
510 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
511 Operand *Source2, Operand *Source3) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800512 return new (Func->allocate<InstInsertElement>())
Matt Wala49889232014-07-18 12:45:09 -0700513 InstInsertElement(Func, Dest, Source1, Source2, Source3);
514 }
515
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700516 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700517 static bool classof(const Inst *Inst) {
518 return Inst->getKind() == InsertElement;
519 }
520
521private:
522 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
523 Operand *Source2, Operand *Source3);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700524 ~InstInsertElement() override {}
Matt Wala49889232014-07-18 12:45:09 -0700525};
526
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700527// Call to an intrinsic function. The call target is captured as getSrc(0),
528// and arg I is captured as getSrc(I+1).
529class InstIntrinsicCall : public InstCall {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700530 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
531 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
532
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700533public:
534 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
535 Operand *CallTarget,
536 const Intrinsics::IntrinsicInfo &Info) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800537 return new (Func->allocate<InstIntrinsicCall>())
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700538 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
539 }
540 static bool classof(const Inst *Inst) {
541 return Inst->getKind() == IntrinsicCall;
542 }
543
544 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
545
546private:
547 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
548 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
Karl Schimpf8df26f32014-09-19 09:33:26 -0700549 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700550 Inst::IntrinsicCall),
551 Info(Info) {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700552 ~InstIntrinsicCall() override {}
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700553 const Intrinsics::IntrinsicInfo Info;
554};
555
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700556// Load instruction. The source address is captured in getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700557class InstLoad : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700558 InstLoad(const InstLoad &) = delete;
559 InstLoad &operator=(const InstLoad &) = delete;
560
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700561public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700562 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
Jim Stichnothc4554d72014-09-30 16:49:38 -0700563 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700564 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700565 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800566 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700567 }
568 Operand *getSourceAddress() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700569 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700570 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
571
572private:
573 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700574 ~InstLoad() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700575};
576
577// Phi instruction. For incoming edge I, the node is Labels[I] and
578// the Phi source operand is getSrc(I).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700579class InstPhi : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700580 InstPhi(const InstPhi &) = delete;
581 InstPhi &operator=(const InstPhi &) = delete;
582
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700583public:
584 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800585 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700586 }
587 void addArgument(Operand *Source, CfgNode *Label);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700588 Operand *getOperandForTarget(CfgNode *Target) const;
Jim Stichnoth98712a32014-10-24 10:59:02 -0700589 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700590 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700591 Liveness *Liveness);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700592 Inst *lower(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700593 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700594 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
595
596private:
597 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700598 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700599 Func->deallocateArrayOf<CfgNode *>(Labels);
600 Inst::destroy(Func);
601 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700602 ~InstPhi() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700603
604 // Labels[] duplicates the InEdges[] information in the enclosing
605 // CfgNode, but the Phi instruction is created before InEdges[]
606 // is available, so it's more complicated to share the list.
607 CfgNode **Labels;
608};
609
610// Ret instruction. The return value is captured in getSrc(0), but if
611// there is no return value (void-type function), then
612// getSrcSize()==0 and hasRetValue()==false.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700613class InstRet : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700614 InstRet(const InstRet &) = delete;
615 InstRet &operator=(const InstRet &) = delete;
616
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700617public:
Jim Stichnothae953202014-12-20 06:17:49 -0800618 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800619 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700620 }
621 bool hasRetValue() const { return getSrcSize(); }
622 Operand *getRetValue() const {
623 assert(hasRetValue());
624 return getSrc(0);
625 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700626 NodeList getTerminatorEdges() const override { return NodeList(); }
627 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700628 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
629
630private:
631 InstRet(Cfg *Func, Operand *RetValue);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700632 ~InstRet() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700633};
634
635// Select instruction. The condition, true, and false operands are captured.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700636class InstSelect : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700637 InstSelect(const InstSelect &) = delete;
638 InstSelect &operator=(const InstSelect &) = delete;
639
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700640public:
641 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
642 Operand *SourceTrue, Operand *SourceFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800643 return new (Func->allocate<InstSelect>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700644 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
645 }
646 Operand *getCondition() const { return getSrc(0); }
647 Operand *getTrueOperand() const { return getSrc(1); }
648 Operand *getFalseOperand() const { return getSrc(2); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700649 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700650 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
651
652private:
653 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
654 Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700655 ~InstSelect() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700656};
657
658// Store instruction. The address operand is captured, along with the
659// data operand to be stored into the address.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700660class InstStore : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700661 InstStore(const InstStore &) = delete;
662 InstStore &operator=(const InstStore &) = delete;
663
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700664public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700665 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
666 uint32_t align = 1) {
667 // TODO(kschimpf) Stop ignoring alignment specification.
668 (void)align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800669 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700670 }
671 Operand *getAddr() const { return getSrc(1); }
672 Operand *getData() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700673 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700674 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
675
676private:
677 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700678 ~InstStore() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700679};
680
681// Switch instruction. The single source operand is captured as
682// getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700683class InstSwitch : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700684 InstSwitch(const InstSwitch &) = delete;
685 InstSwitch &operator=(const InstSwitch &) = delete;
686
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700687public:
688 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
689 CfgNode *LabelDefault) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800690 return new (Func->allocate<InstSwitch>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700691 InstSwitch(Func, NumCases, Source, LabelDefault);
692 }
693 Operand *getComparison() const { return getSrc(0); }
694 CfgNode *getLabelDefault() const { return LabelDefault; }
695 SizeT getNumCases() const { return NumCases; }
696 uint64_t getValue(SizeT I) const {
697 assert(I < NumCases);
698 return Values[I];
699 }
700 CfgNode *getLabel(SizeT I) const {
701 assert(I < NumCases);
702 return Labels[I];
703 }
704 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700705 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700706 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700707 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700708 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
709
710private:
711 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700712 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700713 Func->deallocateArrayOf<uint64_t>(Values);
714 Func->deallocateArrayOf<CfgNode *>(Labels);
715 Inst::destroy(Func);
716 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700717 ~InstSwitch() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700718
719 CfgNode *LabelDefault;
720 SizeT NumCases; // not including the default case
721 uint64_t *Values; // size is NumCases
722 CfgNode **Labels; // size is NumCases
723};
724
725// Unreachable instruction. This is a terminator instruction with no
726// operands.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700727class InstUnreachable : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700728 InstUnreachable(const InstUnreachable &) = delete;
729 InstUnreachable &operator=(const InstUnreachable &) = delete;
730
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700731public:
732 static InstUnreachable *create(Cfg *Func) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800733 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700734 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700735 NodeList getTerminatorEdges() const override { return NodeList(); }
736 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700737 static bool classof(const Inst *Inst) {
738 return Inst->getKind() == Unreachable;
739 }
740
741private:
742 InstUnreachable(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700743 ~InstUnreachable() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700744};
745
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700746// FakeDef instruction. This creates a fake definition of a variable,
747// which is how we represent the case when an instruction produces
748// multiple results. This doesn't happen with high-level ICE
749// instructions, but might with lowered instructions. For example,
750// this would be a way to represent condition flags being modified by
751// an instruction.
752//
753// It's generally useful to set the optional source operand to be the
754// dest variable of the instruction that actually produces the FakeDef
755// dest. Otherwise, the original instruction could be dead-code
756// eliminated if its dest operand is unused, and therefore the FakeDef
757// dest wouldn't be properly initialized.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700758class InstFakeDef : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700759 InstFakeDef(const InstFakeDef &) = delete;
760 InstFakeDef &operator=(const InstFakeDef &) = delete;
761
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700762public:
Jim Stichnothae953202014-12-20 06:17:49 -0800763 static InstFakeDef *create(Cfg *Func, Variable *Dest,
764 Variable *Src = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800765 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700766 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700767 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700768 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700769 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700770 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
771
772private:
773 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700774 ~InstFakeDef() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700775};
776
777// FakeUse instruction. This creates a fake use of a variable, to
778// keep the instruction that produces that variable from being
779// dead-code eliminated. This is useful in a variety of lowering
780// situations. The FakeUse instruction has no dest, so it can itself
781// never be dead-code eliminated.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700782class InstFakeUse : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700783 InstFakeUse(const InstFakeUse &) = delete;
784 InstFakeUse &operator=(const InstFakeUse &) = delete;
785
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700786public:
787 static InstFakeUse *create(Cfg *Func, Variable *Src) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800788 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700789 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700790 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700791 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700792 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700793 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
794
795private:
796 InstFakeUse(Cfg *Func, Variable *Src);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700797 ~InstFakeUse() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700798};
799
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800800// FakeKill instruction. This "kills" a set of variables by modeling
801// a trivial live range at this instruction for each (implicit)
802// variable. The primary use is to indicate that scratch registers
803// are killed after a call, so that the register allocator won't
804// assign a scratch register to a variable whose live range spans a
805// call.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700806//
807// The FakeKill instruction also holds a pointer to the instruction
808// that kills the set of variables, so that if that linked instruction
809// gets dead-code eliminated, the FakeKill instruction will as well.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700810class InstFakeKill : public InstHighLevel {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700811 InstFakeKill(const InstFakeKill &) = delete;
812 InstFakeKill &operator=(const InstFakeKill &) = delete;
813
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700814public:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800815 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800816 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700817 }
818 const Inst *getLinked() const { return Linked; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700819 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700820 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700821 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700822 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
823
824private:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800825 InstFakeKill(Cfg *Func, const Inst *Linked);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700826 ~InstFakeKill() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700827
828 // This instruction is ignored if Linked->isDeleted() is true.
829 const Inst *Linked;
830};
831
832// The Target instruction is the base class for all target-specific
833// instructions.
834class InstTarget : public Inst {
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700835 InstTarget(const InstTarget &) = delete;
836 InstTarget &operator=(const InstTarget &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700837
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700838public:
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700839 uint32_t getEmitInstCount() const override { return 1; }
840 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700841 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
842
843protected:
844 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
845 : Inst(Func, Kind, MaxSrcs, Dest) {
846 assert(Kind >= Target);
847 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700848 ~InstTarget() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700849};
850
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700851} // end of namespace Ice
852
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800853namespace llvm {
854
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800855// Override the default ilist traits so that Inst's private ctor and
856// deleted dtor aren't invoked.
857template <>
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800858struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800859 Ice::Inst *createSentinel() const {
860 return static_cast<Ice::Inst *>(&Sentinel);
861 }
862 static void destroySentinel(Ice::Inst *) {}
863 Ice::Inst *provideInitialHead() const { return createSentinel(); }
864 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
865 static void noteHead(Ice::Inst *, Ice::Inst *) {}
866 void deleteNode(Ice::Inst *) {}
867
868private:
869 mutable ilist_half_node<Ice::Inst> Sentinel;
870};
871
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800872} // end of namespace llvm
873
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700874#endif // SUBZERO_SRC_ICEINST_H