blob: cfa6dd3a48a0ba26d10ec5f87c7d5ef1f487a634 [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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file declares the Inst class and its target-independent
12/// subclasses, which represent the high-level Vanilla ICE instructions
13/// and map roughly 1:1 to LLVM instructions.
14///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070015//===----------------------------------------------------------------------===//
16
17#ifndef SUBZERO_SRC_ICEINST_H
18#define SUBZERO_SRC_ICEINST_H
19
John Porto7e93c622015-06-23 10:58:57 -070020#include "IceCfg.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070021#include "IceDefs.h"
22#include "IceInst.def"
Jan Voung3bd9f1a2014-06-18 10:50:57 -070023#include "IceIntrinsics.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024#include "IceTypes.h"
25
26// TODO: The Cfg structure, and instructions in particular, need to be
27// validated for things like valid operand types, valid branch
28// targets, proper ordering of Phi and non-Phi instructions, etc.
29// Most of the validity checking will be done in the bitcode reader.
30// We need a list of everything that should be validated, and tests
31// for each.
32
33namespace Ice {
34
Andrew Scull9612d322015-07-06 14:53:25 -070035/// Base instruction class for ICE. Inst has two subclasses:
36/// InstHighLevel and InstTarget. High-level ICE instructions inherit
37/// from InstHighLevel, and low-level (target-specific) ICE
38/// instructions inherit from InstTarget.
Jim Stichnoth607e9f02014-11-06 13:32:05 -080039class Inst : public llvm::ilist_node<Inst> {
Jim Stichnothc6ead202015-02-24 09:30:30 -080040 Inst() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070041 Inst(const Inst &) = delete;
42 Inst &operator=(const Inst &) = delete;
43
Jim Stichnothf7c9a142014-04-29 10:52:43 -070044public:
45 enum InstKind {
46 // Arbitrary (alphabetical) order, except put Unreachable first.
47 Unreachable,
48 Alloca,
49 Arithmetic,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070050 Br,
51 Call,
52 Cast,
Matt Wala49889232014-07-18 12:45:09 -070053 ExtractElement,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070054 Fcmp,
55 Icmp,
Jan Voung3bd9f1a2014-06-18 10:50:57 -070056 IntrinsicCall,
Matt Wala49889232014-07-18 12:45:09 -070057 InsertElement,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058 Load,
59 Phi,
60 Ret,
61 Select,
62 Store,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070063 Switch,
Jim Stichnothc6ead202015-02-24 09:30:30 -080064 Assign, // not part of LLVM/PNaCl bitcode
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -080065 BundleLock, // not part of LLVM/PNaCl bitcode
66 BundleUnlock, // not part of LLVM/PNaCl bitcode
67 FakeDef, // not part of LLVM/PNaCl bitcode
68 FakeUse, // not part of LLVM/PNaCl bitcode
69 FakeKill, // not part of LLVM/PNaCl bitcode
70 Target // target-specific low-level ICE
71 // Anything >= Target is an InstTarget subclass.
Jan Voungb3401d22015-05-18 09:38:21 -070072 // Note that the value-spaces are shared across targets.
73 // To avoid confusion over the definition of shared values,
74 // an object specific to one target should never be passed
75 // to a different target.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070076 };
77 InstKind getKind() const { return Kind; }
78
Jim Stichnothd97c7df2014-06-04 11:57:08 -070079 InstNumberT getNumber() const { return Number; }
80 void renumber(Cfg *Func);
Jim Stichnothe5b73e62014-12-15 09:58:51 -080081 enum {
82 NumberDeleted = -1,
83 NumberSentinel = 0,
84 NumberInitial = 2,
85 NumberExtended = NumberInitial - 1
86 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -070087
88 bool isDeleted() const { return Deleted; }
89 void setDeleted() { Deleted = true; }
Jim Stichnotha59ae6f2015-05-17 10:11:41 -070090 void setDead(bool Value = true) { Dead = Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070091 void deleteIfDead();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070092
93 bool hasSideEffects() const { return HasSideEffects; }
94
Jim Stichnoth47752552014-10-13 17:15:08 -070095 bool isDestNonKillable() const { return IsDestNonKillable; }
96 void setDestNonKillable() { IsDestNonKillable = true; }
97
Jim Stichnothf7c9a142014-04-29 10:52:43 -070098 Variable *getDest() const { return Dest; }
99
100 SizeT getSrcSize() const { return NumSrcs; }
101 Operand *getSrc(SizeT I) const {
102 assert(I < getSrcSize());
103 return Srcs[I];
104 }
105
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700106 bool isLastUse(const Operand *Src) const;
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700107 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700108
Andrew Scull9612d322015-07-06 14:53:25 -0700109 /// Returns a list of out-edges corresponding to a terminator
110 /// instruction, which is the last instruction of the block.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700111 virtual NodeList getTerminatorEdges() const {
112 // All valid terminator instructions override this method. For
113 // the default implementation, we assert in case some CfgNode
114 // is constructed without a terminator instruction at the end.
115 llvm_unreachable(
116 "getTerminatorEdges() called on a non-terminator instruction");
117 return NodeList();
118 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700119 virtual bool isUnconditionalBranch() const { return false; }
Andrew Scull9612d322015-07-06 14:53:25 -0700120 /// If the instruction is a branch-type instruction with OldNode as a
121 /// target, repoint it to NewNode and return true, otherwise return
122 /// false. Only repoint one instance, even if the instruction has
123 /// multiple instances of OldNode as a target.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700124 virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
125 (void)OldNode;
126 (void)NewNode;
127 return false;
128 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700129
Jim Stichnothad403532014-09-25 12:44:17 -0700130 virtual bool isSimpleAssign() const { return false; }
131
Jim Stichnoth47752552014-10-13 17:15:08 -0700132 void livenessLightweight(Cfg *Func, LivenessBV &Live);
Andrew Scull9612d322015-07-06 14:53:25 -0700133 /// Calculates liveness for this instruction. Returns true if this
134 /// instruction is (tentatively) still live and should be retained,
135 /// and false if this instruction is (tentatively) dead and should be
136 /// deleted. The decision is tentative until the liveness dataflow
137 /// algorithm has converged, and then a separate pass permanently
138 /// deletes dead instructions.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700139 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
Jim Stichnoth47752552014-10-13 17:15:08 -0700140 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
Jim Stichnoth18735602014-09-16 19:59:35 -0700141
Andrew Scull9612d322015-07-06 14:53:25 -0700142 /// Get the number of native instructions that this instruction
143 /// ultimately emits. By default, high-level instructions don't
144 /// result in any native instructions, and a target-specific
145 /// instruction results in a single native instruction.
Jim Stichnoth18735602014-09-16 19:59:35 -0700146 virtual uint32_t getEmitInstCount() const { return 0; }
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800147 // TODO(stichnot): Change Inst back to abstract once the g++ build
148 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++
149 // because the resize(size_t, Ice::Inst) method is incorrectly
150 // declared and thus doesn't allow the abstract class Ice::Inst.
151 // The method should be declared resize(size_t, const Ice::Inst &).
152 // virtual void emit(const Cfg *Func) const = 0;
153 // virtual void emitIAS(const Cfg *Func) const = 0;
154 virtual void emit(const Cfg *) const {
155 llvm_unreachable("emit on abstract class");
156 }
157 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700158 virtual void dump(const Cfg *Func) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700159 virtual void dumpExtras(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700160 void dumpDecorated(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700161 void emitSources(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700162 void dumpSources(const Cfg *Func) const;
163 void dumpDest(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700164 virtual bool isRedundantAssign() const { return false; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700165
John Porto1bec8bc2015-06-22 10:51:13 -0700166 // TODO(jpp): Insts should not have non-trivial destructors, but they
167 // currently do. This dtor is marked final as a multi-step refactor that
168 // will eventually fix this problem.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700169 virtual ~Inst() = default;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700170
171protected:
172 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
173 void addSource(Operand *Src) {
174 assert(Src);
175 assert(NumSrcs < MaxSrcs);
176 Srcs[NumSrcs++] = Src;
177 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700178 void setLastUse(SizeT VarIndex) {
179 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
180 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
181 }
182 void resetLastUses() { LiveRangesEnded = 0; }
Andrew Scull9612d322015-07-06 14:53:25 -0700183 /// The destroy() method lets the instruction cleanly release any
184 /// memory that was allocated via the Cfg's allocator.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700185 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
186
187 const InstKind Kind;
Andrew Scull9612d322015-07-06 14:53:25 -0700188 /// Number is the instruction number for describing live ranges.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700189 InstNumberT Number;
Andrew Scull9612d322015-07-06 14:53:25 -0700190 /// Deleted means irrevocably deleted.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700191 bool Deleted = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700192 /// Dead means one of two things depending on context: (1) pending
193 /// deletion after liveness analysis converges, or (2) marked for
194 /// deletion during lowering due to a folded bool operation.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700195 bool Dead = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700196 /// HasSideEffects means the instruction is something like a function
197 /// call or a volatile load that can't be removed even if its Dest
198 /// variable is not live.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700199 bool HasSideEffects = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700200 /// IsDestNonKillable means that liveness analysis shouldn't consider
201 /// this instruction to kill the Dest variable. This is used when
202 /// lowering produces two assignments to the same variable.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700203 bool IsDestNonKillable = false;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700204
205 Variable *Dest;
206 const SizeT MaxSrcs; // only used for assert
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700207 SizeT NumSrcs = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700208 Operand **Srcs;
209
Andrew Scull9612d322015-07-06 14:53:25 -0700210 /// LiveRangesEnded marks which Variables' live ranges end in this
211 /// instruction. An instruction can have an arbitrary number of
212 /// source operands (e.g. a call instruction), and each source
213 /// operand can contain 0 or 1 Variable (and target-specific operands
214 /// could contain more than 1 Variable). All the variables in an
215 /// instruction are conceptually flattened and each variable is
216 /// mapped to one bit position of the LiveRangesEnded bit vector.
217 /// Only the first CHAR_BIT * sizeof(LREndedBits) variables are
218 /// tracked this way.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700219 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
220 LREndedBits LiveRangesEnded;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700221};
222
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700223class InstHighLevel : public Inst {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800224 InstHighLevel() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700225 InstHighLevel(const InstHighLevel &) = delete;
226 InstHighLevel &operator=(const InstHighLevel &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700227
228protected:
229 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
230 : Inst(Func, Kind, MaxSrcs, Dest) {}
231 void emit(const Cfg * /*Func*/) const override {
232 llvm_unreachable("emit() called on a non-lowered instruction");
233 }
234 void emitIAS(const Cfg * /*Func*/) const override {
235 llvm_unreachable("emitIAS() called on a non-lowered instruction");
236 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700237};
238
Andrew Scull9612d322015-07-06 14:53:25 -0700239/// Alloca instruction. This captures the size in bytes as getSrc(0),
240/// and the required alignment in bytes. The alignment must be either
241/// 0 (no alignment required) or a power of 2.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700242class InstAlloca : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800243 InstAlloca() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700244 InstAlloca(const InstAlloca &) = delete;
245 InstAlloca &operator=(const InstAlloca &) = delete;
246
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700247public:
248 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
249 uint32_t AlignInBytes, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800250 return new (Func->allocate<InstAlloca>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700251 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
252 }
253 uint32_t getAlignInBytes() const { return AlignInBytes; }
254 Operand *getSizeInBytes() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700255 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700256 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
257
258private:
259 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
260 Variable *Dest);
John Porto1bec8bc2015-06-22 10:51:13 -0700261
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700262 const uint32_t AlignInBytes;
263};
264
Andrew Scull9612d322015-07-06 14:53:25 -0700265/// Binary arithmetic instruction. The source operands are captured in
266/// getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700267class InstArithmetic : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800268 InstArithmetic() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700269 InstArithmetic(const InstArithmetic &) = delete;
270 InstArithmetic &operator=(const InstArithmetic &) = delete;
271
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700272public:
273 enum OpKind {
274#define X(tag, str, commutative) tag,
275 ICEINSTARITHMETIC_TABLE
276#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700277 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700278 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700279
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700280 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
281 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800282 return new (Func->allocate<InstArithmetic>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700283 InstArithmetic(Func, Op, Dest, Source1, Source2);
284 }
285 OpKind getOp() const { return Op; }
Karl Schimpfd6064a12014-08-27 15:34:58 -0700286 static const char *getOpName(OpKind Op);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700287 bool isCommutative() const;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700288 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700289 static bool classof(const Inst *Inst) {
290 return Inst->getKind() == Arithmetic;
291 }
292
293private:
294 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
295 Operand *Source2);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700296
297 const OpKind Op;
298};
299
Andrew Scull9612d322015-07-06 14:53:25 -0700300/// Assignment instruction. The source operand is captured in
301/// getSrc(0). This is not part of the LLVM bitcode, but is a useful
302/// abstraction for some of the lowering. E.g., if Phi instruction
303/// lowering happens before target lowering, or for representing an
304/// Inttoptr instruction, or as an intermediate step for lowering a
305/// Load instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700306class InstAssign : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800307 InstAssign() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700308 InstAssign(const InstAssign &) = delete;
309 InstAssign &operator=(const InstAssign &) = delete;
310
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700311public:
312 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800313 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700314 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700315 bool isSimpleAssign() const override { return true; }
316 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700317 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
318
319private:
320 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700321};
322
Andrew Scull9612d322015-07-06 14:53:25 -0700323/// Branch instruction. This represents both conditional and
324/// unconditional branches.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700325class InstBr : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800326 InstBr() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700327 InstBr(const InstBr &) = delete;
328 InstBr &operator=(const InstBr &) = delete;
329
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700330public:
Andrew Scull9612d322015-07-06 14:53:25 -0700331 /// Create a conditional branch. If TargetTrue==TargetFalse, it is
332 /// optimized to an unconditional branch.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700333 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
334 CfgNode *TargetFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800335 return new (Func->allocate<InstBr>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700336 InstBr(Func, Source, TargetTrue, TargetFalse);
337 }
Andrew Scull9612d322015-07-06 14:53:25 -0700338 /// Create an unconditional branch.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700339 static InstBr *create(Cfg *Func, CfgNode *Target) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800340 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700341 }
Jim Stichnothae953202014-12-20 06:17:49 -0800342 bool isUnconditional() const { return getTargetTrue() == nullptr; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700343 Operand *getCondition() const {
344 assert(!isUnconditional());
345 return getSrc(0);
346 }
347 CfgNode *getTargetTrue() const { return TargetTrue; }
348 CfgNode *getTargetFalse() const { return TargetFalse; }
349 CfgNode *getTargetUnconditional() const {
350 assert(isUnconditional());
351 return getTargetFalse();
352 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700353 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700354 bool isUnconditionalBranch() const override { return isUnconditional(); }
355 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700356 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700357 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
358
359private:
Andrew Scull9612d322015-07-06 14:53:25 -0700360 /// Conditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700361 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
Andrew Scull9612d322015-07-06 14:53:25 -0700362 /// Unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700363 InstBr(Cfg *Func, CfgNode *Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700364
Andrew Scull9612d322015-07-06 14:53:25 -0700365 CfgNode *TargetFalse; /// Doubles as unconditional branch target
366 CfgNode *TargetTrue; /// nullptr if unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700367};
368
Andrew Scull9612d322015-07-06 14:53:25 -0700369/// Call instruction. The call target is captured as getSrc(0), and
370/// arg I is captured as getSrc(I+1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700371class InstCall : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800372 InstCall() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700373 InstCall(const InstCall &) = delete;
374 InstCall &operator=(const InstCall &) = delete;
375
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700376public:
377 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700378 Operand *CallTarget, bool HasTailCall) {
Andrew Scull9612d322015-07-06 14:53:25 -0700379 /// Set HasSideEffects to true so that the call instruction can't be
380 /// dead-code eliminated. IntrinsicCalls can override this if the
381 /// particular intrinsic is deletable and has no side-effects.
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700382 const bool HasSideEffects = true;
383 const InstKind Kind = Inst::Call;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800384 return new (Func->allocate<InstCall>()) InstCall(
Karl Schimpf8df26f32014-09-19 09:33:26 -0700385 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700386 }
387 void addArg(Operand *Arg) { addSource(Arg); }
388 Operand *getCallTarget() const { return getSrc(0); }
389 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
390 SizeT getNumArgs() const { return getSrcSize() - 1; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700391 bool isTailcall() const { return HasTailCall; }
Jan Voung3ce1a992015-02-03 08:27:44 -0800392 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700393 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700394 Type getReturnType() const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700395
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700396protected:
397 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700398 bool HasTailCall, bool HasSideEff, InstKind Kind)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700399 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700400 HasSideEffects = HasSideEff;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700401 addSource(CallTarget);
402 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700403
404private:
Karl Schimpf8df26f32014-09-19 09:33:26 -0700405 bool HasTailCall;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700406};
407
Andrew Scull9612d322015-07-06 14:53:25 -0700408/// Cast instruction (a.k.a. conversion operation).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700409class InstCast : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800410 InstCast() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700411 InstCast(const InstCast &) = delete;
412 InstCast &operator=(const InstCast &) = delete;
413
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700414public:
415 enum OpKind {
416#define X(tag, str) tag,
417 ICEINSTCAST_TABLE
418#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700419 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700420 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700421
Karl Schimpfbf170372014-12-15 10:16:31 -0800422 static const char *getCastName(OpKind Kind);
423
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700424 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
425 Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800426 return new (Func->allocate<InstCast>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700427 InstCast(Func, CastKind, Dest, Source);
428 }
429 OpKind getCastKind() const { return CastKind; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700430 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700431 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
432
433private:
434 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
John Porto1bec8bc2015-06-22 10:51:13 -0700435
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700436 const OpKind CastKind;
437};
438
Andrew Scull9612d322015-07-06 14:53:25 -0700439/// ExtractElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700440class InstExtractElement : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800441 InstExtractElement() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700442 InstExtractElement(const InstExtractElement &) = delete;
443 InstExtractElement &operator=(const InstExtractElement &) = delete;
444
Matt Wala49889232014-07-18 12:45:09 -0700445public:
446 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
447 Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800448 return new (Func->allocate<InstExtractElement>())
Matt Wala49889232014-07-18 12:45:09 -0700449 InstExtractElement(Func, Dest, Source1, Source2);
450 }
451
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700452 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700453 static bool classof(const Inst *Inst) {
454 return Inst->getKind() == ExtractElement;
455 }
456
457private:
458 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
459 Operand *Source2);
Matt Wala49889232014-07-18 12:45:09 -0700460};
461
Andrew Scull9612d322015-07-06 14:53:25 -0700462/// Floating-point comparison instruction. The source operands are
463/// captured in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700464class InstFcmp : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800465 InstFcmp() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700466 InstFcmp(const InstFcmp &) = delete;
467 InstFcmp &operator=(const InstFcmp &) = delete;
468
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700469public:
470 enum FCond {
471#define X(tag, str) tag,
472 ICEINSTFCMP_TABLE
473#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700474 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700475 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700476
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700477 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
478 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800479 return new (Func->allocate<InstFcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700480 InstFcmp(Func, Condition, Dest, Source1, Source2);
481 }
482 FCond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700483 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700484 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
485
486private:
487 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
488 Operand *Source2);
John Porto1bec8bc2015-06-22 10:51:13 -0700489
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700490 const FCond Condition;
491};
492
Andrew Scull9612d322015-07-06 14:53:25 -0700493/// Integer comparison instruction. The source operands are captured
494/// in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700495class InstIcmp : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800496 InstIcmp() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700497 InstIcmp(const InstIcmp &) = delete;
498 InstIcmp &operator=(const InstIcmp &) = delete;
499
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700500public:
501 enum ICond {
502#define X(tag, str) tag,
503 ICEINSTICMP_TABLE
504#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700505 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700506 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700507
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700508 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
509 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800510 return new (Func->allocate<InstIcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700511 InstIcmp(Func, Condition, Dest, Source1, Source2);
512 }
513 ICond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700514 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700515 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
516
517private:
518 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
519 Operand *Source2);
John Porto1bec8bc2015-06-22 10:51:13 -0700520
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700521 const ICond Condition;
522};
523
Andrew Scull9612d322015-07-06 14:53:25 -0700524/// InsertElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700525class InstInsertElement : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800526 InstInsertElement() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700527 InstInsertElement(const InstInsertElement &) = delete;
528 InstInsertElement &operator=(const InstInsertElement &) = delete;
529
Matt Wala49889232014-07-18 12:45:09 -0700530public:
531 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
532 Operand *Source2, Operand *Source3) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800533 return new (Func->allocate<InstInsertElement>())
Matt Wala49889232014-07-18 12:45:09 -0700534 InstInsertElement(Func, Dest, Source1, Source2, Source3);
535 }
536
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700537 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700538 static bool classof(const Inst *Inst) {
539 return Inst->getKind() == InsertElement;
540 }
541
542private:
543 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
544 Operand *Source2, Operand *Source3);
Matt Wala49889232014-07-18 12:45:09 -0700545};
546
Andrew Scull9612d322015-07-06 14:53:25 -0700547/// Call to an intrinsic function. The call target is captured as getSrc(0),
548/// and arg I is captured as getSrc(I+1).
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700549class InstIntrinsicCall : public InstCall {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800550 InstIntrinsicCall() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700551 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
552 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
553
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700554public:
555 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
556 Operand *CallTarget,
557 const Intrinsics::IntrinsicInfo &Info) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800558 return new (Func->allocate<InstIntrinsicCall>())
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700559 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
560 }
561 static bool classof(const Inst *Inst) {
562 return Inst->getKind() == IntrinsicCall;
563 }
564
565 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
566
567private:
568 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
569 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
Karl Schimpf8df26f32014-09-19 09:33:26 -0700570 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700571 Inst::IntrinsicCall),
572 Info(Info) {}
John Porto1bec8bc2015-06-22 10:51:13 -0700573
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700574 const Intrinsics::IntrinsicInfo Info;
575};
576
Andrew Scull9612d322015-07-06 14:53:25 -0700577/// Load instruction. The source address is captured in getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700578class InstLoad : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800579 InstLoad() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700580 InstLoad(const InstLoad &) = delete;
581 InstLoad &operator=(const InstLoad &) = delete;
582
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700583public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700584 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
Jim Stichnothc4554d72014-09-30 16:49:38 -0700585 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700586 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700587 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800588 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700589 }
590 Operand *getSourceAddress() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700591 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700592 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
593
594private:
595 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700596};
597
Andrew Scull9612d322015-07-06 14:53:25 -0700598/// Phi instruction. For incoming edge I, the node is Labels[I] and
599/// the Phi source operand is getSrc(I).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700600class InstPhi : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800601 InstPhi() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700602 InstPhi(const InstPhi &) = delete;
603 InstPhi &operator=(const InstPhi &) = delete;
604
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700605public:
606 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800607 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700608 }
609 void addArgument(Operand *Source, CfgNode *Label);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700610 Operand *getOperandForTarget(CfgNode *Target) const;
Jim Stichnoth98712a32014-10-24 10:59:02 -0700611 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700612 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700613 Liveness *Liveness);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700614 Inst *lower(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700615 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700616 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
617
618private:
619 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700620 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700621 Func->deallocateArrayOf<CfgNode *>(Labels);
622 Inst::destroy(Func);
623 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700624
Andrew Scull9612d322015-07-06 14:53:25 -0700625 /// Labels[] duplicates the InEdges[] information in the enclosing
626 /// CfgNode, but the Phi instruction is created before InEdges[]
627 /// is available, so it's more complicated to share the list.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700628 CfgNode **Labels;
629};
630
Andrew Scull9612d322015-07-06 14:53:25 -0700631/// Ret instruction. The return value is captured in getSrc(0), but if
632/// there is no return value (void-type function), then
633/// getSrcSize()==0 and hasRetValue()==false.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700634class InstRet : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800635 InstRet() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700636 InstRet(const InstRet &) = delete;
637 InstRet &operator=(const InstRet &) = delete;
638
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700639public:
Jim Stichnothae953202014-12-20 06:17:49 -0800640 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800641 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700642 }
643 bool hasRetValue() const { return getSrcSize(); }
644 Operand *getRetValue() const {
645 assert(hasRetValue());
646 return getSrc(0);
647 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700648 NodeList getTerminatorEdges() const override { return NodeList(); }
649 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700650 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
651
652private:
653 InstRet(Cfg *Func, Operand *RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700654};
655
Andrew Scull9612d322015-07-06 14:53:25 -0700656/// Select instruction. The condition, true, and false operands are captured.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700657class InstSelect : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800658 InstSelect() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700659 InstSelect(const InstSelect &) = delete;
660 InstSelect &operator=(const InstSelect &) = delete;
661
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700662public:
663 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
664 Operand *SourceTrue, Operand *SourceFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800665 return new (Func->allocate<InstSelect>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700666 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
667 }
668 Operand *getCondition() const { return getSrc(0); }
669 Operand *getTrueOperand() const { return getSrc(1); }
670 Operand *getFalseOperand() const { return getSrc(2); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700671 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700672 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
673
674private:
675 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
676 Operand *Source2);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700677};
678
Andrew Scull9612d322015-07-06 14:53:25 -0700679/// Store instruction. The address operand is captured, along with the
680/// data operand to be stored into the address.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700681class InstStore : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800682 InstStore() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700683 InstStore(const InstStore &) = delete;
684 InstStore &operator=(const InstStore &) = delete;
685
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700686public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700687 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700688 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700689 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700690 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800691 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700692 }
693 Operand *getAddr() const { return getSrc(1); }
694 Operand *getData() const { return getSrc(0); }
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700695 Variable *getRmwBeacon() const { return llvm::dyn_cast<Variable>(getSrc(2)); }
696 void setRmwBeacon(Variable *Beacon);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700697 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700698 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
699
700private:
701 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700702};
703
Andrew Scull9612d322015-07-06 14:53:25 -0700704/// Switch instruction. The single source operand is captured as
705/// getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700706class InstSwitch : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800707 InstSwitch() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700708 InstSwitch(const InstSwitch &) = delete;
709 InstSwitch &operator=(const InstSwitch &) = delete;
710
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700711public:
712 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
713 CfgNode *LabelDefault) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800714 return new (Func->allocate<InstSwitch>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700715 InstSwitch(Func, NumCases, Source, LabelDefault);
716 }
717 Operand *getComparison() const { return getSrc(0); }
718 CfgNode *getLabelDefault() const { return LabelDefault; }
719 SizeT getNumCases() const { return NumCases; }
720 uint64_t getValue(SizeT I) const {
721 assert(I < NumCases);
722 return Values[I];
723 }
724 CfgNode *getLabel(SizeT I) const {
725 assert(I < NumCases);
726 return Labels[I];
727 }
728 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700729 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700730 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700731 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700732 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
733
734private:
735 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700736 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700737 Func->deallocateArrayOf<uint64_t>(Values);
738 Func->deallocateArrayOf<CfgNode *>(Labels);
739 Inst::destroy(Func);
740 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700741
742 CfgNode *LabelDefault;
Andrew Scull9612d322015-07-06 14:53:25 -0700743 SizeT NumCases; /// not including the default case
744 uint64_t *Values; /// size is NumCases
745 CfgNode **Labels; /// size is NumCases
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700746};
747
Andrew Scull9612d322015-07-06 14:53:25 -0700748/// Unreachable instruction. This is a terminator instruction with no
749/// operands.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700750class InstUnreachable : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800751 InstUnreachable() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700752 InstUnreachable(const InstUnreachable &) = delete;
753 InstUnreachable &operator=(const InstUnreachable &) = delete;
754
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700755public:
756 static InstUnreachable *create(Cfg *Func) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800757 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700758 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700759 NodeList getTerminatorEdges() const override { return NodeList(); }
760 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700761 static bool classof(const Inst *Inst) {
762 return Inst->getKind() == Unreachable;
763 }
764
765private:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800766 explicit InstUnreachable(Cfg *Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700767};
768
Andrew Scull9612d322015-07-06 14:53:25 -0700769/// BundleLock instruction. There are no operands. Contains an option
770/// indicating whether align_to_end is specified.
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800771class InstBundleLock : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800772 InstBundleLock() = delete;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800773 InstBundleLock(const InstBundleLock &) = delete;
774 InstBundleLock &operator=(const InstBundleLock &) = delete;
775
776public:
777 enum Option { Opt_None, Opt_AlignToEnd };
778 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
779 return new (Func->allocate<InstBundleLock>())
780 InstBundleLock(Func, BundleOption);
781 }
782 void emit(const Cfg *Func) const override;
783 void emitIAS(const Cfg * /* Func */) const override {}
784 void dump(const Cfg *Func) const override;
785 Option getOption() const { return BundleOption; }
786 static bool classof(const Inst *Inst) {
787 return Inst->getKind() == BundleLock;
788 }
789
790private:
791 Option BundleOption;
792 InstBundleLock(Cfg *Func, Option BundleOption);
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800793};
794
Andrew Scull9612d322015-07-06 14:53:25 -0700795/// BundleUnlock instruction. There are no operands.
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800796class InstBundleUnlock : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800797 InstBundleUnlock() = delete;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800798 InstBundleUnlock(const InstBundleUnlock &) = delete;
799 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
800
801public:
802 static InstBundleUnlock *create(Cfg *Func) {
803 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
804 }
805 void emit(const Cfg *Func) const override;
806 void emitIAS(const Cfg * /* Func */) const override {}
807 void dump(const Cfg *Func) const override;
808 static bool classof(const Inst *Inst) {
809 return Inst->getKind() == BundleUnlock;
810 }
811
812private:
813 explicit InstBundleUnlock(Cfg *Func);
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800814};
815
Andrew Scull9612d322015-07-06 14:53:25 -0700816/// FakeDef instruction. This creates a fake definition of a variable,
817/// which is how we represent the case when an instruction produces
818/// multiple results. This doesn't happen with high-level ICE
819/// instructions, but might with lowered instructions. For example,
820/// this would be a way to represent condition flags being modified by
821/// an instruction.
822///
823/// It's generally useful to set the optional source operand to be the
824/// dest variable of the instruction that actually produces the FakeDef
825/// dest. Otherwise, the original instruction could be dead-code
826/// eliminated if its dest operand is unused, and therefore the FakeDef
827/// dest wouldn't be properly initialized.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700828class InstFakeDef : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800829 InstFakeDef() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700830 InstFakeDef(const InstFakeDef &) = delete;
831 InstFakeDef &operator=(const InstFakeDef &) = delete;
832
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700833public:
Jim Stichnothae953202014-12-20 06:17:49 -0800834 static InstFakeDef *create(Cfg *Func, Variable *Dest,
835 Variable *Src = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800836 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700837 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700838 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700839 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700840 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700841 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
842
843private:
844 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700845};
846
Andrew Scull9612d322015-07-06 14:53:25 -0700847/// FakeUse instruction. This creates a fake use of a variable, to
848/// keep the instruction that produces that variable from being
849/// dead-code eliminated. This is useful in a variety of lowering
850/// situations. The FakeUse instruction has no dest, so it can itself
851/// never be dead-code eliminated.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700852class InstFakeUse : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800853 InstFakeUse() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700854 InstFakeUse(const InstFakeUse &) = delete;
855 InstFakeUse &operator=(const InstFakeUse &) = delete;
856
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700857public:
858 static InstFakeUse *create(Cfg *Func, Variable *Src) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800859 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700860 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700861 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700862 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700863 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700864 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
865
866private:
867 InstFakeUse(Cfg *Func, Variable *Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700868};
869
Andrew Scull9612d322015-07-06 14:53:25 -0700870/// FakeKill instruction. This "kills" a set of variables by modeling
871/// a trivial live range at this instruction for each (implicit)
872/// variable. The primary use is to indicate that scratch registers
873/// are killed after a call, so that the register allocator won't
874/// assign a scratch register to a variable whose live range spans a
875/// call.
876///
877/// The FakeKill instruction also holds a pointer to the instruction
878/// that kills the set of variables, so that if that linked instruction
879/// gets dead-code eliminated, the FakeKill instruction will as well.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700880class InstFakeKill : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800881 InstFakeKill() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700882 InstFakeKill(const InstFakeKill &) = delete;
883 InstFakeKill &operator=(const InstFakeKill &) = delete;
884
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700885public:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800886 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800887 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700888 }
889 const Inst *getLinked() const { return Linked; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700890 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700891 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700892 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700893 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
894
895private:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800896 InstFakeKill(Cfg *Func, const Inst *Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700897
Andrew Scull9612d322015-07-06 14:53:25 -0700898 /// This instruction is ignored if Linked->isDeleted() is true.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700899 const Inst *Linked;
900};
901
Andrew Scull9612d322015-07-06 14:53:25 -0700902/// The Target instruction is the base class for all target-specific
903/// instructions.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700904class InstTarget : public Inst {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800905 InstTarget() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700906 InstTarget(const InstTarget &) = delete;
907 InstTarget &operator=(const InstTarget &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700908
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700909public:
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700910 uint32_t getEmitInstCount() const override { return 1; }
911 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700912 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
913
914protected:
915 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
916 : Inst(Func, Kind, MaxSrcs, Dest) {
917 assert(Kind >= Target);
918 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700919};
920
Jan Voungb3401d22015-05-18 09:38:21 -0700921bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
922
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700923} // end of namespace Ice
924
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800925namespace llvm {
926
Andrew Scull9612d322015-07-06 14:53:25 -0700927/// Override the default ilist traits so that Inst's private ctor and
928/// deleted dtor aren't invoked.
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800929template <>
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800930struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800931 Ice::Inst *createSentinel() const {
932 return static_cast<Ice::Inst *>(&Sentinel);
933 }
934 static void destroySentinel(Ice::Inst *) {}
935 Ice::Inst *provideInitialHead() const { return createSentinel(); }
936 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
937 static void noteHead(Ice::Inst *, Ice::Inst *) {}
938 void deleteNode(Ice::Inst *) {}
939
940private:
941 mutable ilist_half_node<Ice::Inst> Sentinel;
942};
943
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800944} // end of namespace llvm
945
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700946#endif // SUBZERO_SRC_ICEINST_H