blob: 360135a133b144c05cfe4013e8ff110cef550192 [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
Andrew Scull87f80c12015-07-20 10:19:16 -070070 JumpTable, // not part of LLVM/PNaCl bitcode
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -080071 Target // target-specific low-level ICE
72 // Anything >= Target is an InstTarget subclass.
Jan Voungb3401d22015-05-18 09:38:21 -070073 // Note that the value-spaces are shared across targets.
74 // To avoid confusion over the definition of shared values,
75 // an object specific to one target should never be passed
76 // to a different target.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070077 };
78 InstKind getKind() const { return Kind; }
79
Jim Stichnothd97c7df2014-06-04 11:57:08 -070080 InstNumberT getNumber() const { return Number; }
81 void renumber(Cfg *Func);
Jim Stichnothe5b73e62014-12-15 09:58:51 -080082 enum {
83 NumberDeleted = -1,
84 NumberSentinel = 0,
85 NumberInitial = 2,
86 NumberExtended = NumberInitial - 1
87 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -070088
89 bool isDeleted() const { return Deleted; }
90 void setDeleted() { Deleted = true; }
Jim Stichnotha59ae6f2015-05-17 10:11:41 -070091 void setDead(bool Value = true) { Dead = Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070092 void deleteIfDead();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070093
94 bool hasSideEffects() const { return HasSideEffects; }
95
Jim Stichnoth47752552014-10-13 17:15:08 -070096 bool isDestNonKillable() const { return IsDestNonKillable; }
97 void setDestNonKillable() { IsDestNonKillable = true; }
98
Jim Stichnothf7c9a142014-04-29 10:52:43 -070099 Variable *getDest() const { return Dest; }
100
101 SizeT getSrcSize() const { return NumSrcs; }
102 Operand *getSrc(SizeT I) const {
103 assert(I < getSrcSize());
104 return Srcs[I];
105 }
106
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700107 bool isLastUse(const Operand *Src) const;
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700108 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700109
Andrew Scull9612d322015-07-06 14:53:25 -0700110 /// Returns a list of out-edges corresponding to a terminator
111 /// instruction, which is the last instruction of the block.
Andrew Scull87f80c12015-07-20 10:19:16 -0700112 /// The list must not contain duplicates.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700113 virtual NodeList getTerminatorEdges() const {
114 // All valid terminator instructions override this method. For
115 // the default implementation, we assert in case some CfgNode
116 // is constructed without a terminator instruction at the end.
117 llvm_unreachable(
118 "getTerminatorEdges() called on a non-terminator instruction");
119 return NodeList();
120 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700121 virtual bool isUnconditionalBranch() const { return false; }
Andrew Scull9612d322015-07-06 14:53:25 -0700122 /// If the instruction is a branch-type instruction with OldNode as a
123 /// target, repoint it to NewNode and return true, otherwise return
Andrew Scull87f80c12015-07-20 10:19:16 -0700124 /// false. Repoint all instances of OldNode as a target.
125 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700126 (void)OldNode;
127 (void)NewNode;
128 return false;
129 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700130
Jim Stichnothad403532014-09-25 12:44:17 -0700131 virtual bool isSimpleAssign() const { return false; }
132
Jim Stichnoth47752552014-10-13 17:15:08 -0700133 void livenessLightweight(Cfg *Func, LivenessBV &Live);
Andrew Scull9612d322015-07-06 14:53:25 -0700134 /// Calculates liveness for this instruction. Returns true if this
135 /// instruction is (tentatively) still live and should be retained,
136 /// and false if this instruction is (tentatively) dead and should be
137 /// deleted. The decision is tentative until the liveness dataflow
138 /// algorithm has converged, and then a separate pass permanently
139 /// deletes dead instructions.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700140 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
Jim Stichnoth47752552014-10-13 17:15:08 -0700141 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
Jim Stichnoth18735602014-09-16 19:59:35 -0700142
Andrew Scull9612d322015-07-06 14:53:25 -0700143 /// Get the number of native instructions that this instruction
144 /// ultimately emits. By default, high-level instructions don't
145 /// result in any native instructions, and a target-specific
146 /// instruction results in a single native instruction.
Jim Stichnoth18735602014-09-16 19:59:35 -0700147 virtual uint32_t getEmitInstCount() const { return 0; }
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800148 // TODO(stichnot): Change Inst back to abstract once the g++ build
149 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++
150 // because the resize(size_t, Ice::Inst) method is incorrectly
151 // declared and thus doesn't allow the abstract class Ice::Inst.
152 // The method should be declared resize(size_t, const Ice::Inst &).
153 // virtual void emit(const Cfg *Func) const = 0;
154 // virtual void emitIAS(const Cfg *Func) const = 0;
155 virtual void emit(const Cfg *) const {
156 llvm_unreachable("emit on abstract class");
157 }
158 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700159 virtual void dump(const Cfg *Func) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700160 virtual void dumpExtras(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700161 void dumpDecorated(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700162 void emitSources(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700163 void dumpSources(const Cfg *Func) const;
164 void dumpDest(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700165 virtual bool isRedundantAssign() const { return false; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700166
John Porto1bec8bc2015-06-22 10:51:13 -0700167 // TODO(jpp): Insts should not have non-trivial destructors, but they
168 // currently do. This dtor is marked final as a multi-step refactor that
169 // will eventually fix this problem.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700170 virtual ~Inst() = default;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700171
172protected:
173 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
174 void addSource(Operand *Src) {
175 assert(Src);
176 assert(NumSrcs < MaxSrcs);
177 Srcs[NumSrcs++] = Src;
178 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700179 void setLastUse(SizeT VarIndex) {
180 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
181 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
182 }
183 void resetLastUses() { LiveRangesEnded = 0; }
Andrew Scull9612d322015-07-06 14:53:25 -0700184 /// The destroy() method lets the instruction cleanly release any
185 /// memory that was allocated via the Cfg's allocator.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700186 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
187
188 const InstKind Kind;
Andrew Scull9612d322015-07-06 14:53:25 -0700189 /// Number is the instruction number for describing live ranges.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700190 InstNumberT Number;
Andrew Scull9612d322015-07-06 14:53:25 -0700191 /// Deleted means irrevocably deleted.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700192 bool Deleted = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700193 /// Dead means one of two things depending on context: (1) pending
194 /// deletion after liveness analysis converges, or (2) marked for
195 /// deletion during lowering due to a folded bool operation.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700196 bool Dead = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700197 /// HasSideEffects means the instruction is something like a function
198 /// call or a volatile load that can't be removed even if its Dest
199 /// variable is not live.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700200 bool HasSideEffects = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700201 /// IsDestNonKillable means that liveness analysis shouldn't consider
202 /// this instruction to kill the Dest variable. This is used when
203 /// lowering produces two assignments to the same variable.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700204 bool IsDestNonKillable = false;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700205
206 Variable *Dest;
207 const SizeT MaxSrcs; // only used for assert
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700208 SizeT NumSrcs = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700209 Operand **Srcs;
210
Andrew Scull9612d322015-07-06 14:53:25 -0700211 /// LiveRangesEnded marks which Variables' live ranges end in this
212 /// instruction. An instruction can have an arbitrary number of
213 /// source operands (e.g. a call instruction), and each source
214 /// operand can contain 0 or 1 Variable (and target-specific operands
215 /// could contain more than 1 Variable). All the variables in an
216 /// instruction are conceptually flattened and each variable is
217 /// mapped to one bit position of the LiveRangesEnded bit vector.
218 /// Only the first CHAR_BIT * sizeof(LREndedBits) variables are
219 /// tracked this way.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700220 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
221 LREndedBits LiveRangesEnded;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700222};
223
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700224class InstHighLevel : public Inst {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800225 InstHighLevel() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700226 InstHighLevel(const InstHighLevel &) = delete;
227 InstHighLevel &operator=(const InstHighLevel &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700228
229protected:
230 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
231 : Inst(Func, Kind, MaxSrcs, Dest) {}
232 void emit(const Cfg * /*Func*/) const override {
233 llvm_unreachable("emit() called on a non-lowered instruction");
234 }
235 void emitIAS(const Cfg * /*Func*/) const override {
236 llvm_unreachable("emitIAS() called on a non-lowered instruction");
237 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700238};
239
Andrew Scull9612d322015-07-06 14:53:25 -0700240/// Alloca instruction. This captures the size in bytes as getSrc(0),
241/// and the required alignment in bytes. The alignment must be either
242/// 0 (no alignment required) or a power of 2.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700243class InstAlloca : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800244 InstAlloca() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700245 InstAlloca(const InstAlloca &) = delete;
246 InstAlloca &operator=(const InstAlloca &) = delete;
247
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700248public:
249 static InstAlloca *create(Cfg *Func, Operand *ByteCount,
250 uint32_t AlignInBytes, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800251 return new (Func->allocate<InstAlloca>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700252 InstAlloca(Func, ByteCount, AlignInBytes, Dest);
253 }
254 uint32_t getAlignInBytes() const { return AlignInBytes; }
255 Operand *getSizeInBytes() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700256 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700257 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
258
259private:
260 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
261 Variable *Dest);
John Porto1bec8bc2015-06-22 10:51:13 -0700262
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700263 const uint32_t AlignInBytes;
264};
265
Andrew Scull9612d322015-07-06 14:53:25 -0700266/// Binary arithmetic instruction. The source operands are captured in
267/// getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700268class InstArithmetic : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800269 InstArithmetic() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700270 InstArithmetic(const InstArithmetic &) = delete;
271 InstArithmetic &operator=(const InstArithmetic &) = delete;
272
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700273public:
274 enum OpKind {
275#define X(tag, str, commutative) tag,
276 ICEINSTARITHMETIC_TABLE
277#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700278 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700279 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700280
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700281 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
282 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800283 return new (Func->allocate<InstArithmetic>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700284 InstArithmetic(Func, Op, Dest, Source1, Source2);
285 }
286 OpKind getOp() const { return Op; }
Karl Schimpfd6064a12014-08-27 15:34:58 -0700287 static const char *getOpName(OpKind Op);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700288 bool isCommutative() const;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700289 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700290 static bool classof(const Inst *Inst) {
291 return Inst->getKind() == Arithmetic;
292 }
293
294private:
295 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
296 Operand *Source2);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700297
298 const OpKind Op;
299};
300
Andrew Scull9612d322015-07-06 14:53:25 -0700301/// Assignment instruction. The source operand is captured in
302/// getSrc(0). This is not part of the LLVM bitcode, but is a useful
303/// abstraction for some of the lowering. E.g., if Phi instruction
304/// lowering happens before target lowering, or for representing an
305/// Inttoptr instruction, or as an intermediate step for lowering a
306/// Load instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700307class InstAssign : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800308 InstAssign() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700309 InstAssign(const InstAssign &) = delete;
310 InstAssign &operator=(const InstAssign &) = delete;
311
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700312public:
313 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800314 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700315 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700316 bool isSimpleAssign() const override { return true; }
317 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700318 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
319
320private:
321 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700322};
323
Andrew Scull9612d322015-07-06 14:53:25 -0700324/// Branch instruction. This represents both conditional and
325/// unconditional branches.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700326class InstBr : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800327 InstBr() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700328 InstBr(const InstBr &) = delete;
329 InstBr &operator=(const InstBr &) = delete;
330
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700331public:
Andrew Scull9612d322015-07-06 14:53:25 -0700332 /// Create a conditional branch. If TargetTrue==TargetFalse, it is
333 /// optimized to an unconditional branch.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700334 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
335 CfgNode *TargetFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800336 return new (Func->allocate<InstBr>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700337 InstBr(Func, Source, TargetTrue, TargetFalse);
338 }
Andrew Scull9612d322015-07-06 14:53:25 -0700339 /// Create an unconditional branch.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700340 static InstBr *create(Cfg *Func, CfgNode *Target) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800341 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700342 }
Jim Stichnothae953202014-12-20 06:17:49 -0800343 bool isUnconditional() const { return getTargetTrue() == nullptr; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700344 Operand *getCondition() const {
345 assert(!isUnconditional());
346 return getSrc(0);
347 }
348 CfgNode *getTargetTrue() const { return TargetTrue; }
349 CfgNode *getTargetFalse() const { return TargetFalse; }
350 CfgNode *getTargetUnconditional() const {
351 assert(isUnconditional());
352 return getTargetFalse();
353 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700354 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700355 bool isUnconditionalBranch() const override { return isUnconditional(); }
Andrew Scull87f80c12015-07-20 10:19:16 -0700356 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700357 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700358 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
359
360private:
Andrew Scull9612d322015-07-06 14:53:25 -0700361 /// Conditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700362 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
Andrew Scull9612d322015-07-06 14:53:25 -0700363 /// Unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700364 InstBr(Cfg *Func, CfgNode *Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700365
Andrew Scull9612d322015-07-06 14:53:25 -0700366 CfgNode *TargetFalse; /// Doubles as unconditional branch target
367 CfgNode *TargetTrue; /// nullptr if unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700368};
369
Andrew Scull9612d322015-07-06 14:53:25 -0700370/// Call instruction. The call target is captured as getSrc(0), and
371/// arg I is captured as getSrc(I+1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700372class InstCall : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800373 InstCall() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700374 InstCall(const InstCall &) = delete;
375 InstCall &operator=(const InstCall &) = delete;
376
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700377public:
378 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700379 Operand *CallTarget, bool HasTailCall) {
Andrew Scull9612d322015-07-06 14:53:25 -0700380 /// Set HasSideEffects to true so that the call instruction can't be
381 /// dead-code eliminated. IntrinsicCalls can override this if the
382 /// particular intrinsic is deletable and has no side-effects.
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700383 const bool HasSideEffects = true;
384 const InstKind Kind = Inst::Call;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800385 return new (Func->allocate<InstCall>()) InstCall(
Karl Schimpf8df26f32014-09-19 09:33:26 -0700386 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700387 }
388 void addArg(Operand *Arg) { addSource(Arg); }
389 Operand *getCallTarget() const { return getSrc(0); }
390 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
391 SizeT getNumArgs() const { return getSrcSize() - 1; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700392 bool isTailcall() const { return HasTailCall; }
Jan Voung3ce1a992015-02-03 08:27:44 -0800393 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700394 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700395 Type getReturnType() const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700396
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700397protected:
398 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
Karl Schimpf8df26f32014-09-19 09:33:26 -0700399 bool HasTailCall, bool HasSideEff, InstKind Kind)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700400 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700401 HasSideEffects = HasSideEff;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700402 addSource(CallTarget);
403 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700404
405private:
Karl Schimpf8df26f32014-09-19 09:33:26 -0700406 bool HasTailCall;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700407};
408
Andrew Scull9612d322015-07-06 14:53:25 -0700409/// Cast instruction (a.k.a. conversion operation).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700410class InstCast : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800411 InstCast() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700412 InstCast(const InstCast &) = delete;
413 InstCast &operator=(const InstCast &) = delete;
414
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700415public:
416 enum OpKind {
417#define X(tag, str) tag,
418 ICEINSTCAST_TABLE
419#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700420 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700421 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700422
Karl Schimpfbf170372014-12-15 10:16:31 -0800423 static const char *getCastName(OpKind Kind);
424
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700425 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
426 Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800427 return new (Func->allocate<InstCast>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700428 InstCast(Func, CastKind, Dest, Source);
429 }
430 OpKind getCastKind() const { return CastKind; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700431 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700432 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
433
434private:
435 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
John Porto1bec8bc2015-06-22 10:51:13 -0700436
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700437 const OpKind CastKind;
438};
439
Andrew Scull9612d322015-07-06 14:53:25 -0700440/// ExtractElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700441class InstExtractElement : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800442 InstExtractElement() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700443 InstExtractElement(const InstExtractElement &) = delete;
444 InstExtractElement &operator=(const InstExtractElement &) = delete;
445
Matt Wala49889232014-07-18 12:45:09 -0700446public:
447 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
448 Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800449 return new (Func->allocate<InstExtractElement>())
Matt Wala49889232014-07-18 12:45:09 -0700450 InstExtractElement(Func, Dest, Source1, Source2);
451 }
452
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700453 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700454 static bool classof(const Inst *Inst) {
455 return Inst->getKind() == ExtractElement;
456 }
457
458private:
459 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
460 Operand *Source2);
Matt Wala49889232014-07-18 12:45:09 -0700461};
462
Andrew Scull9612d322015-07-06 14:53:25 -0700463/// Floating-point comparison instruction. The source operands are
464/// captured in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700465class InstFcmp : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800466 InstFcmp() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700467 InstFcmp(const InstFcmp &) = delete;
468 InstFcmp &operator=(const InstFcmp &) = delete;
469
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700470public:
471 enum FCond {
472#define X(tag, str) tag,
473 ICEINSTFCMP_TABLE
474#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700475 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700476 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700477
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700478 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
479 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800480 return new (Func->allocate<InstFcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700481 InstFcmp(Func, Condition, Dest, Source1, Source2);
482 }
483 FCond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700484 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700485 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
486
487private:
488 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
489 Operand *Source2);
John Porto1bec8bc2015-06-22 10:51:13 -0700490
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700491 const FCond Condition;
492};
493
Andrew Scull9612d322015-07-06 14:53:25 -0700494/// Integer comparison instruction. The source operands are captured
495/// in getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700496class InstIcmp : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800497 InstIcmp() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700498 InstIcmp(const InstIcmp &) = delete;
499 InstIcmp &operator=(const InstIcmp &) = delete;
500
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700501public:
502 enum ICond {
503#define X(tag, str) tag,
504 ICEINSTICMP_TABLE
505#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700506 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700507 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700508
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700509 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
510 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800511 return new (Func->allocate<InstIcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700512 InstIcmp(Func, Condition, Dest, Source1, Source2);
513 }
514 ICond getCondition() const { return Condition; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700515 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700516 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
517
518private:
519 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
520 Operand *Source2);
John Porto1bec8bc2015-06-22 10:51:13 -0700521
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700522 const ICond Condition;
523};
524
Andrew Scull9612d322015-07-06 14:53:25 -0700525/// InsertElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700526class InstInsertElement : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800527 InstInsertElement() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700528 InstInsertElement(const InstInsertElement &) = delete;
529 InstInsertElement &operator=(const InstInsertElement &) = delete;
530
Matt Wala49889232014-07-18 12:45:09 -0700531public:
532 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
533 Operand *Source2, Operand *Source3) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800534 return new (Func->allocate<InstInsertElement>())
Matt Wala49889232014-07-18 12:45:09 -0700535 InstInsertElement(Func, Dest, Source1, Source2, Source3);
536 }
537
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700538 void dump(const Cfg *Func) const override;
Matt Wala49889232014-07-18 12:45:09 -0700539 static bool classof(const Inst *Inst) {
540 return Inst->getKind() == InsertElement;
541 }
542
543private:
544 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
545 Operand *Source2, Operand *Source3);
Matt Wala49889232014-07-18 12:45:09 -0700546};
547
Andrew Scull9612d322015-07-06 14:53:25 -0700548/// Call to an intrinsic function. The call target is captured as getSrc(0),
549/// and arg I is captured as getSrc(I+1).
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700550class InstIntrinsicCall : public InstCall {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800551 InstIntrinsicCall() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700552 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
553 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
554
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700555public:
556 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
557 Operand *CallTarget,
558 const Intrinsics::IntrinsicInfo &Info) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800559 return new (Func->allocate<InstIntrinsicCall>())
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700560 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
561 }
562 static bool classof(const Inst *Inst) {
563 return Inst->getKind() == IntrinsicCall;
564 }
565
566 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
567
568private:
569 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
570 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
Karl Schimpf8df26f32014-09-19 09:33:26 -0700571 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700572 Inst::IntrinsicCall),
573 Info(Info) {}
John Porto1bec8bc2015-06-22 10:51:13 -0700574
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700575 const Intrinsics::IntrinsicInfo Info;
576};
577
Andrew Scull9612d322015-07-06 14:53:25 -0700578/// Load instruction. The source address is captured in getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700579class InstLoad : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800580 InstLoad() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700581 InstLoad(const InstLoad &) = delete;
582 InstLoad &operator=(const InstLoad &) = delete;
583
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700584public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700585 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
Jim Stichnothc4554d72014-09-30 16:49:38 -0700586 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700587 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700588 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800589 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700590 }
591 Operand *getSourceAddress() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700592 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700593 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
594
595private:
596 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700597};
598
Andrew Scull9612d322015-07-06 14:53:25 -0700599/// Phi instruction. For incoming edge I, the node is Labels[I] and
600/// the Phi source operand is getSrc(I).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700601class InstPhi : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800602 InstPhi() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700603 InstPhi(const InstPhi &) = delete;
604 InstPhi &operator=(const InstPhi &) = delete;
605
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700606public:
607 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800608 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700609 }
610 void addArgument(Operand *Source, CfgNode *Label);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700611 Operand *getOperandForTarget(CfgNode *Target) const;
Jim Stichnoth98712a32014-10-24 10:59:02 -0700612 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700613 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700614 Liveness *Liveness);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700615 Inst *lower(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700616 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700617 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
618
619private:
620 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700621 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700622 Func->deallocateArrayOf<CfgNode *>(Labels);
623 Inst::destroy(Func);
624 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700625
Andrew Scull9612d322015-07-06 14:53:25 -0700626 /// Labels[] duplicates the InEdges[] information in the enclosing
627 /// CfgNode, but the Phi instruction is created before InEdges[]
628 /// is available, so it's more complicated to share the list.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700629 CfgNode **Labels;
630};
631
Andrew Scull9612d322015-07-06 14:53:25 -0700632/// Ret instruction. The return value is captured in getSrc(0), but if
633/// there is no return value (void-type function), then
634/// getSrcSize()==0 and hasRetValue()==false.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700635class InstRet : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800636 InstRet() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700637 InstRet(const InstRet &) = delete;
638 InstRet &operator=(const InstRet &) = delete;
639
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700640public:
Jim Stichnothae953202014-12-20 06:17:49 -0800641 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800642 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700643 }
644 bool hasRetValue() const { return getSrcSize(); }
645 Operand *getRetValue() const {
646 assert(hasRetValue());
647 return getSrc(0);
648 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700649 NodeList getTerminatorEdges() const override { return NodeList(); }
650 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700651 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
652
653private:
654 InstRet(Cfg *Func, Operand *RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700655};
656
Andrew Scull9612d322015-07-06 14:53:25 -0700657/// Select instruction. The condition, true, and false operands are captured.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700658class InstSelect : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800659 InstSelect() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700660 InstSelect(const InstSelect &) = delete;
661 InstSelect &operator=(const InstSelect &) = delete;
662
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700663public:
664 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
665 Operand *SourceTrue, Operand *SourceFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800666 return new (Func->allocate<InstSelect>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700667 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
668 }
669 Operand *getCondition() const { return getSrc(0); }
670 Operand *getTrueOperand() const { return getSrc(1); }
671 Operand *getFalseOperand() const { return getSrc(2); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700672 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700673 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
674
675private:
676 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
677 Operand *Source2);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700678};
679
Andrew Scull9612d322015-07-06 14:53:25 -0700680/// Store instruction. The address operand is captured, along with the
681/// data operand to be stored into the address.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700682class InstStore : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800683 InstStore() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700684 InstStore(const InstStore &) = delete;
685 InstStore &operator=(const InstStore &) = delete;
686
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700687public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700688 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700689 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700690 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700691 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800692 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700693 }
694 Operand *getAddr() const { return getSrc(1); }
695 Operand *getData() const { return getSrc(0); }
Andrew Scullaa6c1092015-09-03 17:50:30 -0700696 Variable *getRmwBeacon() const;
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700697 void setRmwBeacon(Variable *Beacon);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700698 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700699 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
700
701private:
702 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700703};
704
Andrew Scull9612d322015-07-06 14:53:25 -0700705/// Switch instruction. The single source operand is captured as
706/// getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700707class InstSwitch : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800708 InstSwitch() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700709 InstSwitch(const InstSwitch &) = delete;
710 InstSwitch &operator=(const InstSwitch &) = delete;
711
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700712public:
713 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
714 CfgNode *LabelDefault) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800715 return new (Func->allocate<InstSwitch>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700716 InstSwitch(Func, NumCases, Source, LabelDefault);
717 }
718 Operand *getComparison() const { return getSrc(0); }
719 CfgNode *getLabelDefault() const { return LabelDefault; }
720 SizeT getNumCases() const { return NumCases; }
721 uint64_t getValue(SizeT I) const {
722 assert(I < NumCases);
723 return Values[I];
724 }
725 CfgNode *getLabel(SizeT I) const {
726 assert(I < NumCases);
727 return Labels[I];
728 }
729 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700730 NodeList getTerminatorEdges() const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700731 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700732 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700733 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
734
735private:
736 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700737 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700738 Func->deallocateArrayOf<uint64_t>(Values);
739 Func->deallocateArrayOf<CfgNode *>(Labels);
740 Inst::destroy(Func);
741 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700742
743 CfgNode *LabelDefault;
Andrew Scull9612d322015-07-06 14:53:25 -0700744 SizeT NumCases; /// not including the default case
745 uint64_t *Values; /// size is NumCases
746 CfgNode **Labels; /// size is NumCases
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700747};
748
Andrew Scull9612d322015-07-06 14:53:25 -0700749/// Unreachable instruction. This is a terminator instruction with no
750/// operands.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700751class InstUnreachable : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800752 InstUnreachable() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700753 InstUnreachable(const InstUnreachable &) = delete;
754 InstUnreachable &operator=(const InstUnreachable &) = delete;
755
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700756public:
757 static InstUnreachable *create(Cfg *Func) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800758 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700759 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700760 NodeList getTerminatorEdges() const override { return NodeList(); }
761 void dump(const Cfg *Func) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700762 static bool classof(const Inst *Inst) {
763 return Inst->getKind() == Unreachable;
764 }
765
766private:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800767 explicit InstUnreachable(Cfg *Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700768};
769
Andrew Scull9612d322015-07-06 14:53:25 -0700770/// BundleLock instruction. There are no operands. Contains an option
771/// indicating whether align_to_end is specified.
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800772class InstBundleLock : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800773 InstBundleLock() = delete;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800774 InstBundleLock(const InstBundleLock &) = delete;
775 InstBundleLock &operator=(const InstBundleLock &) = delete;
776
777public:
778 enum Option { Opt_None, Opt_AlignToEnd };
779 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
780 return new (Func->allocate<InstBundleLock>())
781 InstBundleLock(Func, BundleOption);
782 }
783 void emit(const Cfg *Func) const override;
784 void emitIAS(const Cfg * /* Func */) const override {}
785 void dump(const Cfg *Func) const override;
786 Option getOption() const { return BundleOption; }
787 static bool classof(const Inst *Inst) {
788 return Inst->getKind() == BundleLock;
789 }
790
791private:
792 Option BundleOption;
793 InstBundleLock(Cfg *Func, Option BundleOption);
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800794};
795
Andrew Scull9612d322015-07-06 14:53:25 -0700796/// BundleUnlock instruction. There are no operands.
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800797class InstBundleUnlock : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800798 InstBundleUnlock() = delete;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800799 InstBundleUnlock(const InstBundleUnlock &) = delete;
800 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
801
802public:
803 static InstBundleUnlock *create(Cfg *Func) {
804 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
805 }
806 void emit(const Cfg *Func) const override;
807 void emitIAS(const Cfg * /* Func */) const override {}
808 void dump(const Cfg *Func) const override;
809 static bool classof(const Inst *Inst) {
810 return Inst->getKind() == BundleUnlock;
811 }
812
813private:
814 explicit InstBundleUnlock(Cfg *Func);
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800815};
816
Andrew Scull9612d322015-07-06 14:53:25 -0700817/// FakeDef instruction. This creates a fake definition of a variable,
818/// which is how we represent the case when an instruction produces
819/// multiple results. This doesn't happen with high-level ICE
820/// instructions, but might with lowered instructions. For example,
821/// this would be a way to represent condition flags being modified by
822/// an instruction.
823///
824/// It's generally useful to set the optional source operand to be the
825/// dest variable of the instruction that actually produces the FakeDef
826/// dest. Otherwise, the original instruction could be dead-code
827/// eliminated if its dest operand is unused, and therefore the FakeDef
828/// dest wouldn't be properly initialized.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700829class InstFakeDef : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800830 InstFakeDef() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700831 InstFakeDef(const InstFakeDef &) = delete;
832 InstFakeDef &operator=(const InstFakeDef &) = delete;
833
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700834public:
Jim Stichnothae953202014-12-20 06:17:49 -0800835 static InstFakeDef *create(Cfg *Func, Variable *Dest,
836 Variable *Src = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800837 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700838 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700839 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700840 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700841 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700842 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
843
844private:
845 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700846};
847
Andrew Scull9612d322015-07-06 14:53:25 -0700848/// FakeUse instruction. This creates a fake use of a variable, to
849/// keep the instruction that produces that variable from being
850/// dead-code eliminated. This is useful in a variety of lowering
851/// situations. The FakeUse instruction has no dest, so it can itself
852/// never be dead-code eliminated.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700853class InstFakeUse : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800854 InstFakeUse() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700855 InstFakeUse(const InstFakeUse &) = delete;
856 InstFakeUse &operator=(const InstFakeUse &) = delete;
857
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700858public:
859 static InstFakeUse *create(Cfg *Func, Variable *Src) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800860 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700861 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700862 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700863 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700864 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700865 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
866
867private:
868 InstFakeUse(Cfg *Func, Variable *Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700869};
870
Andrew Scull9612d322015-07-06 14:53:25 -0700871/// FakeKill instruction. This "kills" a set of variables by modeling
872/// a trivial live range at this instruction for each (implicit)
873/// variable. The primary use is to indicate that scratch registers
874/// are killed after a call, so that the register allocator won't
875/// assign a scratch register to a variable whose live range spans a
876/// call.
877///
878/// The FakeKill instruction also holds a pointer to the instruction
879/// that kills the set of variables, so that if that linked instruction
880/// gets dead-code eliminated, the FakeKill instruction will as well.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700881class InstFakeKill : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800882 InstFakeKill() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700883 InstFakeKill(const InstFakeKill &) = delete;
884 InstFakeKill &operator=(const InstFakeKill &) = delete;
885
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700886public:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800887 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800888 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700889 }
890 const Inst *getLinked() const { return Linked; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700891 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700892 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700893 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700894 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
895
896private:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800897 InstFakeKill(Cfg *Func, const Inst *Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700898
Andrew Scull9612d322015-07-06 14:53:25 -0700899 /// This instruction is ignored if Linked->isDeleted() is true.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700900 const Inst *Linked;
901};
902
Andrew Scull87f80c12015-07-20 10:19:16 -0700903/// JumpTable instruction. This represents a jump table that will be
904/// stored in the .rodata section. This is used to track and repoint
905/// the target CfgNodes which may change, for example due to
906/// splitting for phi lowering.
907class InstJumpTable : public InstHighLevel {
908 InstJumpTable() = delete;
909 InstJumpTable(const InstJumpTable &) = delete;
910 InstJumpTable &operator=(const InstJumpTable &) = delete;
911
912public:
913 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
914 return new (Func->allocate<InstJumpTable>())
915 InstJumpTable(Func, NumTargets, Default);
916 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700917 void addTarget(SizeT TargetIndex, CfgNode *Target) {
918 assert(TargetIndex < NumTargets);
919 Targets[TargetIndex] = Target;
920 }
921 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Andrew Scull86df4e92015-07-30 13:54:44 -0700922 SizeT getId() const { return Id; }
923 SizeT getNumTargets() const { return NumTargets; }
924 CfgNode *getTarget(SizeT I) const {
925 assert(I < NumTargets);
926 return Targets[I];
927 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700928 void dump(const Cfg *Func) const override;
929 static bool classof(const Inst *Inst) { return Inst->getKind() == JumpTable; }
930
Andrew Scull86df4e92015-07-30 13:54:44 -0700931 static IceString makeName(const IceString &FuncName, SizeT Id) {
932 return ".L" + FuncName + "$jumptable$__" + std::to_string(Id);
933 }
934
Andrew Scull87f80c12015-07-20 10:19:16 -0700935private:
936 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
937 void destroy(Cfg *Func) override {
938 Func->deallocateArrayOf<CfgNode *>(Targets);
939 Inst::destroy(Func);
940 }
941
Andrew Scull86df4e92015-07-30 13:54:44 -0700942 const SizeT Id;
Andrew Scull87f80c12015-07-20 10:19:16 -0700943 const SizeT NumTargets;
944 CfgNode **Targets;
945};
946
Andrew Scull9612d322015-07-06 14:53:25 -0700947/// The Target instruction is the base class for all target-specific
948/// instructions.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700949class InstTarget : public Inst {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800950 InstTarget() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700951 InstTarget(const InstTarget &) = delete;
952 InstTarget &operator=(const InstTarget &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700953
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700954public:
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700955 uint32_t getEmitInstCount() const override { return 1; }
956 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700957 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
958
959protected:
960 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
961 : Inst(Func, Kind, MaxSrcs, Dest) {
962 assert(Kind >= Target);
963 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700964};
965
Jan Voungb3401d22015-05-18 09:38:21 -0700966bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
967
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700968} // end of namespace Ice
969
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800970namespace llvm {
971
Andrew Scull9612d322015-07-06 14:53:25 -0700972/// Override the default ilist traits so that Inst's private ctor and
973/// deleted dtor aren't invoked.
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800974template <>
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800975struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800976 Ice::Inst *createSentinel() const {
977 return static_cast<Ice::Inst *>(&Sentinel);
978 }
979 static void destroySentinel(Ice::Inst *) {}
980 Ice::Inst *provideInitialHead() const { return createSentinel(); }
981 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
982 static void noteHead(Ice::Inst *, Ice::Inst *) {}
983 void deleteNode(Ice::Inst *) {}
984
985private:
986 mutable ilist_half_node<Ice::Inst> Sentinel;
987};
988
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800989} // end of namespace llvm
990
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700991#endif // SUBZERO_SRC_ICEINST_H