blob: 8ffb1d2c0873da2142cf87d11a052a7dcadf5e00 [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
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the Inst class and its target-independent subclasses.
12///
13/// These represent the high-level Vanilla ICE instructions and map roughly 1:1
14/// to LLVM instructions.
Andrew Scull9612d322015-07-06 14:53:25 -070015///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070016//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEINST_H
19#define SUBZERO_SRC_ICEINST_H
20
John Porto7e93c622015-06-23 10:58:57 -070021#include "IceCfg.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070022#include "IceDefs.h"
23#include "IceInst.def"
Jan Voung3bd9f1a2014-06-18 10:50:57 -070024#include "IceIntrinsics.h"
John Portoa47c11c2016-04-21 05:53:42 -070025#include "IceOperand.h"
John Porto03077212016-04-05 06:30:21 -070026#include "IceSwitchLowering.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070027#include "IceTypes.h"
28
29// TODO: The Cfg structure, and instructions in particular, need to be
Andrew Scull6ef79492015-09-09 15:50:42 -070030// validated for things like valid operand types, valid branch targets, proper
Andrew Scull57e12682015-09-16 11:30:19 -070031// ordering of Phi and non-Phi instructions, etc. Most of the validity checking
32// will be done in the bitcode reader. We need a list of everything that should
33// be validated, and tests for each.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070034
35namespace Ice {
36
Andrew Scull6ef79492015-09-09 15:50:42 -070037/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
38/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
39/// low-level (target-specific) ICE instructions inherit from InstTarget.
Jim Stichnoth607e9f02014-11-06 13:32:05 -080040class Inst : public llvm::ilist_node<Inst> {
Jim Stichnothc6ead202015-02-24 09:30:30 -080041 Inst() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070042 Inst(const Inst &) = delete;
43 Inst &operator=(const Inst &) = delete;
44
Jim Stichnothf7c9a142014-04-29 10:52:43 -070045public:
46 enum InstKind {
47 // Arbitrary (alphabetical) order, except put Unreachable first.
48 Unreachable,
49 Alloca,
50 Arithmetic,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070051 Br,
52 Call,
53 Cast,
Matt Wala49889232014-07-18 12:45:09 -070054 ExtractElement,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070055 Fcmp,
56 Icmp,
Jan Voung3bd9f1a2014-06-18 10:50:57 -070057 IntrinsicCall,
Matt Wala49889232014-07-18 12:45:09 -070058 InsertElement,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070059 Load,
60 Phi,
61 Ret,
62 Select,
63 Store,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070064 Switch,
John Portoa47c11c2016-04-21 05:53:42 -070065 Assign, // not part of LLVM/PNaCl bitcode
66 Breakpoint, // not part of LLVM/PNaCl bitcode
67 BundleLock, // not part of LLVM/PNaCl bitcode
68 BundleUnlock, // not part of LLVM/PNaCl bitcode
69 FakeDef, // not part of LLVM/PNaCl bitcode
70 FakeUse, // not part of LLVM/PNaCl bitcode
71 FakeKill, // not part of LLVM/PNaCl bitcode
72 JumpTable, // not part of LLVM/PNaCl bitcode
73 ShuffleVector, // not part of LLVM/PNaCl bitcode
Andrew Scull6ef79492015-09-09 15:50:42 -070074 // Anything >= Target is an InstTarget subclass. Note that the value-spaces
75 // are shared across targets. To avoid confusion over the definition of
76 // shared values, an object specific to one target should never be passed
77 // to a different target.
78 Target,
79 Target_Max = std::numeric_limits<uint8_t>::max(),
Jim Stichnothf7c9a142014-04-29 10:52:43 -070080 };
Andrew Scull6ef79492015-09-09 15:50:42 -070081 static_assert(Target <= Target_Max, "Must not be above max.");
Jim Stichnothf7c9a142014-04-29 10:52:43 -070082 InstKind getKind() const { return Kind; }
Jim Stichnoth467ffe52016-03-29 15:01:06 -070083 virtual const char *getInstName() const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070084
Jim Stichnothd97c7df2014-06-04 11:57:08 -070085 InstNumberT getNumber() const { return Number; }
86 void renumber(Cfg *Func);
Jim Stichnothe5b73e62014-12-15 09:58:51 -080087 enum {
88 NumberDeleted = -1,
89 NumberSentinel = 0,
90 NumberInitial = 2,
91 NumberExtended = NumberInitial - 1
92 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -070093
94 bool isDeleted() const { return Deleted; }
95 void setDeleted() { Deleted = true; }
Jim Stichnotha59ae6f2015-05-17 10:11:41 -070096 void setDead(bool Value = true) { Dead = Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070097 void deleteIfDead();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070098
99 bool hasSideEffects() const { return HasSideEffects; }
100
Jim Stichnoth230d4102015-09-25 17:40:32 -0700101 bool isDestRedefined() const { return IsDestRedefined; }
102 void setDestRedefined() { IsDestRedefined = true; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700103
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700104 Variable *getDest() const { return Dest; }
105
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700106 SizeT getSrcSize() const { return Srcs.size(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700107 Operand *getSrc(SizeT I) const {
108 assert(I < getSrcSize());
109 return Srcs[I];
110 }
Manasij Mukherjee032c3152016-05-24 14:25:04 -0700111 void replaceSource(SizeT Index, Operand *Replacement) {
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700112 assert(Index < getSrcSize());
Manasij Mukherjee032c3152016-05-24 14:25:04 -0700113 assert(!isDeleted());
Manasij Mukherjee032c3152016-05-24 14:25:04 -0700114 Srcs[Index] = Replacement;
115 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700116
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700117 bool isLastUse(const Operand *Src) const;
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700118 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700119
Andrew Scull6ef79492015-09-09 15:50:42 -0700120 /// Returns a list of out-edges corresponding to a terminator instruction,
121 /// which is the last instruction of the block. The list must not contain
122 /// duplicates.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700123 virtual NodeList getTerminatorEdges() const {
Andrew Scull6ef79492015-09-09 15:50:42 -0700124 // All valid terminator instructions override this method. For the default
125 // implementation, we assert in case some CfgNode is constructed without a
126 // terminator instruction at the end.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700127 llvm_unreachable(
128 "getTerminatorEdges() called on a non-terminator instruction");
129 return NodeList();
130 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700131 virtual bool isUnconditionalBranch() const { return false; }
Andrew Scull57e12682015-09-16 11:30:19 -0700132 /// If the instruction is a branch-type instruction with OldNode as a target,
133 /// repoint it to NewNode and return true, otherwise return false. Repoint all
134 /// instances of OldNode as a target.
Andrew Scull87f80c12015-07-20 10:19:16 -0700135 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700136 (void)OldNode;
137 (void)NewNode;
138 return false;
139 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700140
Jim Stichnoth28b71be2015-10-12 15:24:46 -0700141 /// Returns true if the instruction is equivalent to a simple
142 /// "var_dest=var_src" assignment where the dest and src are both variables.
143 virtual bool isVarAssign() const { return false; }
Jim Stichnothad403532014-09-25 12:44:17 -0700144
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700145 /// Returns true if the instruction has a possible side effect of changing
146 /// memory, in which case a memory load should not be reordered with respect
147 /// to this instruction. It should really be pure virtual, but we can't
148 /// because of g++ and llvm::ilist<>, so we implement it as
149 /// report_fatal_error().
150 virtual bool isMemoryWrite() const;
151
Jim Stichnothb9a84722016-08-01 13:18:36 -0700152 /// Returns true if the (target-specific) instruction represents an
153 /// intra-block label, i.e. branch target. This is meant primarily for
154 /// Cfg::splitLocalVars().
155 virtual bool isLabel() const { return false; }
156 /// If the (target-specific) instruction represents an intra-block branch to
157 /// some Label instruction, return that Label branch target instruction;
158 /// otherwise return nullptr.
159 virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; }
160
Jim Stichnoth47752552014-10-13 17:15:08 -0700161 void livenessLightweight(Cfg *Func, LivenessBV &Live);
Andrew Scull57e12682015-09-16 11:30:19 -0700162 /// Calculates liveness for this instruction. Returns true if this instruction
163 /// is (tentatively) still live and should be retained, and false if this
164 /// instruction is (tentatively) dead and should be deleted. The decision is
165 /// tentative until the liveness dataflow algorithm has converged, and then a
166 /// separate pass permanently deletes dead instructions.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700167 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
Jim Stichnoth47752552014-10-13 17:15:08 -0700168 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
Jim Stichnoth18735602014-09-16 19:59:35 -0700169
Andrew Scull6ef79492015-09-09 15:50:42 -0700170 /// Get the number of native instructions that this instruction ultimately
171 /// emits. By default, high-level instructions don't result in any native
172 /// instructions, and a target-specific instruction results in a single native
173 /// instruction.
Jim Stichnoth18735602014-09-16 19:59:35 -0700174 virtual uint32_t getEmitInstCount() const { return 0; }
Andrew Scull57e12682015-09-16 11:30:19 -0700175 // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
176 // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
177 // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
178 // allow the abstract class Ice::Inst. The method should be declared
179 // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
180 // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800181 virtual void emit(const Cfg *) const {
182 llvm_unreachable("emit on abstract class");
183 }
184 virtual void emitIAS(const Cfg *Func) const { emit(Func); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700185 virtual void dump(const Cfg *Func) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700186 virtual void dumpExtras(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700187 void dumpDecorated(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700188 void emitSources(const Cfg *Func) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700189 void dumpSources(const Cfg *Func) const;
190 void dumpDest(const Cfg *Func) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700191 virtual bool isRedundantAssign() const { return false; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700192
Sean Kleinfc707ff2016-02-29 16:44:07 -0800193 virtual ~Inst() = default;
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700194 void replaceDest(Variable *Var) { Dest = Var; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700195
Nicolas Capens038a9b92016-09-12 15:40:25 -0400196 void operator delete(void *Ptr, std::size_t Size) {
197 assert(CfgAllocatorTraits::current() != nullptr);
198 CfgAllocatorTraits::current()->Deallocate(Ptr, Size);
199 llvm::report_fatal_error("Inst unexpectedly deleted");
200 }
201
Alexis Hetu932640b2018-06-20 15:35:53 -0400202 inline void* getExternalData() const { return externalData; }
203 inline void setExternalData(void* data) { externalData = data; }
204
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700205protected:
206 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
207 void addSource(Operand *Src) {
208 assert(Src);
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700209 Srcs.push_back(Src);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700210 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700211 void setLastUse(SizeT VarIndex) {
212 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
213 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
214 }
215 void resetLastUses() { LiveRangesEnded = 0; }
Andrew Scull57e12682015-09-16 11:30:19 -0700216 /// The destroy() method lets the instruction cleanly release any memory that
217 /// was allocated via the Cfg's allocator.
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700218 virtual void destroy(Cfg *) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700219
220 const InstKind Kind;
Andrew Scull9612d322015-07-06 14:53:25 -0700221 /// Number is the instruction number for describing live ranges.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700222 InstNumberT Number;
Andrew Scull9612d322015-07-06 14:53:25 -0700223 /// Deleted means irrevocably deleted.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700224 bool Deleted = false;
Andrew Scull57e12682015-09-16 11:30:19 -0700225 /// Dead means one of two things depending on context: (1) pending deletion
226 /// after liveness analysis converges, or (2) marked for deletion during
227 /// lowering due to a folded bool operation.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700228 bool Dead = false;
Andrew Scull57e12682015-09-16 11:30:19 -0700229 /// HasSideEffects means the instruction is something like a function call or
230 /// a volatile load that can't be removed even if its Dest variable is not
231 /// live.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700232 bool HasSideEffects = false;
Jim Stichnoth230d4102015-09-25 17:40:32 -0700233 /// IsDestRedefined indicates that this instruction is not the first
234 /// definition of Dest in the basic block. The effect is that liveness
235 /// analysis shouldn't consider this instruction to be the start of Dest's
236 /// live range; rather, there is some other instruction earlier in the basic
237 /// block with the same Dest. This is maintained because liveness analysis
238 /// has an invariant (primarily for performance reasons) that any Variable's
239 /// live range recorded in a basic block has at most one start and at most one
240 /// end.
241 bool IsDestRedefined = false;
Alexis Hetu932640b2018-06-20 15:35:53 -0400242 /// External data can be set by an optimizer to compute and retain any
243 /// information related to the current instruction. All the memory used to
244 /// store this information must be managed by the optimizer.
245 void* externalData = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700246
247 Variable *Dest;
248 const SizeT MaxSrcs; // only used for assert
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700249
250 CfgVector<Operand *> Srcs;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700251
Andrew Scull9612d322015-07-06 14:53:25 -0700252 /// LiveRangesEnded marks which Variables' live ranges end in this
Andrew Scull57e12682015-09-16 11:30:19 -0700253 /// instruction. An instruction can have an arbitrary number of source
254 /// operands (e.g. a call instruction), and each source operand can contain 0
255 /// or 1 Variable (and target-specific operands could contain more than 1
256 /// Variable). All the variables in an instruction are conceptually flattened
257 /// and each variable is mapped to one bit position of the LiveRangesEnded bit
258 /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
Andrew Scull9612d322015-07-06 14:53:25 -0700259 /// tracked this way.
Andrew Scull8072bae2015-09-14 16:01:26 -0700260 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700261 LREndedBits LiveRangesEnded;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700262};
263
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700264class InstHighLevel : public Inst {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800265 InstHighLevel() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700266 InstHighLevel(const InstHighLevel &) = delete;
267 InstHighLevel &operator=(const InstHighLevel &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700268
269protected:
270 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
271 : Inst(Func, Kind, MaxSrcs, Dest) {}
272 void emit(const Cfg * /*Func*/) const override {
273 llvm_unreachable("emit() called on a non-lowered instruction");
274 }
275 void emitIAS(const Cfg * /*Func*/) const override {
276 llvm_unreachable("emitIAS() called on a non-lowered instruction");
277 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700278};
279
Andrew Scull57e12682015-09-16 11:30:19 -0700280/// Alloca instruction. This captures the size in bytes as getSrc(0), and the
281/// required alignment in bytes. The alignment must be either 0 (no alignment
282/// required) or a power of 2.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700283class InstAlloca : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800284 InstAlloca() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700285 InstAlloca(const InstAlloca &) = delete;
286 InstAlloca &operator=(const InstAlloca &) = delete;
287
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700288public:
David Sehr2f3b8ec2015-11-16 16:51:39 -0800289 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
290 uint32_t AlignInBytes) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800291 return new (Func->allocate<InstAlloca>())
David Sehr2f3b8ec2015-11-16 16:51:39 -0800292 InstAlloca(Func, Dest, ByteCount, AlignInBytes);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700293 }
294 uint32_t getAlignInBytes() const { return AlignInBytes; }
295 Operand *getSizeInBytes() const { return getSrc(0); }
Jim Stichnoth55f931f2015-09-23 16:33:08 -0700296 bool getKnownFrameOffset() const { return KnownFrameOffset; }
297 void setKnownFrameOffset() { KnownFrameOffset = true; }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700298 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700299 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800300 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700301
302private:
David Sehr2f3b8ec2015-11-16 16:51:39 -0800303 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
304 uint32_t AlignInBytes);
John Porto1bec8bc2015-06-22 10:51:13 -0700305
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700306 const uint32_t AlignInBytes;
Jim Stichnoth55f931f2015-09-23 16:33:08 -0700307 bool KnownFrameOffset = false;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700308};
309
Andrew Scull57e12682015-09-16 11:30:19 -0700310/// Binary arithmetic instruction. The source operands are captured in getSrc(0)
311/// and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700312class InstArithmetic : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800313 InstArithmetic() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700314 InstArithmetic(const InstArithmetic &) = delete;
315 InstArithmetic &operator=(const InstArithmetic &) = delete;
316
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700317public:
318 enum OpKind {
319#define X(tag, str, commutative) tag,
320 ICEINSTARITHMETIC_TABLE
321#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700322 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700323 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700324
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700325 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
326 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800327 return new (Func->allocate<InstArithmetic>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700328 InstArithmetic(Func, Op, Dest, Source1, Source2);
329 }
330 OpKind getOp() const { return Op; }
Eric Holke37076a2016-01-27 14:06:35 -0800331
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700332 virtual const char *getInstName() const override;
Eric Holke37076a2016-01-27 14:06:35 -0800333
Karl Schimpfd6064a12014-08-27 15:34:58 -0700334 static const char *getOpName(OpKind Op);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700335 bool isCommutative() const;
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700336 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700337 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800338 static bool classof(const Inst *Instr) {
339 return Instr->getKind() == Arithmetic;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700340 }
341
342private:
343 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
344 Operand *Source2);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700345
346 const OpKind Op;
347};
348
Andrew Scull57e12682015-09-16 11:30:19 -0700349/// Assignment instruction. The source operand is captured in getSrc(0). This is
350/// not part of the LLVM bitcode, but is a useful abstraction for some of the
351/// lowering. E.g., if Phi instruction lowering happens before target lowering,
352/// or for representing an Inttoptr instruction, or as an intermediate step for
353/// lowering a Load instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700354class InstAssign : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800355 InstAssign() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700356 InstAssign(const InstAssign &) = delete;
357 InstAssign &operator=(const InstAssign &) = delete;
358
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700359public:
360 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800361 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700362 }
Jim Stichnoth28b71be2015-10-12 15:24:46 -0700363 bool isVarAssign() const override;
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700364 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700365 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800366 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700367
368private:
369 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700370};
371
Andrew Scull57e12682015-09-16 11:30:19 -0700372/// Branch instruction. This represents both conditional and unconditional
373/// branches.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700374class InstBr : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800375 InstBr() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700376 InstBr(const InstBr &) = delete;
377 InstBr &operator=(const InstBr &) = delete;
378
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700379public:
Andrew Scull57e12682015-09-16 11:30:19 -0700380 /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
381 /// to an unconditional branch.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700382 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
383 CfgNode *TargetFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800384 return new (Func->allocate<InstBr>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700385 InstBr(Func, Source, TargetTrue, TargetFalse);
386 }
Andrew Scull9612d322015-07-06 14:53:25 -0700387 /// Create an unconditional branch.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700388 static InstBr *create(Cfg *Func, CfgNode *Target) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800389 return new (Func->allocate<InstBr>()) InstBr(Func, Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700390 }
Jim Stichnothae953202014-12-20 06:17:49 -0800391 bool isUnconditional() const { return getTargetTrue() == nullptr; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700392 Operand *getCondition() const {
393 assert(!isUnconditional());
394 return getSrc(0);
395 }
396 CfgNode *getTargetTrue() const { return TargetTrue; }
397 CfgNode *getTargetFalse() const { return TargetFalse; }
398 CfgNode *getTargetUnconditional() const {
399 assert(isUnconditional());
400 return getTargetFalse();
401 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700402 NodeList getTerminatorEdges() const override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700403 bool isUnconditionalBranch() const override { return isUnconditional(); }
Andrew Scull87f80c12015-07-20 10:19:16 -0700404 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700405 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700406 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800407 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700408
409private:
Andrew Scull9612d322015-07-06 14:53:25 -0700410 /// Conditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700411 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
Andrew Scull9612d322015-07-06 14:53:25 -0700412 /// Unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700413 InstBr(Cfg *Func, CfgNode *Target);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700414
Andrew Scull9612d322015-07-06 14:53:25 -0700415 CfgNode *TargetFalse; /// Doubles as unconditional branch target
416 CfgNode *TargetTrue; /// nullptr if unconditional branch
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700417};
418
Andrew Scull57e12682015-09-16 11:30:19 -0700419/// Call instruction. The call target is captured as getSrc(0), and arg I is
420/// captured as getSrc(I+1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700421class InstCall : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800422 InstCall() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700423 InstCall(const InstCall &) = delete;
424 InstCall &operator=(const InstCall &) = delete;
425
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700426public:
427 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
John Porto5e0a8a72015-11-20 13:50:36 -0800428 Operand *CallTarget, bool HasTailCall,
429 bool IsTargetHelperCall = false) {
Andrew Scull9612d322015-07-06 14:53:25 -0700430 /// Set HasSideEffects to true so that the call instruction can't be
Andrew Scull57e12682015-09-16 11:30:19 -0700431 /// dead-code eliminated. IntrinsicCalls can override this if the particular
432 /// intrinsic is deletable and has no side-effects.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700433 constexpr bool HasSideEffects = true;
434 constexpr InstKind Kind = Inst::Call;
John Porto5e0a8a72015-11-20 13:50:36 -0800435 return new (Func->allocate<InstCall>())
436 InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
437 IsTargetHelperCall, HasSideEffects, Kind);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700438 }
439 void addArg(Operand *Arg) { addSource(Arg); }
440 Operand *getCallTarget() const { return getSrc(0); }
441 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
442 SizeT getNumArgs() const { return getSrcSize() - 1; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700443 bool isTailcall() const { return HasTailCall; }
John Porto5e0a8a72015-11-20 13:50:36 -0800444 bool isTargetHelperCall() const { return IsTargetHelperCall; }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700445 bool isMemoryWrite() const override { return true; }
Jan Voung3ce1a992015-02-03 08:27:44 -0800446 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800447 static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
Karl Schimpf8df26f32014-09-19 09:33:26 -0700448 Type getReturnType() const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700449
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700450protected:
451 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
John Porto5e0a8a72015-11-20 13:50:36 -0800452 bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
453 InstKind Kind)
454 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
455 IsTargetHelperCall(IsTargetHelperCall) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700456 HasSideEffects = HasSideEff;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700457 addSource(CallTarget);
458 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700459
460private:
John Porto5e0a8a72015-11-20 13:50:36 -0800461 const bool HasTailCall;
462 const bool IsTargetHelperCall;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700463};
464
Andrew Scull9612d322015-07-06 14:53:25 -0700465/// Cast instruction (a.k.a. conversion operation).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700466class InstCast : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800467 InstCast() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700468 InstCast(const InstCast &) = delete;
469 InstCast &operator=(const InstCast &) = delete;
470
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700471public:
472 enum OpKind {
473#define X(tag, str) tag,
474 ICEINSTCAST_TABLE
475#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700476 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700477 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700478
Karl Schimpfbf170372014-12-15 10:16:31 -0800479 static const char *getCastName(OpKind Kind);
480
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700481 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
482 Operand *Source) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800483 return new (Func->allocate<InstCast>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700484 InstCast(Func, CastKind, Dest, Source);
485 }
486 OpKind getCastKind() const { return CastKind; }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700487 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700488 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800489 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700490
491private:
492 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
John Porto1bec8bc2015-06-22 10:51:13 -0700493
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700494 const OpKind CastKind;
495};
496
Andrew Scull9612d322015-07-06 14:53:25 -0700497/// ExtractElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700498class InstExtractElement : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800499 InstExtractElement() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700500 InstExtractElement(const InstExtractElement &) = delete;
501 InstExtractElement &operator=(const InstExtractElement &) = delete;
502
Matt Wala49889232014-07-18 12:45:09 -0700503public:
504 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
505 Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800506 return new (Func->allocate<InstExtractElement>())
Matt Wala49889232014-07-18 12:45:09 -0700507 InstExtractElement(Func, Dest, Source1, Source2);
508 }
509
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700510 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700511 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800512 static bool classof(const Inst *Instr) {
513 return Instr->getKind() == ExtractElement;
Matt Wala49889232014-07-18 12:45:09 -0700514 }
515
516private:
517 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
518 Operand *Source2);
Matt Wala49889232014-07-18 12:45:09 -0700519};
520
Andrew Scull57e12682015-09-16 11:30:19 -0700521/// Floating-point comparison instruction. The source operands are captured in
522/// getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700523class InstFcmp : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800524 InstFcmp() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700525 InstFcmp(const InstFcmp &) = delete;
526 InstFcmp &operator=(const InstFcmp &) = delete;
527
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700528public:
529 enum FCond {
530#define X(tag, str) tag,
531 ICEINSTFCMP_TABLE
532#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700533 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700534 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700535
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700536 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
537 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800538 return new (Func->allocate<InstFcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700539 InstFcmp(Func, Condition, Dest, Source1, Source2);
540 }
541 FCond getCondition() const { return Condition; }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700542 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700543 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800544 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700545
546private:
547 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
548 Operand *Source2);
John Porto1bec8bc2015-06-22 10:51:13 -0700549
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700550 const FCond Condition;
551};
552
Andrew Scull57e12682015-09-16 11:30:19 -0700553/// Integer comparison instruction. The source operands are captured in
554/// getSrc(0) and getSrc(1).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700555class InstIcmp : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800556 InstIcmp() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700557 InstIcmp(const InstIcmp &) = delete;
558 InstIcmp &operator=(const InstIcmp &) = delete;
559
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700560public:
561 enum ICond {
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700562#define X(tag, inverse, str) tag,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700563 ICEINSTICMP_TABLE
564#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700565 _num
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700566 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700567
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700568 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
569 Operand *Source1, Operand *Source2) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800570 return new (Func->allocate<InstIcmp>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700571 InstIcmp(Func, Condition, Dest, Source1, Source2);
572 }
573 ICond getCondition() const { return Condition; }
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700574 void reverseConditionAndOperands();
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700575 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700576 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800577 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700578
579private:
580 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
581 Operand *Source2);
John Porto1bec8bc2015-06-22 10:51:13 -0700582
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700583 ICond Condition;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700584};
585
Andrew Scull9612d322015-07-06 14:53:25 -0700586/// InsertElement instruction.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700587class InstInsertElement : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800588 InstInsertElement() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700589 InstInsertElement(const InstInsertElement &) = delete;
590 InstInsertElement &operator=(const InstInsertElement &) = delete;
591
Matt Wala49889232014-07-18 12:45:09 -0700592public:
593 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
594 Operand *Source2, Operand *Source3) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800595 return new (Func->allocate<InstInsertElement>())
Matt Wala49889232014-07-18 12:45:09 -0700596 InstInsertElement(Func, Dest, Source1, Source2, Source3);
597 }
598
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700599 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700600 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800601 static bool classof(const Inst *Instr) {
602 return Instr->getKind() == InsertElement;
Matt Wala49889232014-07-18 12:45:09 -0700603 }
604
605private:
606 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
607 Operand *Source2, Operand *Source3);
Matt Wala49889232014-07-18 12:45:09 -0700608};
609
Andrew Scull57e12682015-09-16 11:30:19 -0700610/// Call to an intrinsic function. The call target is captured as getSrc(0), and
611/// arg I is captured as getSrc(I+1).
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700612class InstIntrinsicCall : public InstCall {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800613 InstIntrinsicCall() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700614 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
615 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
616
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700617public:
618 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
619 Operand *CallTarget,
620 const Intrinsics::IntrinsicInfo &Info) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800621 return new (Func->allocate<InstIntrinsicCall>())
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700622 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
623 }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800624 static bool classof(const Inst *Instr) {
625 return Instr->getKind() == IntrinsicCall;
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700626 }
627
628 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700629 bool isMemoryWrite() const override {
630 return getIntrinsicInfo().IsMemoryWrite;
631 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700632
633private:
634 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
635 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
John Porto5e0a8a72015-11-20 13:50:36 -0800636 : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
637 Info.HasSideEffects, Inst::IntrinsicCall),
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700638 Info(Info) {}
John Porto1bec8bc2015-06-22 10:51:13 -0700639
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700640 const Intrinsics::IntrinsicInfo Info;
641};
642
Andrew Scull57e12682015-09-16 11:30:19 -0700643/// Load instruction. The source address is captured in getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700644class InstLoad : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800645 InstLoad() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700646 InstLoad(const InstLoad &) = delete;
647 InstLoad &operator=(const InstLoad &) = delete;
648
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700649public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700650 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
Jim Stichnothc4554d72014-09-30 16:49:38 -0700651 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700652 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700653 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800654 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700655 }
656 Operand *getSourceAddress() const { return getSrc(0); }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700657 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700658 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800659 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700660
661private:
662 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700663};
664
Andrew Scull57e12682015-09-16 11:30:19 -0700665/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
666/// source operand is getSrc(I).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700667class InstPhi : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800668 InstPhi() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700669 InstPhi(const InstPhi &) = delete;
670 InstPhi &operator=(const InstPhi &) = delete;
671
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700672public:
673 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800674 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700675 }
676 void addArgument(Operand *Source, CfgNode *Label);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700677 Operand *getOperandForTarget(CfgNode *Target) const;
David Sehr263ac522016-04-04 10:11:08 -0700678 void clearOperandForTarget(CfgNode *Target);
Jim Stichnoth98712a32014-10-24 10:59:02 -0700679 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
Eric Holk16f80612016-04-04 17:07:42 -0700680 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700681 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700682 Liveness *Liveness);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700683 Inst *lower(Cfg *Func);
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700684 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700685 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800686 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700687
688private:
689 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700690 void destroy(Cfg *Func) override { Inst::destroy(Func); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700691
Andrew Scull57e12682015-09-16 11:30:19 -0700692 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
693 /// but the Phi instruction is created before InEdges[] is available, so it's
694 /// more complicated to share the list.
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700695 CfgVector<CfgNode *> Labels;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700696};
697
Andrew Scull57e12682015-09-16 11:30:19 -0700698/// Ret instruction. The return value is captured in getSrc(0), but if there is
699/// no return value (void-type function), then getSrcSize()==0 and
700/// hasRetValue()==false.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700701class InstRet : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800702 InstRet() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700703 InstRet(const InstRet &) = delete;
704 InstRet &operator=(const InstRet &) = delete;
705
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700706public:
Jim Stichnothae953202014-12-20 06:17:49 -0800707 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800708 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700709 }
710 bool hasRetValue() const { return getSrcSize(); }
711 Operand *getRetValue() const {
712 assert(hasRetValue());
713 return getSrc(0);
714 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700715 NodeList getTerminatorEdges() const override { return NodeList(); }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700716 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700717 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800718 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700719
720private:
721 InstRet(Cfg *Func, Operand *RetValue);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700722};
723
Andrew Scull9612d322015-07-06 14:53:25 -0700724/// Select instruction. The condition, true, and false operands are captured.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700725class InstSelect : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800726 InstSelect() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700727 InstSelect(const InstSelect &) = delete;
728 InstSelect &operator=(const InstSelect &) = delete;
729
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700730public:
731 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
732 Operand *SourceTrue, Operand *SourceFalse) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800733 return new (Func->allocate<InstSelect>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700734 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
735 }
736 Operand *getCondition() const { return getSrc(0); }
737 Operand *getTrueOperand() const { return getSrc(1); }
738 Operand *getFalseOperand() const { return getSrc(2); }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700739 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700740 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800741 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700742
743private:
744 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
745 Operand *Source2);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700746};
747
Andrew Scull57e12682015-09-16 11:30:19 -0700748/// Store instruction. The address operand is captured, along with the data
749/// operand to be stored into the address.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700750class InstStore : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800751 InstStore() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700752 InstStore(const InstStore &) = delete;
753 InstStore &operator=(const InstStore &) = delete;
754
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700755public:
Karl Schimpf41689df2014-09-10 14:36:07 -0700756 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700757 uint32_t Align = 1) {
Karl Schimpf41689df2014-09-10 14:36:07 -0700758 // TODO(kschimpf) Stop ignoring alignment specification.
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700759 (void)Align;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800760 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700761 }
762 Operand *getAddr() const { return getSrc(1); }
763 Operand *getData() const { return getSrc(0); }
Andrew Scullaa6c1092015-09-03 17:50:30 -0700764 Variable *getRmwBeacon() const;
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700765 void setRmwBeacon(Variable *Beacon);
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700766 bool isMemoryWrite() const override { return true; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700767 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800768 static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700769
770private:
771 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700772};
773
Andrew Scull57e12682015-09-16 11:30:19 -0700774/// Switch instruction. The single source operand is captured as getSrc(0).
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700775class InstSwitch : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800776 InstSwitch() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700777 InstSwitch(const InstSwitch &) = delete;
778 InstSwitch &operator=(const InstSwitch &) = delete;
779
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700780public:
781 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
782 CfgNode *LabelDefault) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800783 return new (Func->allocate<InstSwitch>())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700784 InstSwitch(Func, NumCases, Source, LabelDefault);
785 }
786 Operand *getComparison() const { return getSrc(0); }
787 CfgNode *getLabelDefault() const { return LabelDefault; }
788 SizeT getNumCases() const { return NumCases; }
789 uint64_t getValue(SizeT I) const {
790 assert(I < NumCases);
791 return Values[I];
792 }
793 CfgNode *getLabel(SizeT I) const {
794 assert(I < NumCases);
795 return Labels[I];
796 }
797 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700798 NodeList getTerminatorEdges() const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700799 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700800 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700801 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800802 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700803
804private:
805 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700806 void destroy(Cfg *Func) override {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700807 Func->deallocateArrayOf<uint64_t>(Values);
808 Func->deallocateArrayOf<CfgNode *>(Labels);
809 Inst::destroy(Func);
810 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700811
812 CfgNode *LabelDefault;
Andrew Scull9612d322015-07-06 14:53:25 -0700813 SizeT NumCases; /// not including the default case
814 uint64_t *Values; /// size is NumCases
815 CfgNode **Labels; /// size is NumCases
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700816};
817
Andrew Scull57e12682015-09-16 11:30:19 -0700818/// Unreachable instruction. This is a terminator instruction with no operands.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700819class InstUnreachable : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800820 InstUnreachable() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700821 InstUnreachable(const InstUnreachable &) = delete;
822 InstUnreachable &operator=(const InstUnreachable &) = delete;
823
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700824public:
825 static InstUnreachable *create(Cfg *Func) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800826 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700827 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700828 NodeList getTerminatorEdges() const override { return NodeList(); }
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700829 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700830 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800831 static bool classof(const Inst *Instr) {
832 return Instr->getKind() == Unreachable;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700833 }
834
835private:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800836 explicit InstUnreachable(Cfg *Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700837};
838
Andrew Scull57e12682015-09-16 11:30:19 -0700839/// BundleLock instruction. There are no operands. Contains an option
Andrew Scull9612d322015-07-06 14:53:25 -0700840/// indicating whether align_to_end is specified.
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800841class InstBundleLock : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800842 InstBundleLock() = delete;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800843 InstBundleLock(const InstBundleLock &) = delete;
844 InstBundleLock &operator=(const InstBundleLock &) = delete;
845
846public:
John Porto56958cb2016-01-14 09:18:18 -0800847 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800848 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
849 return new (Func->allocate<InstBundleLock>())
850 InstBundleLock(Func, BundleOption);
851 }
852 void emit(const Cfg *Func) const override;
853 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700854 bool isMemoryWrite() const override { return false; }
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800855 void dump(const Cfg *Func) const override;
856 Option getOption() const { return BundleOption; }
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800857 static bool classof(const Inst *Instr) {
858 return Instr->getKind() == BundleLock;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800859 }
860
861private:
862 Option BundleOption;
863 InstBundleLock(Cfg *Func, Option BundleOption);
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800864};
865
Andrew Scull57e12682015-09-16 11:30:19 -0700866/// BundleUnlock instruction. There are no operands.
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800867class InstBundleUnlock : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800868 InstBundleUnlock() = delete;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800869 InstBundleUnlock(const InstBundleUnlock &) = delete;
870 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
871
872public:
873 static InstBundleUnlock *create(Cfg *Func) {
874 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
875 }
876 void emit(const Cfg *Func) const override;
877 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700878 bool isMemoryWrite() const override { return false; }
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800879 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800880 static bool classof(const Inst *Instr) {
881 return Instr->getKind() == BundleUnlock;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800882 }
883
884private:
885 explicit InstBundleUnlock(Cfg *Func);
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800886};
887
Andrew Scull57e12682015-09-16 11:30:19 -0700888/// FakeDef instruction. This creates a fake definition of a variable, which is
889/// how we represent the case when an instruction produces multiple results.
890/// This doesn't happen with high-level ICE instructions, but might with lowered
891/// instructions. For example, this would be a way to represent condition flags
892/// being modified by an instruction.
Andrew Scull9612d322015-07-06 14:53:25 -0700893///
Andrew Scull57e12682015-09-16 11:30:19 -0700894/// It's generally useful to set the optional source operand to be the dest
895/// variable of the instruction that actually produces the FakeDef dest.
896/// Otherwise, the original instruction could be dead-code eliminated if its
897/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
898/// initialized.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700899class InstFakeDef : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800900 InstFakeDef() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700901 InstFakeDef(const InstFakeDef &) = delete;
902 InstFakeDef &operator=(const InstFakeDef &) = delete;
903
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700904public:
Jim Stichnothae953202014-12-20 06:17:49 -0800905 static InstFakeDef *create(Cfg *Func, Variable *Dest,
906 Variable *Src = nullptr) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800907 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700908 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700909 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700910 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700911 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700912 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800913 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700914
915private:
916 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700917};
918
Andrew Scull57e12682015-09-16 11:30:19 -0700919/// FakeUse instruction. This creates a fake use of a variable, to keep the
920/// instruction that produces that variable from being dead-code eliminated.
921/// This is useful in a variety of lowering situations. The FakeUse instruction
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800922/// has no dest, so it can itself never be dead-code eliminated. A weight can
923/// be provided to provide extra bias to the register allocator - for simplicity
924/// of implementation, weight=N is handled by holding N copies of the variable
925/// as source operands.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700926class InstFakeUse : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800927 InstFakeUse() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700928 InstFakeUse(const InstFakeUse &) = delete;
929 InstFakeUse &operator=(const InstFakeUse &) = delete;
930
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700931public:
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800932 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
933 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700934 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700935 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700936 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700937 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700938 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800939 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700940
941private:
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800942 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700943};
944
Andrew Scull57e12682015-09-16 11:30:19 -0700945/// FakeKill instruction. This "kills" a set of variables by modeling a trivial
946/// live range at this instruction for each (implicit) variable. The primary use
947/// is to indicate that scratch registers are killed after a call, so that the
948/// register allocator won't assign a scratch register to a variable whose live
949/// range spans a call.
Andrew Scull9612d322015-07-06 14:53:25 -0700950///
Andrew Scull57e12682015-09-16 11:30:19 -0700951/// The FakeKill instruction also holds a pointer to the instruction that kills
952/// the set of variables, so that if that linked instruction gets dead-code
953/// eliminated, the FakeKill instruction will as well.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700954class InstFakeKill : public InstHighLevel {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800955 InstFakeKill() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700956 InstFakeKill(const InstFakeKill &) = delete;
957 InstFakeKill &operator=(const InstFakeKill &) = delete;
958
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700959public:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800960 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800961 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700962 }
963 const Inst *getLinked() const { return Linked; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700964 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700965 void emitIAS(const Cfg * /* Func */) const override {}
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700966 bool isMemoryWrite() const override { return false; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700967 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800968 static bool classof(const Inst *Instr) {
969 return Instr->getKind() == FakeKill;
970 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700971
972private:
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800973 InstFakeKill(Cfg *Func, const Inst *Linked);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700974
Andrew Scull9612d322015-07-06 14:53:25 -0700975 /// This instruction is ignored if Linked->isDeleted() is true.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700976 const Inst *Linked;
977};
978
John Portoa47c11c2016-04-21 05:53:42 -0700979/// ShuffleVector instruction. This represents a shuffle operation on vector
980/// types. This instruction is not part of the PNaCl bitcode: it is generated
981/// by Subzero when it matches the pattern used by pnacl-clang when compiling
982/// to bitcode.
983class InstShuffleVector : public InstHighLevel {
984 InstShuffleVector() = delete;
985 InstShuffleVector(const InstShuffleVector &) = delete;
986 InstShuffleVector &operator=(const InstShuffleVector &) = delete;
987
988public:
Nicolas Capens579b1b32016-12-09 14:56:03 -0500989 static InstShuffleVector *create(Cfg *Func, Variable *Dest, Operand *Src0,
990 Operand *Src1) {
John Portoa47c11c2016-04-21 05:53:42 -0700991 return new (Func->allocate<InstShuffleVector>())
992 InstShuffleVector(Func, Dest, Src0, Src1);
993 }
994
995 SizeT getNumIndexes() const { return NumIndexes; }
996
997 void addIndex(ConstantInteger32 *Index) {
998 assert(CurrentIndex < NumIndexes);
999 Indexes[CurrentIndex++] = Index;
1000 }
1001
1002 ConstantInteger32 *getIndex(SizeT Pos) const {
1003 assert(Pos < NumIndexes);
1004 return Indexes[Pos];
1005 }
1006
Nicolas Capensf6951fa2017-10-02 10:44:03 -04001007 int32_t getIndexValue(SizeT Pos) const { return getIndex(Pos)->getValue(); }
1008
1009 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3) const {
1010 static constexpr SizeT ExpectedNumElements = 4;
1011 assert(ExpectedNumElements == getNumIndexes());
1012 (void)ExpectedNumElements;
1013
1014 return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
1015 getIndexValue(2) == i2 && getIndexValue(3) == i3;
1016 }
1017
1018 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
1019 int32_t i5, int32_t i6, int32_t i7) const {
Nicolas Capens1448d952016-10-14 16:37:09 -04001020 static constexpr SizeT ExpectedNumElements = 8;
1021 assert(ExpectedNumElements == getNumIndexes());
1022 (void)ExpectedNumElements;
1023
Nicolas Capensf6951fa2017-10-02 10:44:03 -04001024 return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
1025 getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
1026 getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
1027 getIndexValue(6) == i6 && getIndexValue(7) == i7;
Nicolas Capens1448d952016-10-14 16:37:09 -04001028 }
1029
Nicolas Capensf6951fa2017-10-02 10:44:03 -04001030 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
1031 int32_t i5, int32_t i6, int32_t i7, int32_t i8, int32_t i9,
1032 int32_t i10, int32_t i11, int32_t i12, int32_t i13,
1033 int32_t i14, int32_t i15) const {
Nicolas Capens1448d952016-10-14 16:37:09 -04001034 static constexpr SizeT ExpectedNumElements = 16;
1035 assert(ExpectedNumElements == getNumIndexes());
1036 (void)ExpectedNumElements;
1037
Nicolas Capensf6951fa2017-10-02 10:44:03 -04001038 return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
1039 getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
1040 getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
1041 getIndexValue(6) == i6 && getIndexValue(7) == i7 &&
1042 getIndexValue(8) == i8 && getIndexValue(9) == i9 &&
1043 getIndexValue(10) == i10 && getIndexValue(11) == i11 &&
1044 getIndexValue(12) == i12 && getIndexValue(13) == i13 &&
1045 getIndexValue(14) == i14 && getIndexValue(15) == i15;
Nicolas Capens1448d952016-10-14 16:37:09 -04001046 }
1047
Jim Stichnothcd261e92016-04-21 17:57:56 -07001048 bool isMemoryWrite() const override { return false; }
John Portoa47c11c2016-04-21 05:53:42 -07001049 void dump(const Cfg *Func) const override;
1050 static bool classof(const Inst *Instr) {
1051 return Instr->getKind() == ShuffleVector;
1052 }
1053
1054private:
Nicolas Capens579b1b32016-12-09 14:56:03 -05001055 InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1);
John Portoa47c11c2016-04-21 05:53:42 -07001056
1057 void destroy(Cfg *Func) override {
1058 Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
1059 Inst::destroy(Func);
1060 }
1061
1062 ConstantInteger32 **Indexes;
1063 SizeT CurrentIndex = 0;
1064 const SizeT NumIndexes;
1065};
1066
Andrew Scull57e12682015-09-16 11:30:19 -07001067/// JumpTable instruction. This represents a jump table that will be stored in
1068/// the .rodata section. This is used to track and repoint the target CfgNodes
1069/// which may change, for example due to splitting for phi lowering.
Andrew Scull87f80c12015-07-20 10:19:16 -07001070class InstJumpTable : public InstHighLevel {
1071 InstJumpTable() = delete;
1072 InstJumpTable(const InstJumpTable &) = delete;
1073 InstJumpTable &operator=(const InstJumpTable &) = delete;
1074
1075public:
1076 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
1077 return new (Func->allocate<InstJumpTable>())
1078 InstJumpTable(Func, NumTargets, Default);
1079 }
Andrew Scull87f80c12015-07-20 10:19:16 -07001080 void addTarget(SizeT TargetIndex, CfgNode *Target) {
1081 assert(TargetIndex < NumTargets);
1082 Targets[TargetIndex] = Target;
1083 }
1084 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Andrew Scull86df4e92015-07-30 13:54:44 -07001085 SizeT getId() const { return Id; }
1086 SizeT getNumTargets() const { return NumTargets; }
1087 CfgNode *getTarget(SizeT I) const {
1088 assert(I < NumTargets);
1089 return Targets[I];
1090 }
Jim Stichnothf1f773d2016-04-21 16:54:33 -07001091 bool isMemoryWrite() const override { return false; }
Andrew Scull87f80c12015-07-20 10:19:16 -07001092 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001093 static bool classof(const Inst *Instr) {
1094 return Instr->getKind() == JumpTable;
1095 }
John Porto03077212016-04-05 06:30:21 -07001096 // Creates a JumpTableData struct (used for ELF emission) that represents this
1097 // InstJumpTable.
1098 JumpTableData toJumpTableData(Assembler *Asm) const;
Andrew Scull87f80c12015-07-20 10:19:16 -07001099
John Porto03077212016-04-05 06:30:21 -07001100 // InstJumpTable is just a placeholder for the switch targets, and it does not
1101 // need to emit any code, so we redefine emit and emitIAS to do nothing.
1102 void emit(const Cfg *) const override {}
1103 void emitIAS(const Cfg * /* Func */) const override {}
1104
1105 const std::string getName() const {
1106 assert(Name.hasStdString());
1107 return Name.toString();
1108 }
1109
1110 std::string getSectionName() const {
1111 return JumpTableData::createSectionName(FuncName);
Andrew Scull86df4e92015-07-30 13:54:44 -07001112 }
1113
Andrew Scull87f80c12015-07-20 10:19:16 -07001114private:
1115 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
1116 void destroy(Cfg *Func) override {
1117 Func->deallocateArrayOf<CfgNode *>(Targets);
1118 Inst::destroy(Func);
1119 }
1120
Andrew Scull86df4e92015-07-30 13:54:44 -07001121 const SizeT Id;
Andrew Scull87f80c12015-07-20 10:19:16 -07001122 const SizeT NumTargets;
1123 CfgNode **Targets;
John Porto03077212016-04-05 06:30:21 -07001124 GlobalString Name; // This JumpTable's name in the output.
1125 GlobalString FuncName;
Andrew Scull87f80c12015-07-20 10:19:16 -07001126};
1127
Eric Holk67c7c412016-04-15 13:05:37 -07001128/// This instruction inserts an unconditional breakpoint.
1129///
1130/// On x86, this assembles into an INT 3 instruction.
1131///
1132/// This instruction is primarily meant for debugging the code generator.
1133class InstBreakpoint : public InstHighLevel {
1134public:
1135 InstBreakpoint() = delete;
1136 InstBreakpoint(const InstBreakpoint &) = delete;
1137 InstBreakpoint &operator=(const InstBreakpoint &) = delete;
1138
Jim Stichnothf1f773d2016-04-21 16:54:33 -07001139 explicit InstBreakpoint(Cfg *Func);
1140 bool isMemoryWrite() const override { return false; }
Eric Holk67c7c412016-04-15 13:05:37 -07001141
1142public:
1143 static InstBreakpoint *create(Cfg *Func) {
1144 return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
1145 }
1146
1147 static bool classof(const Inst *Instr) {
1148 return Instr->getKind() == Breakpoint;
1149 }
1150};
1151
Andrew Scull9612d322015-07-06 14:53:25 -07001152/// The Target instruction is the base class for all target-specific
1153/// instructions.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001154class InstTarget : public Inst {
Jim Stichnothc6ead202015-02-24 09:30:30 -08001155 InstTarget() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -07001156 InstTarget(const InstTarget &) = delete;
1157 InstTarget &operator=(const InstTarget &) = delete;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001158
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001159public:
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001160 uint32_t getEmitInstCount() const override { return 1; }
Jim Stichnothf1f773d2016-04-21 16:54:33 -07001161 bool isMemoryWrite() const override {
1162 return true; // conservative answer
1163 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001164 void dump(const Cfg *Func) const override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001165 static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001166
1167protected:
1168 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
1169 : Inst(Func, Kind, MaxSrcs, Dest) {
1170 assert(Kind >= Target);
Andrew Scull6ef79492015-09-09 15:50:42 -07001171 assert(Kind <= Target_Max);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001172 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001173};
1174
Jan Voungb3401d22015-05-18 09:38:21 -07001175bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
1176
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001177} // end of namespace Ice
1178
Jim Stichnoth8b21cc52016-08-29 10:15:18 -07001179#ifdef PNACL_LLVM
Jim Stichnothdddaf9c2014-12-04 14:09:21 -08001180namespace llvm {
1181
Andrew Scull57e12682015-09-16 11:30:19 -07001182/// Override the default ilist traits so that Inst's private ctor and deleted
1183/// dtor aren't invoked.
Jim Stichnoth607e9f02014-11-06 13:32:05 -08001184template <>
Jim Stichnothdddaf9c2014-12-04 14:09:21 -08001185struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
Jim Stichnoth607e9f02014-11-06 13:32:05 -08001186 Ice::Inst *createSentinel() const {
1187 return static_cast<Ice::Inst *>(&Sentinel);
1188 }
1189 static void destroySentinel(Ice::Inst *) {}
1190 Ice::Inst *provideInitialHead() const { return createSentinel(); }
1191 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
1192 static void noteHead(Ice::Inst *, Ice::Inst *) {}
1193 void deleteNode(Ice::Inst *) {}
1194
1195private:
1196 mutable ilist_half_node<Ice::Inst> Sentinel;
1197};
1198
Jim Stichnothdddaf9c2014-12-04 14:09:21 -08001199} // end of namespace llvm
Jim Stichnoth8b21cc52016-08-29 10:15:18 -07001200#endif // PNACL_LLVM
Jim Stichnothdddaf9c2014-12-04 14:09:21 -08001201
Jim Stichnothf5fdd232016-05-09 12:24:36 -07001202namespace Ice {
1203
1204inline InstList::iterator instToIterator(Inst *Instr) {
1205#ifdef PNACL_LLVM
1206 return Instr;
Jim Stichnotha5b16ab2016-05-10 11:20:41 -07001207#else // !PNACL_LLVM
Jim Stichnothf5fdd232016-05-09 12:24:36 -07001208 return Instr->getIterator();
1209#endif // !PNACL_LLVM
1210}
1211
Jim Stichnotha5b16ab2016-05-10 11:20:41 -07001212inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; }
Jim Stichnothf5fdd232016-05-09 12:24:36 -07001213
1214inline const Inst *iteratorToInst(InstList::const_iterator Iter) {
1215 return &*Iter;
1216}
1217
Jim Stichnoth7c9728f2016-08-31 13:42:00 -07001218inline InstList::iterator
1219reverseToForwardIterator(InstList::reverse_iterator RI) {
1220#ifdef PNACL_LLVM
1221 return RI.base();
1222#else // !PNACL_LLVM
1223 return ++RI.getReverse();
1224#endif // !PNACL_LLVM
1225}
1226
Jim Stichnothf5fdd232016-05-09 12:24:36 -07001227} // end of namespace Ice
1228
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001229#endif // SUBZERO_SRC_ICEINST_H