xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceInst.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the Inst class and its target-independent subclasses.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker /// These represent the high-level Vanilla ICE instructions and map roughly 1:1
14*03ce13f7SAndroid Build Coastguard Worker /// to LLVM instructions.
15*03ce13f7SAndroid Build Coastguard Worker ///
16*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEINST_H
19*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEINST_H
20*03ce13f7SAndroid Build Coastguard Worker 
21*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceInst.def"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceIntrinsics.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "IceSwitchLowering.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h"
28*03ce13f7SAndroid Build Coastguard Worker 
29*03ce13f7SAndroid Build Coastguard Worker // TODO: The Cfg structure, and instructions in particular, need to be
30*03ce13f7SAndroid Build Coastguard Worker // validated for things like valid operand types, valid branch targets, proper
31*03ce13f7SAndroid Build Coastguard Worker // ordering of Phi and non-Phi instructions, etc. Most of the validity checking
32*03ce13f7SAndroid Build Coastguard Worker // will be done in the bitcode reader. We need a list of everything that should
33*03ce13f7SAndroid Build Coastguard Worker // be validated, and tests for each.
34*03ce13f7SAndroid Build Coastguard Worker 
35*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
36*03ce13f7SAndroid Build Coastguard Worker 
37*03ce13f7SAndroid Build Coastguard Worker /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
38*03ce13f7SAndroid Build Coastguard Worker /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
39*03ce13f7SAndroid Build Coastguard Worker /// low-level (target-specific) ICE instructions inherit from InstTarget.
40*03ce13f7SAndroid Build Coastguard Worker class Inst : public llvm::ilist_node<Inst> {
41*03ce13f7SAndroid Build Coastguard Worker   Inst() = delete;
42*03ce13f7SAndroid Build Coastguard Worker   Inst(const Inst &) = delete;
43*03ce13f7SAndroid Build Coastguard Worker   Inst &operator=(const Inst &) = delete;
44*03ce13f7SAndroid Build Coastguard Worker 
45*03ce13f7SAndroid Build Coastguard Worker public:
46*03ce13f7SAndroid Build Coastguard Worker   enum InstKind {
47*03ce13f7SAndroid Build Coastguard Worker     // Arbitrary (alphabetical) order, except put Unreachable first.
48*03ce13f7SAndroid Build Coastguard Worker     Unreachable,
49*03ce13f7SAndroid Build Coastguard Worker     Alloca,
50*03ce13f7SAndroid Build Coastguard Worker     Arithmetic,
51*03ce13f7SAndroid Build Coastguard Worker     Br,
52*03ce13f7SAndroid Build Coastguard Worker     Call,
53*03ce13f7SAndroid Build Coastguard Worker     Cast,
54*03ce13f7SAndroid Build Coastguard Worker     ExtractElement,
55*03ce13f7SAndroid Build Coastguard Worker     Fcmp,
56*03ce13f7SAndroid Build Coastguard Worker     Icmp,
57*03ce13f7SAndroid Build Coastguard Worker     Intrinsic,
58*03ce13f7SAndroid Build Coastguard Worker     InsertElement,
59*03ce13f7SAndroid Build Coastguard Worker     Load,
60*03ce13f7SAndroid Build Coastguard Worker     Phi,
61*03ce13f7SAndroid Build Coastguard Worker     Ret,
62*03ce13f7SAndroid Build Coastguard Worker     Select,
63*03ce13f7SAndroid Build Coastguard Worker     Store,
64*03ce13f7SAndroid Build Coastguard Worker     Switch,
65*03ce13f7SAndroid Build Coastguard Worker     Assign,        // not part of LLVM/PNaCl bitcode
66*03ce13f7SAndroid Build Coastguard Worker     Breakpoint,    // not part of LLVM/PNaCl bitcode
67*03ce13f7SAndroid Build Coastguard Worker     FakeDef,       // not part of LLVM/PNaCl bitcode
68*03ce13f7SAndroid Build Coastguard Worker     FakeUse,       // not part of LLVM/PNaCl bitcode
69*03ce13f7SAndroid Build Coastguard Worker     FakeKill,      // not part of LLVM/PNaCl bitcode
70*03ce13f7SAndroid Build Coastguard Worker     JumpTable,     // not part of LLVM/PNaCl bitcode
71*03ce13f7SAndroid Build Coastguard Worker     ShuffleVector, // not part of LLVM/PNaCl bitcode
72*03ce13f7SAndroid Build Coastguard Worker     // Anything >= Target is an InstTarget subclass. Note that the value-spaces
73*03ce13f7SAndroid Build Coastguard Worker     // are shared across targets. To avoid confusion over the definition of
74*03ce13f7SAndroid Build Coastguard Worker     // shared values, an object specific to one target should never be passed
75*03ce13f7SAndroid Build Coastguard Worker     // to a different target.
76*03ce13f7SAndroid Build Coastguard Worker     Target,
77*03ce13f7SAndroid Build Coastguard Worker     Target_Max = std::numeric_limits<uint8_t>::max(),
78*03ce13f7SAndroid Build Coastguard Worker   };
79*03ce13f7SAndroid Build Coastguard Worker   static_assert(Target <= Target_Max, "Must not be above max.");
getKind()80*03ce13f7SAndroid Build Coastguard Worker   InstKind getKind() const { return Kind; }
81*03ce13f7SAndroid Build Coastguard Worker   virtual const char *getInstName() const;
82*03ce13f7SAndroid Build Coastguard Worker 
getNumber()83*03ce13f7SAndroid Build Coastguard Worker   InstNumberT getNumber() const { return Number; }
84*03ce13f7SAndroid Build Coastguard Worker   void renumber(Cfg *Func);
85*03ce13f7SAndroid Build Coastguard Worker   enum {
86*03ce13f7SAndroid Build Coastguard Worker     NumberDeleted = -1,
87*03ce13f7SAndroid Build Coastguard Worker     NumberSentinel = 0,
88*03ce13f7SAndroid Build Coastguard Worker     NumberInitial = 2,
89*03ce13f7SAndroid Build Coastguard Worker     NumberExtended = NumberInitial - 1
90*03ce13f7SAndroid Build Coastguard Worker   };
91*03ce13f7SAndroid Build Coastguard Worker 
isDeleted()92*03ce13f7SAndroid Build Coastguard Worker   bool isDeleted() const { return Deleted; }
setDeleted()93*03ce13f7SAndroid Build Coastguard Worker   void setDeleted() { Deleted = true; }
94*03ce13f7SAndroid Build Coastguard Worker   void setDead(bool Value = true) { Dead = Value; }
95*03ce13f7SAndroid Build Coastguard Worker   void deleteIfDead();
96*03ce13f7SAndroid Build Coastguard Worker 
hasSideEffects()97*03ce13f7SAndroid Build Coastguard Worker   bool hasSideEffects() const { return HasSideEffects; }
98*03ce13f7SAndroid Build Coastguard Worker 
isDestRedefined()99*03ce13f7SAndroid Build Coastguard Worker   bool isDestRedefined() const { return IsDestRedefined; }
setDestRedefined()100*03ce13f7SAndroid Build Coastguard Worker   void setDestRedefined() { IsDestRedefined = true; }
101*03ce13f7SAndroid Build Coastguard Worker 
getDest()102*03ce13f7SAndroid Build Coastguard Worker   Variable *getDest() const { return Dest; }
103*03ce13f7SAndroid Build Coastguard Worker 
getSrcSize()104*03ce13f7SAndroid Build Coastguard Worker   SizeT getSrcSize() const { return Srcs.size(); }
getSrc(SizeT I)105*03ce13f7SAndroid Build Coastguard Worker   Operand *getSrc(SizeT I) const {
106*03ce13f7SAndroid Build Coastguard Worker     assert(I < getSrcSize());
107*03ce13f7SAndroid Build Coastguard Worker     return Srcs[I];
108*03ce13f7SAndroid Build Coastguard Worker   }
replaceSource(SizeT Index,Operand * Replacement)109*03ce13f7SAndroid Build Coastguard Worker   void replaceSource(SizeT Index, Operand *Replacement) {
110*03ce13f7SAndroid Build Coastguard Worker     assert(Index < getSrcSize());
111*03ce13f7SAndroid Build Coastguard Worker     assert(!isDeleted());
112*03ce13f7SAndroid Build Coastguard Worker     Srcs[Index] = Replacement;
113*03ce13f7SAndroid Build Coastguard Worker   }
114*03ce13f7SAndroid Build Coastguard Worker   // Instructions which load data take their address in Src[0], while
115*03ce13f7SAndroid Build Coastguard Worker   // store instructions use Src[1] for the address and Src[0] for the data.
getLoadAddress()116*03ce13f7SAndroid Build Coastguard Worker   Operand *getLoadAddress() const { return getSrc(0); }
getStoreAddress()117*03ce13f7SAndroid Build Coastguard Worker   Operand *getStoreAddress() const { return getSrc(1); }
getData()118*03ce13f7SAndroid Build Coastguard Worker   Operand *getData() const { return getSrc(0); }
119*03ce13f7SAndroid Build Coastguard Worker 
120*03ce13f7SAndroid Build Coastguard Worker   bool isLastUse(const Operand *Src) const;
121*03ce13f7SAndroid Build Coastguard Worker   void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
122*03ce13f7SAndroid Build Coastguard Worker 
123*03ce13f7SAndroid Build Coastguard Worker   /// Returns a list of out-edges corresponding to a terminator instruction,
124*03ce13f7SAndroid Build Coastguard Worker   /// which is the last instruction of the block. The list must not contain
125*03ce13f7SAndroid Build Coastguard Worker   /// duplicates.
getTerminatorEdges()126*03ce13f7SAndroid Build Coastguard Worker   virtual NodeList getTerminatorEdges() const {
127*03ce13f7SAndroid Build Coastguard Worker     // All valid terminator instructions override this method. For the default
128*03ce13f7SAndroid Build Coastguard Worker     // implementation, we assert in case some CfgNode is constructed without a
129*03ce13f7SAndroid Build Coastguard Worker     // terminator instruction at the end.
130*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable(
131*03ce13f7SAndroid Build Coastguard Worker         "getTerminatorEdges() called on a non-terminator instruction");
132*03ce13f7SAndroid Build Coastguard Worker     return NodeList();
133*03ce13f7SAndroid Build Coastguard Worker   }
isUnconditionalBranch()134*03ce13f7SAndroid Build Coastguard Worker   virtual bool isUnconditionalBranch() const { return false; }
135*03ce13f7SAndroid Build Coastguard Worker   /// If the instruction is a branch-type instruction with OldNode as a target,
136*03ce13f7SAndroid Build Coastguard Worker   /// repoint it to NewNode and return true, otherwise return false. Repoint all
137*03ce13f7SAndroid Build Coastguard Worker   /// instances of OldNode as a target.
repointEdges(CfgNode * OldNode,CfgNode * NewNode)138*03ce13f7SAndroid Build Coastguard Worker   virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
139*03ce13f7SAndroid Build Coastguard Worker     (void)OldNode;
140*03ce13f7SAndroid Build Coastguard Worker     (void)NewNode;
141*03ce13f7SAndroid Build Coastguard Worker     return false;
142*03ce13f7SAndroid Build Coastguard Worker   }
143*03ce13f7SAndroid Build Coastguard Worker 
144*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if the instruction is equivalent to a simple
145*03ce13f7SAndroid Build Coastguard Worker   /// "var_dest=var_src" assignment where the dest and src are both variables.
isVarAssign()146*03ce13f7SAndroid Build Coastguard Worker   virtual bool isVarAssign() const { return false; }
147*03ce13f7SAndroid Build Coastguard Worker 
148*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if the instruction has a possible side effect of changing
149*03ce13f7SAndroid Build Coastguard Worker   /// memory, in which case a memory load should not be reordered with respect
150*03ce13f7SAndroid Build Coastguard Worker   /// to this instruction.  It should really be pure virtual, but we can't
151*03ce13f7SAndroid Build Coastguard Worker   /// because of g++ and llvm::ilist<>, so we implement it as
152*03ce13f7SAndroid Build Coastguard Worker   /// report_fatal_error().
153*03ce13f7SAndroid Build Coastguard Worker   virtual bool isMemoryWrite() const;
154*03ce13f7SAndroid Build Coastguard Worker 
155*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if the (target-specific) instruction represents an
156*03ce13f7SAndroid Build Coastguard Worker   /// intra-block label, i.e. branch target.  This is meant primarily for
157*03ce13f7SAndroid Build Coastguard Worker   /// Cfg::splitLocalVars().
isLabel()158*03ce13f7SAndroid Build Coastguard Worker   virtual bool isLabel() const { return false; }
159*03ce13f7SAndroid Build Coastguard Worker   /// If the (target-specific) instruction represents an intra-block branch to
160*03ce13f7SAndroid Build Coastguard Worker   /// some Label instruction, return that Label branch target instruction;
161*03ce13f7SAndroid Build Coastguard Worker   /// otherwise return nullptr.
getIntraBlockBranchTarget()162*03ce13f7SAndroid Build Coastguard Worker   virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; }
163*03ce13f7SAndroid Build Coastguard Worker 
164*03ce13f7SAndroid Build Coastguard Worker   void livenessLightweight(Cfg *Func, LivenessBV &Live);
165*03ce13f7SAndroid Build Coastguard Worker   /// Calculates liveness for this instruction. Returns true if this instruction
166*03ce13f7SAndroid Build Coastguard Worker   /// is (tentatively) still live and should be retained, and false if this
167*03ce13f7SAndroid Build Coastguard Worker   /// instruction is (tentatively) dead and should be deleted. The decision is
168*03ce13f7SAndroid Build Coastguard Worker   /// tentative until the liveness dataflow algorithm has converged, and then a
169*03ce13f7SAndroid Build Coastguard Worker   /// separate pass permanently deletes dead instructions.
170*03ce13f7SAndroid Build Coastguard Worker   bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
171*03ce13f7SAndroid Build Coastguard Worker                 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
172*03ce13f7SAndroid Build Coastguard Worker 
173*03ce13f7SAndroid Build Coastguard Worker   /// Get the number of native instructions that this instruction ultimately
174*03ce13f7SAndroid Build Coastguard Worker   /// emits. By default, high-level instructions don't result in any native
175*03ce13f7SAndroid Build Coastguard Worker   /// instructions, and a target-specific instruction results in a single native
176*03ce13f7SAndroid Build Coastguard Worker   /// instruction.
getEmitInstCount()177*03ce13f7SAndroid Build Coastguard Worker   virtual uint32_t getEmitInstCount() const { return 0; }
178*03ce13f7SAndroid Build Coastguard Worker   // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
179*03ce13f7SAndroid Build Coastguard Worker   // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
180*03ce13f7SAndroid Build Coastguard Worker   // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
181*03ce13f7SAndroid Build Coastguard Worker   // allow the abstract class Ice::Inst. The method should be declared
182*03ce13f7SAndroid Build Coastguard Worker   // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
183*03ce13f7SAndroid Build Coastguard Worker   // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
emit(const Cfg *)184*03ce13f7SAndroid Build Coastguard Worker   virtual void emit(const Cfg *) const {
185*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable("emit on abstract class");
186*03ce13f7SAndroid Build Coastguard Worker   }
emitIAS(const Cfg * Func)187*03ce13f7SAndroid Build Coastguard Worker   virtual void emitIAS(const Cfg *Func) const { emit(Func); }
188*03ce13f7SAndroid Build Coastguard Worker   virtual void dump(const Cfg *Func) const;
189*03ce13f7SAndroid Build Coastguard Worker   virtual void dumpExtras(const Cfg *Func) const;
190*03ce13f7SAndroid Build Coastguard Worker   void dumpDecorated(const Cfg *Func) const;
191*03ce13f7SAndroid Build Coastguard Worker   void emitSources(const Cfg *Func) const;
192*03ce13f7SAndroid Build Coastguard Worker   void dumpSources(const Cfg *Func) const;
193*03ce13f7SAndroid Build Coastguard Worker   void dumpDest(const Cfg *Func) const;
isRedundantAssign()194*03ce13f7SAndroid Build Coastguard Worker   virtual bool isRedundantAssign() const { return false; }
195*03ce13f7SAndroid Build Coastguard Worker 
196*03ce13f7SAndroid Build Coastguard Worker   virtual ~Inst() = default;
replaceDest(Variable * Var)197*03ce13f7SAndroid Build Coastguard Worker   void replaceDest(Variable *Var) { Dest = Var; }
198*03ce13f7SAndroid Build Coastguard Worker 
delete(void * Ptr,std::size_t Size)199*03ce13f7SAndroid Build Coastguard Worker   void operator delete(void *Ptr, std::size_t Size) {
200*03ce13f7SAndroid Build Coastguard Worker     assert(CfgAllocatorTraits::current() != nullptr);
201*03ce13f7SAndroid Build Coastguard Worker     CfgAllocatorTraits::current()->Deallocate(Ptr, Size);
202*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Inst unexpectedly deleted");
203*03ce13f7SAndroid Build Coastguard Worker   }
204*03ce13f7SAndroid Build Coastguard Worker 
getExternalData()205*03ce13f7SAndroid Build Coastguard Worker   inline void *getExternalData() const { return externalData; }
setExternalData(void * data)206*03ce13f7SAndroid Build Coastguard Worker   inline void setExternalData(void *data) { externalData = data; }
207*03ce13f7SAndroid Build Coastguard Worker 
208*03ce13f7SAndroid Build Coastguard Worker protected:
209*03ce13f7SAndroid Build Coastguard Worker   Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
addSource(Operand * Src)210*03ce13f7SAndroid Build Coastguard Worker   void addSource(Operand *Src) {
211*03ce13f7SAndroid Build Coastguard Worker     assert(Src);
212*03ce13f7SAndroid Build Coastguard Worker     Srcs.push_back(Src);
213*03ce13f7SAndroid Build Coastguard Worker   }
setLastUse(SizeT VarIndex)214*03ce13f7SAndroid Build Coastguard Worker   void setLastUse(SizeT VarIndex) {
215*03ce13f7SAndroid Build Coastguard Worker     if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
216*03ce13f7SAndroid Build Coastguard Worker       LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
217*03ce13f7SAndroid Build Coastguard Worker   }
resetLastUses()218*03ce13f7SAndroid Build Coastguard Worker   void resetLastUses() { LiveRangesEnded = 0; }
219*03ce13f7SAndroid Build Coastguard Worker   /// The destroy() method lets the instruction cleanly release any memory that
220*03ce13f7SAndroid Build Coastguard Worker   /// was allocated via the Cfg's allocator.
destroy(Cfg *)221*03ce13f7SAndroid Build Coastguard Worker   virtual void destroy(Cfg *) {}
222*03ce13f7SAndroid Build Coastguard Worker 
223*03ce13f7SAndroid Build Coastguard Worker   const InstKind Kind;
224*03ce13f7SAndroid Build Coastguard Worker   /// Number is the instruction number for describing live ranges.
225*03ce13f7SAndroid Build Coastguard Worker   InstNumberT Number;
226*03ce13f7SAndroid Build Coastguard Worker   /// Deleted means irrevocably deleted.
227*03ce13f7SAndroid Build Coastguard Worker   bool Deleted = false;
228*03ce13f7SAndroid Build Coastguard Worker   /// Dead means one of two things depending on context: (1) pending deletion
229*03ce13f7SAndroid Build Coastguard Worker   /// after liveness analysis converges, or (2) marked for deletion during
230*03ce13f7SAndroid Build Coastguard Worker   /// lowering due to a folded bool operation.
231*03ce13f7SAndroid Build Coastguard Worker   bool Dead = false;
232*03ce13f7SAndroid Build Coastguard Worker   /// HasSideEffects means the instruction is something like a function call or
233*03ce13f7SAndroid Build Coastguard Worker   /// a volatile load that can't be removed even if its Dest variable is not
234*03ce13f7SAndroid Build Coastguard Worker   /// live.
235*03ce13f7SAndroid Build Coastguard Worker   bool HasSideEffects = false;
236*03ce13f7SAndroid Build Coastguard Worker   /// IsDestRedefined indicates that this instruction is not the first
237*03ce13f7SAndroid Build Coastguard Worker   /// definition of Dest in the basic block.  The effect is that liveness
238*03ce13f7SAndroid Build Coastguard Worker   /// analysis shouldn't consider this instruction to be the start of Dest's
239*03ce13f7SAndroid Build Coastguard Worker   /// live range; rather, there is some other instruction earlier in the basic
240*03ce13f7SAndroid Build Coastguard Worker   /// block with the same Dest.  This is maintained because liveness analysis
241*03ce13f7SAndroid Build Coastguard Worker   /// has an invariant (primarily for performance reasons) that any Variable's
242*03ce13f7SAndroid Build Coastguard Worker   /// live range recorded in a basic block has at most one start and at most one
243*03ce13f7SAndroid Build Coastguard Worker   /// end.
244*03ce13f7SAndroid Build Coastguard Worker   bool IsDestRedefined = false;
245*03ce13f7SAndroid Build Coastguard Worker   /// External data can be set by an optimizer to compute and retain any
246*03ce13f7SAndroid Build Coastguard Worker   /// information related to the current instruction. All the memory used to
247*03ce13f7SAndroid Build Coastguard Worker   /// store this information must be managed by the optimizer.
248*03ce13f7SAndroid Build Coastguard Worker   void *externalData = nullptr;
249*03ce13f7SAndroid Build Coastguard Worker 
250*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest;
251*03ce13f7SAndroid Build Coastguard Worker   const SizeT MaxSrcs; // only used for assert
252*03ce13f7SAndroid Build Coastguard Worker 
253*03ce13f7SAndroid Build Coastguard Worker   CfgVector<Operand *> Srcs;
254*03ce13f7SAndroid Build Coastguard Worker 
255*03ce13f7SAndroid Build Coastguard Worker   /// LiveRangesEnded marks which Variables' live ranges end in this
256*03ce13f7SAndroid Build Coastguard Worker   /// instruction. An instruction can have an arbitrary number of source
257*03ce13f7SAndroid Build Coastguard Worker   /// operands (e.g. a call instruction), and each source operand can contain 0
258*03ce13f7SAndroid Build Coastguard Worker   /// or 1 Variable (and target-specific operands could contain more than 1
259*03ce13f7SAndroid Build Coastguard Worker   /// Variable). All the variables in an instruction are conceptually flattened
260*03ce13f7SAndroid Build Coastguard Worker   /// and each variable is mapped to one bit position of the LiveRangesEnded bit
261*03ce13f7SAndroid Build Coastguard Worker   /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
262*03ce13f7SAndroid Build Coastguard Worker   /// tracked this way.
263*03ce13f7SAndroid Build Coastguard Worker   using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
264*03ce13f7SAndroid Build Coastguard Worker   LREndedBits LiveRangesEnded;
265*03ce13f7SAndroid Build Coastguard Worker };
266*03ce13f7SAndroid Build Coastguard Worker 
267*03ce13f7SAndroid Build Coastguard Worker class InstHighLevel : public Inst {
268*03ce13f7SAndroid Build Coastguard Worker   InstHighLevel() = delete;
269*03ce13f7SAndroid Build Coastguard Worker   InstHighLevel(const InstHighLevel &) = delete;
270*03ce13f7SAndroid Build Coastguard Worker   InstHighLevel &operator=(const InstHighLevel &) = delete;
271*03ce13f7SAndroid Build Coastguard Worker 
272*03ce13f7SAndroid Build Coastguard Worker protected:
InstHighLevel(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)273*03ce13f7SAndroid Build Coastguard Worker   InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
274*03ce13f7SAndroid Build Coastguard Worker       : Inst(Func, Kind, MaxSrcs, Dest) {}
emit(const Cfg *)275*03ce13f7SAndroid Build Coastguard Worker   void emit(const Cfg * /*Func*/) const override {
276*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable("emit() called on a non-lowered instruction");
277*03ce13f7SAndroid Build Coastguard Worker   }
emitIAS(const Cfg *)278*03ce13f7SAndroid Build Coastguard Worker   void emitIAS(const Cfg * /*Func*/) const override {
279*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable("emitIAS() called on a non-lowered instruction");
280*03ce13f7SAndroid Build Coastguard Worker   }
281*03ce13f7SAndroid Build Coastguard Worker };
282*03ce13f7SAndroid Build Coastguard Worker 
283*03ce13f7SAndroid Build Coastguard Worker /// Alloca instruction. This captures the size in bytes as getSrc(0), and the
284*03ce13f7SAndroid Build Coastguard Worker /// required alignment in bytes. The alignment must be either 0 (no alignment
285*03ce13f7SAndroid Build Coastguard Worker /// required) or a power of 2.
286*03ce13f7SAndroid Build Coastguard Worker class InstAlloca : public InstHighLevel {
287*03ce13f7SAndroid Build Coastguard Worker   InstAlloca() = delete;
288*03ce13f7SAndroid Build Coastguard Worker   InstAlloca(const InstAlloca &) = delete;
289*03ce13f7SAndroid Build Coastguard Worker   InstAlloca &operator=(const InstAlloca &) = delete;
290*03ce13f7SAndroid Build Coastguard Worker 
291*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Variable * Dest,Operand * ByteCount,uint32_t AlignInBytes)292*03ce13f7SAndroid Build Coastguard Worker   static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
293*03ce13f7SAndroid Build Coastguard Worker                             uint32_t AlignInBytes) {
294*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstAlloca>())
295*03ce13f7SAndroid Build Coastguard Worker         InstAlloca(Func, Dest, ByteCount, AlignInBytes);
296*03ce13f7SAndroid Build Coastguard Worker   }
getAlignInBytes()297*03ce13f7SAndroid Build Coastguard Worker   uint32_t getAlignInBytes() const { return AlignInBytes; }
getSizeInBytes()298*03ce13f7SAndroid Build Coastguard Worker   Operand *getSizeInBytes() const { return getSrc(0); }
getKnownFrameOffset()299*03ce13f7SAndroid Build Coastguard Worker   bool getKnownFrameOffset() const { return KnownFrameOffset; }
setKnownFrameOffset()300*03ce13f7SAndroid Build Coastguard Worker   void setKnownFrameOffset() { KnownFrameOffset = true; }
isMemoryWrite()301*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
302*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)303*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
304*03ce13f7SAndroid Build Coastguard Worker 
305*03ce13f7SAndroid Build Coastguard Worker private:
306*03ce13f7SAndroid Build Coastguard Worker   InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
307*03ce13f7SAndroid Build Coastguard Worker              uint32_t AlignInBytes);
308*03ce13f7SAndroid Build Coastguard Worker 
309*03ce13f7SAndroid Build Coastguard Worker   const uint32_t AlignInBytes;
310*03ce13f7SAndroid Build Coastguard Worker   bool KnownFrameOffset = false;
311*03ce13f7SAndroid Build Coastguard Worker };
312*03ce13f7SAndroid Build Coastguard Worker 
313*03ce13f7SAndroid Build Coastguard Worker /// Binary arithmetic instruction. The source operands are captured in getSrc(0)
314*03ce13f7SAndroid Build Coastguard Worker /// and getSrc(1).
315*03ce13f7SAndroid Build Coastguard Worker class InstArithmetic : public InstHighLevel {
316*03ce13f7SAndroid Build Coastguard Worker   InstArithmetic() = delete;
317*03ce13f7SAndroid Build Coastguard Worker   InstArithmetic(const InstArithmetic &) = delete;
318*03ce13f7SAndroid Build Coastguard Worker   InstArithmetic &operator=(const InstArithmetic &) = delete;
319*03ce13f7SAndroid Build Coastguard Worker 
320*03ce13f7SAndroid Build Coastguard Worker public:
321*03ce13f7SAndroid Build Coastguard Worker   enum OpKind {
322*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str, commutative) tag,
323*03ce13f7SAndroid Build Coastguard Worker     ICEINSTARITHMETIC_TABLE
324*03ce13f7SAndroid Build Coastguard Worker #undef X
325*03ce13f7SAndroid Build Coastguard Worker         _num
326*03ce13f7SAndroid Build Coastguard Worker   };
327*03ce13f7SAndroid Build Coastguard Worker 
create(Cfg * Func,OpKind Op,Variable * Dest,Operand * Source1,Operand * Source2)328*03ce13f7SAndroid Build Coastguard Worker   static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
329*03ce13f7SAndroid Build Coastguard Worker                                 Operand *Source1, Operand *Source2) {
330*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstArithmetic>())
331*03ce13f7SAndroid Build Coastguard Worker         InstArithmetic(Func, Op, Dest, Source1, Source2);
332*03ce13f7SAndroid Build Coastguard Worker   }
getOp()333*03ce13f7SAndroid Build Coastguard Worker   OpKind getOp() const { return Op; }
334*03ce13f7SAndroid Build Coastguard Worker 
335*03ce13f7SAndroid Build Coastguard Worker   virtual const char *getInstName() const override;
336*03ce13f7SAndroid Build Coastguard Worker 
337*03ce13f7SAndroid Build Coastguard Worker   static const char *getOpName(OpKind Op);
338*03ce13f7SAndroid Build Coastguard Worker   bool isCommutative() const;
isMemoryWrite()339*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
340*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)341*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
342*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == Arithmetic;
343*03ce13f7SAndroid Build Coastguard Worker   }
344*03ce13f7SAndroid Build Coastguard Worker 
345*03ce13f7SAndroid Build Coastguard Worker private:
346*03ce13f7SAndroid Build Coastguard Worker   InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
347*03ce13f7SAndroid Build Coastguard Worker                  Operand *Source2);
348*03ce13f7SAndroid Build Coastguard Worker 
349*03ce13f7SAndroid Build Coastguard Worker   const OpKind Op;
350*03ce13f7SAndroid Build Coastguard Worker };
351*03ce13f7SAndroid Build Coastguard Worker 
352*03ce13f7SAndroid Build Coastguard Worker /// Assignment instruction. The source operand is captured in getSrc(0). This is
353*03ce13f7SAndroid Build Coastguard Worker /// not part of the LLVM bitcode, but is a useful abstraction for some of the
354*03ce13f7SAndroid Build Coastguard Worker /// lowering. E.g., if Phi instruction lowering happens before target lowering,
355*03ce13f7SAndroid Build Coastguard Worker /// or for representing an Inttoptr instruction, or as an intermediate step for
356*03ce13f7SAndroid Build Coastguard Worker /// lowering a Load instruction.
357*03ce13f7SAndroid Build Coastguard Worker class InstAssign : public InstHighLevel {
358*03ce13f7SAndroid Build Coastguard Worker   InstAssign() = delete;
359*03ce13f7SAndroid Build Coastguard Worker   InstAssign(const InstAssign &) = delete;
360*03ce13f7SAndroid Build Coastguard Worker   InstAssign &operator=(const InstAssign &) = delete;
361*03ce13f7SAndroid Build Coastguard Worker 
362*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Variable * Dest,Operand * Source)363*03ce13f7SAndroid Build Coastguard Worker   static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
364*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
365*03ce13f7SAndroid Build Coastguard Worker   }
366*03ce13f7SAndroid Build Coastguard Worker   bool isVarAssign() const override;
isMemoryWrite()367*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
368*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)369*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
370*03ce13f7SAndroid Build Coastguard Worker 
371*03ce13f7SAndroid Build Coastguard Worker private:
372*03ce13f7SAndroid Build Coastguard Worker   InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
373*03ce13f7SAndroid Build Coastguard Worker };
374*03ce13f7SAndroid Build Coastguard Worker 
375*03ce13f7SAndroid Build Coastguard Worker /// Branch instruction. This represents both conditional and unconditional
376*03ce13f7SAndroid Build Coastguard Worker /// branches.
377*03ce13f7SAndroid Build Coastguard Worker class InstBr : public InstHighLevel {
378*03ce13f7SAndroid Build Coastguard Worker   InstBr() = delete;
379*03ce13f7SAndroid Build Coastguard Worker   InstBr(const InstBr &) = delete;
380*03ce13f7SAndroid Build Coastguard Worker   InstBr &operator=(const InstBr &) = delete;
381*03ce13f7SAndroid Build Coastguard Worker 
382*03ce13f7SAndroid Build Coastguard Worker public:
383*03ce13f7SAndroid Build Coastguard Worker   /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
384*03ce13f7SAndroid Build Coastguard Worker   /// to an unconditional branch.
create(Cfg * Func,Operand * Source,CfgNode * TargetTrue,CfgNode * TargetFalse)385*03ce13f7SAndroid Build Coastguard Worker   static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
386*03ce13f7SAndroid Build Coastguard Worker                         CfgNode *TargetFalse) {
387*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstBr>())
388*03ce13f7SAndroid Build Coastguard Worker         InstBr(Func, Source, TargetTrue, TargetFalse);
389*03ce13f7SAndroid Build Coastguard Worker   }
390*03ce13f7SAndroid Build Coastguard Worker   /// Create an unconditional branch.
create(Cfg * Func,CfgNode * Target)391*03ce13f7SAndroid Build Coastguard Worker   static InstBr *create(Cfg *Func, CfgNode *Target) {
392*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstBr>()) InstBr(Func, Target);
393*03ce13f7SAndroid Build Coastguard Worker   }
isUnconditional()394*03ce13f7SAndroid Build Coastguard Worker   bool isUnconditional() const { return getTargetTrue() == nullptr; }
getCondition()395*03ce13f7SAndroid Build Coastguard Worker   Operand *getCondition() const {
396*03ce13f7SAndroid Build Coastguard Worker     assert(!isUnconditional());
397*03ce13f7SAndroid Build Coastguard Worker     return getSrc(0);
398*03ce13f7SAndroid Build Coastguard Worker   }
getTargetTrue()399*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getTargetTrue() const { return TargetTrue; }
getTargetFalse()400*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getTargetFalse() const { return TargetFalse; }
getTargetUnconditional()401*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getTargetUnconditional() const {
402*03ce13f7SAndroid Build Coastguard Worker     assert(isUnconditional());
403*03ce13f7SAndroid Build Coastguard Worker     return getTargetFalse();
404*03ce13f7SAndroid Build Coastguard Worker   }
405*03ce13f7SAndroid Build Coastguard Worker   NodeList getTerminatorEdges() const override;
isUnconditionalBranch()406*03ce13f7SAndroid Build Coastguard Worker   bool isUnconditionalBranch() const override { return isUnconditional(); }
407*03ce13f7SAndroid Build Coastguard Worker   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
isMemoryWrite()408*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
409*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)410*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
411*03ce13f7SAndroid Build Coastguard Worker 
412*03ce13f7SAndroid Build Coastguard Worker private:
413*03ce13f7SAndroid Build Coastguard Worker   /// Conditional branch
414*03ce13f7SAndroid Build Coastguard Worker   InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
415*03ce13f7SAndroid Build Coastguard Worker   /// Unconditional branch
416*03ce13f7SAndroid Build Coastguard Worker   InstBr(Cfg *Func, CfgNode *Target);
417*03ce13f7SAndroid Build Coastguard Worker 
418*03ce13f7SAndroid Build Coastguard Worker   CfgNode *TargetFalse; /// Doubles as unconditional branch target
419*03ce13f7SAndroid Build Coastguard Worker   CfgNode *TargetTrue;  /// nullptr if unconditional branch
420*03ce13f7SAndroid Build Coastguard Worker };
421*03ce13f7SAndroid Build Coastguard Worker 
422*03ce13f7SAndroid Build Coastguard Worker /// Call instruction. The call target is captured as getSrc(0), and arg I is
423*03ce13f7SAndroid Build Coastguard Worker /// captured as getSrc(I+1).
424*03ce13f7SAndroid Build Coastguard Worker class InstCall : public InstHighLevel {
425*03ce13f7SAndroid Build Coastguard Worker   InstCall() = delete;
426*03ce13f7SAndroid Build Coastguard Worker   InstCall(const InstCall &) = delete;
427*03ce13f7SAndroid Build Coastguard Worker   InstCall &operator=(const InstCall &) = delete;
428*03ce13f7SAndroid Build Coastguard Worker 
429*03ce13f7SAndroid Build Coastguard Worker public:
430*03ce13f7SAndroid Build Coastguard Worker   static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
431*03ce13f7SAndroid Build Coastguard Worker                           Operand *CallTarget, bool HasTailCall,
432*03ce13f7SAndroid Build Coastguard Worker                           bool IsTargetHelperCall = false,
433*03ce13f7SAndroid Build Coastguard Worker                           bool IsVariadic = false) {
434*03ce13f7SAndroid Build Coastguard Worker     /// Set HasSideEffects to true so that the call instruction can't be
435*03ce13f7SAndroid Build Coastguard Worker     /// dead-code eliminated.
436*03ce13f7SAndroid Build Coastguard Worker     constexpr bool HasSideEffects = true;
437*03ce13f7SAndroid Build Coastguard Worker     constexpr InstKind Kind = Inst::Call;
438*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstCall>())
439*03ce13f7SAndroid Build Coastguard Worker         InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
440*03ce13f7SAndroid Build Coastguard Worker                  IsTargetHelperCall, IsVariadic, HasSideEffects, Kind);
441*03ce13f7SAndroid Build Coastguard Worker   }
addArg(Operand * Arg)442*03ce13f7SAndroid Build Coastguard Worker   void addArg(Operand *Arg) { addSource(Arg); }
getCallTarget()443*03ce13f7SAndroid Build Coastguard Worker   Operand *getCallTarget() const { return getSrc(0); }
getArg(SizeT I)444*03ce13f7SAndroid Build Coastguard Worker   Operand *getArg(SizeT I) const { return getSrc(I + 1); }
getNumArgs()445*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumArgs() const { return getSrcSize() - 1; }
isTailcall()446*03ce13f7SAndroid Build Coastguard Worker   bool isTailcall() const { return HasTailCall; }
isTargetHelperCall()447*03ce13f7SAndroid Build Coastguard Worker   bool isTargetHelperCall() const { return IsTargetHelperCall; }
isVariadic()448*03ce13f7SAndroid Build Coastguard Worker   bool isVariadic() const { return IsVariadic; }
isMemoryWrite()449*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return true; }
450*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)451*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
452*03ce13f7SAndroid Build Coastguard Worker   Type getReturnType() const;
453*03ce13f7SAndroid Build Coastguard Worker 
454*03ce13f7SAndroid Build Coastguard Worker protected:
InstCall(Cfg * Func,SizeT NumArgs,Variable * Dest,Operand * CallTarget,bool HasTailCall,bool IsTargetHelperCall,bool IsVariadic,bool HasSideEff,InstKind Kind)455*03ce13f7SAndroid Build Coastguard Worker   InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
456*03ce13f7SAndroid Build Coastguard Worker            bool HasTailCall, bool IsTargetHelperCall, bool IsVariadic,
457*03ce13f7SAndroid Build Coastguard Worker            bool HasSideEff, InstKind Kind)
458*03ce13f7SAndroid Build Coastguard Worker       : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
459*03ce13f7SAndroid Build Coastguard Worker         IsTargetHelperCall(IsTargetHelperCall), IsVariadic(IsVariadic) {
460*03ce13f7SAndroid Build Coastguard Worker     HasSideEffects = HasSideEff;
461*03ce13f7SAndroid Build Coastguard Worker     addSource(CallTarget);
462*03ce13f7SAndroid Build Coastguard Worker   }
463*03ce13f7SAndroid Build Coastguard Worker 
464*03ce13f7SAndroid Build Coastguard Worker private:
465*03ce13f7SAndroid Build Coastguard Worker   const bool HasTailCall;
466*03ce13f7SAndroid Build Coastguard Worker   const bool IsTargetHelperCall;
467*03ce13f7SAndroid Build Coastguard Worker   const bool IsVariadic;
468*03ce13f7SAndroid Build Coastguard Worker };
469*03ce13f7SAndroid Build Coastguard Worker 
470*03ce13f7SAndroid Build Coastguard Worker /// Cast instruction (a.k.a. conversion operation).
471*03ce13f7SAndroid Build Coastguard Worker class InstCast : public InstHighLevel {
472*03ce13f7SAndroid Build Coastguard Worker   InstCast() = delete;
473*03ce13f7SAndroid Build Coastguard Worker   InstCast(const InstCast &) = delete;
474*03ce13f7SAndroid Build Coastguard Worker   InstCast &operator=(const InstCast &) = delete;
475*03ce13f7SAndroid Build Coastguard Worker 
476*03ce13f7SAndroid Build Coastguard Worker public:
477*03ce13f7SAndroid Build Coastguard Worker   enum OpKind {
478*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str) tag,
479*03ce13f7SAndroid Build Coastguard Worker     ICEINSTCAST_TABLE
480*03ce13f7SAndroid Build Coastguard Worker #undef X
481*03ce13f7SAndroid Build Coastguard Worker         _num
482*03ce13f7SAndroid Build Coastguard Worker   };
483*03ce13f7SAndroid Build Coastguard Worker 
484*03ce13f7SAndroid Build Coastguard Worker   static const char *getCastName(OpKind Kind);
485*03ce13f7SAndroid Build Coastguard Worker 
create(Cfg * Func,OpKind CastKind,Variable * Dest,Operand * Source)486*03ce13f7SAndroid Build Coastguard Worker   static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
487*03ce13f7SAndroid Build Coastguard Worker                           Operand *Source) {
488*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstCast>())
489*03ce13f7SAndroid Build Coastguard Worker         InstCast(Func, CastKind, Dest, Source);
490*03ce13f7SAndroid Build Coastguard Worker   }
getCastKind()491*03ce13f7SAndroid Build Coastguard Worker   OpKind getCastKind() const { return CastKind; }
isMemoryWrite()492*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
493*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)494*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
495*03ce13f7SAndroid Build Coastguard Worker 
496*03ce13f7SAndroid Build Coastguard Worker private:
497*03ce13f7SAndroid Build Coastguard Worker   InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
498*03ce13f7SAndroid Build Coastguard Worker 
499*03ce13f7SAndroid Build Coastguard Worker   const OpKind CastKind;
500*03ce13f7SAndroid Build Coastguard Worker };
501*03ce13f7SAndroid Build Coastguard Worker 
502*03ce13f7SAndroid Build Coastguard Worker /// ExtractElement instruction.
503*03ce13f7SAndroid Build Coastguard Worker class InstExtractElement : public InstHighLevel {
504*03ce13f7SAndroid Build Coastguard Worker   InstExtractElement() = delete;
505*03ce13f7SAndroid Build Coastguard Worker   InstExtractElement(const InstExtractElement &) = delete;
506*03ce13f7SAndroid Build Coastguard Worker   InstExtractElement &operator=(const InstExtractElement &) = delete;
507*03ce13f7SAndroid Build Coastguard Worker 
508*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)509*03ce13f7SAndroid Build Coastguard Worker   static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
510*03ce13f7SAndroid Build Coastguard Worker                                     Operand *Source2) {
511*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstExtractElement>())
512*03ce13f7SAndroid Build Coastguard Worker         InstExtractElement(Func, Dest, Source1, Source2);
513*03ce13f7SAndroid Build Coastguard Worker   }
514*03ce13f7SAndroid Build Coastguard Worker 
isMemoryWrite()515*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
516*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)517*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
518*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == ExtractElement;
519*03ce13f7SAndroid Build Coastguard Worker   }
520*03ce13f7SAndroid Build Coastguard Worker 
521*03ce13f7SAndroid Build Coastguard Worker private:
522*03ce13f7SAndroid Build Coastguard Worker   InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
523*03ce13f7SAndroid Build Coastguard Worker                      Operand *Source2);
524*03ce13f7SAndroid Build Coastguard Worker };
525*03ce13f7SAndroid Build Coastguard Worker 
526*03ce13f7SAndroid Build Coastguard Worker /// Floating-point comparison instruction. The source operands are captured in
527*03ce13f7SAndroid Build Coastguard Worker /// getSrc(0) and getSrc(1).
528*03ce13f7SAndroid Build Coastguard Worker class InstFcmp : public InstHighLevel {
529*03ce13f7SAndroid Build Coastguard Worker   InstFcmp() = delete;
530*03ce13f7SAndroid Build Coastguard Worker   InstFcmp(const InstFcmp &) = delete;
531*03ce13f7SAndroid Build Coastguard Worker   InstFcmp &operator=(const InstFcmp &) = delete;
532*03ce13f7SAndroid Build Coastguard Worker 
533*03ce13f7SAndroid Build Coastguard Worker public:
534*03ce13f7SAndroid Build Coastguard Worker   enum FCond {
535*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str) tag,
536*03ce13f7SAndroid Build Coastguard Worker     ICEINSTFCMP_TABLE
537*03ce13f7SAndroid Build Coastguard Worker #undef X
538*03ce13f7SAndroid Build Coastguard Worker         _num
539*03ce13f7SAndroid Build Coastguard Worker   };
540*03ce13f7SAndroid Build Coastguard Worker 
create(Cfg * Func,FCond Condition,Variable * Dest,Operand * Source1,Operand * Source2)541*03ce13f7SAndroid Build Coastguard Worker   static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
542*03ce13f7SAndroid Build Coastguard Worker                           Operand *Source1, Operand *Source2) {
543*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstFcmp>())
544*03ce13f7SAndroid Build Coastguard Worker         InstFcmp(Func, Condition, Dest, Source1, Source2);
545*03ce13f7SAndroid Build Coastguard Worker   }
getCondition()546*03ce13f7SAndroid Build Coastguard Worker   FCond getCondition() const { return Condition; }
isMemoryWrite()547*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
548*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)549*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
550*03ce13f7SAndroid Build Coastguard Worker 
551*03ce13f7SAndroid Build Coastguard Worker private:
552*03ce13f7SAndroid Build Coastguard Worker   InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
553*03ce13f7SAndroid Build Coastguard Worker            Operand *Source2);
554*03ce13f7SAndroid Build Coastguard Worker 
555*03ce13f7SAndroid Build Coastguard Worker   const FCond Condition;
556*03ce13f7SAndroid Build Coastguard Worker };
557*03ce13f7SAndroid Build Coastguard Worker 
558*03ce13f7SAndroid Build Coastguard Worker /// Integer comparison instruction. The source operands are captured in
559*03ce13f7SAndroid Build Coastguard Worker /// getSrc(0) and getSrc(1).
560*03ce13f7SAndroid Build Coastguard Worker class InstIcmp : public InstHighLevel {
561*03ce13f7SAndroid Build Coastguard Worker   InstIcmp() = delete;
562*03ce13f7SAndroid Build Coastguard Worker   InstIcmp(const InstIcmp &) = delete;
563*03ce13f7SAndroid Build Coastguard Worker   InstIcmp &operator=(const InstIcmp &) = delete;
564*03ce13f7SAndroid Build Coastguard Worker 
565*03ce13f7SAndroid Build Coastguard Worker public:
566*03ce13f7SAndroid Build Coastguard Worker   enum ICond {
567*03ce13f7SAndroid Build Coastguard Worker #define X(tag, inverse, str) tag,
568*03ce13f7SAndroid Build Coastguard Worker     ICEINSTICMP_TABLE
569*03ce13f7SAndroid Build Coastguard Worker #undef X
570*03ce13f7SAndroid Build Coastguard Worker         _num
571*03ce13f7SAndroid Build Coastguard Worker   };
572*03ce13f7SAndroid Build Coastguard Worker 
create(Cfg * Func,ICond Condition,Variable * Dest,Operand * Source1,Operand * Source2)573*03ce13f7SAndroid Build Coastguard Worker   static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
574*03ce13f7SAndroid Build Coastguard Worker                           Operand *Source1, Operand *Source2) {
575*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstIcmp>())
576*03ce13f7SAndroid Build Coastguard Worker         InstIcmp(Func, Condition, Dest, Source1, Source2);
577*03ce13f7SAndroid Build Coastguard Worker   }
getCondition()578*03ce13f7SAndroid Build Coastguard Worker   ICond getCondition() const { return Condition; }
579*03ce13f7SAndroid Build Coastguard Worker   void reverseConditionAndOperands();
isMemoryWrite()580*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
581*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)582*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
583*03ce13f7SAndroid Build Coastguard Worker 
584*03ce13f7SAndroid Build Coastguard Worker private:
585*03ce13f7SAndroid Build Coastguard Worker   InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
586*03ce13f7SAndroid Build Coastguard Worker            Operand *Source2);
587*03ce13f7SAndroid Build Coastguard Worker 
588*03ce13f7SAndroid Build Coastguard Worker   ICond Condition;
589*03ce13f7SAndroid Build Coastguard Worker };
590*03ce13f7SAndroid Build Coastguard Worker 
591*03ce13f7SAndroid Build Coastguard Worker /// InsertElement instruction.
592*03ce13f7SAndroid Build Coastguard Worker class InstInsertElement : public InstHighLevel {
593*03ce13f7SAndroid Build Coastguard Worker   InstInsertElement() = delete;
594*03ce13f7SAndroid Build Coastguard Worker   InstInsertElement(const InstInsertElement &) = delete;
595*03ce13f7SAndroid Build Coastguard Worker   InstInsertElement &operator=(const InstInsertElement &) = delete;
596*03ce13f7SAndroid Build Coastguard Worker 
597*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2,Operand * Source3)598*03ce13f7SAndroid Build Coastguard Worker   static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
599*03ce13f7SAndroid Build Coastguard Worker                                    Operand *Source2, Operand *Source3) {
600*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstInsertElement>())
601*03ce13f7SAndroid Build Coastguard Worker         InstInsertElement(Func, Dest, Source1, Source2, Source3);
602*03ce13f7SAndroid Build Coastguard Worker   }
603*03ce13f7SAndroid Build Coastguard Worker 
isMemoryWrite()604*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
605*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)606*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
607*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == InsertElement;
608*03ce13f7SAndroid Build Coastguard Worker   }
609*03ce13f7SAndroid Build Coastguard Worker 
610*03ce13f7SAndroid Build Coastguard Worker private:
611*03ce13f7SAndroid Build Coastguard Worker   InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
612*03ce13f7SAndroid Build Coastguard Worker                     Operand *Source2, Operand *Source3);
613*03ce13f7SAndroid Build Coastguard Worker };
614*03ce13f7SAndroid Build Coastguard Worker 
615*03ce13f7SAndroid Build Coastguard Worker /// An intrinsic operation, representing either a sequence of instructions,
616*03ce13f7SAndroid Build Coastguard Worker /// or a single instruction. Availability of intrinsics is target-specific.
617*03ce13f7SAndroid Build Coastguard Worker class InstIntrinsic : public InstHighLevel {
618*03ce13f7SAndroid Build Coastguard Worker   InstIntrinsic() = delete;
619*03ce13f7SAndroid Build Coastguard Worker   InstIntrinsic(const InstIntrinsic &) = delete;
620*03ce13f7SAndroid Build Coastguard Worker   InstIntrinsic &operator=(const InstIntrinsic &) = delete;
621*03ce13f7SAndroid Build Coastguard Worker 
622*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,SizeT NumArgs,Variable * Dest,const Intrinsics::IntrinsicInfo & Info)623*03ce13f7SAndroid Build Coastguard Worker   static InstIntrinsic *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
624*03ce13f7SAndroid Build Coastguard Worker                                const Intrinsics::IntrinsicInfo &Info) {
625*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstIntrinsic>())
626*03ce13f7SAndroid Build Coastguard Worker         InstIntrinsic(Func, NumArgs, Dest, Info);
627*03ce13f7SAndroid Build Coastguard Worker   }
addArg(Operand * Arg)628*03ce13f7SAndroid Build Coastguard Worker   void addArg(Operand *Arg) { addSource(Arg); }
getArg(SizeT I)629*03ce13f7SAndroid Build Coastguard Worker   Operand *getArg(SizeT I) const { return getSrc(I); }
getNumArgs()630*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumArgs() const { return getSrcSize(); }
classof(const Inst * Instr)631*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
632*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == Intrinsic;
633*03ce13f7SAndroid Build Coastguard Worker   }
634*03ce13f7SAndroid Build Coastguard Worker 
getIntrinsicInfo()635*03ce13f7SAndroid Build Coastguard Worker   Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
getIntrinsicID()636*03ce13f7SAndroid Build Coastguard Worker   Intrinsics::IntrinsicID getIntrinsicID() const { return Info.ID; }
isMemoryWrite()637*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override {
638*03ce13f7SAndroid Build Coastguard Worker     return getIntrinsicInfo().IsMemoryWrite;
639*03ce13f7SAndroid Build Coastguard Worker   }
640*03ce13f7SAndroid Build Coastguard Worker 
641*03ce13f7SAndroid Build Coastguard Worker private:
InstIntrinsic(Cfg * Func,SizeT NumArgs,Variable * Dest,const Intrinsics::IntrinsicInfo & Info)642*03ce13f7SAndroid Build Coastguard Worker   InstIntrinsic(Cfg *Func, SizeT NumArgs, Variable *Dest,
643*03ce13f7SAndroid Build Coastguard Worker                 const Intrinsics::IntrinsicInfo &Info)
644*03ce13f7SAndroid Build Coastguard Worker       : InstHighLevel(Func, Inst::Intrinsic, NumArgs, Dest), Info(Info) {}
645*03ce13f7SAndroid Build Coastguard Worker 
646*03ce13f7SAndroid Build Coastguard Worker   const Intrinsics::IntrinsicInfo Info;
647*03ce13f7SAndroid Build Coastguard Worker };
648*03ce13f7SAndroid Build Coastguard Worker 
649*03ce13f7SAndroid Build Coastguard Worker /// Load instruction. The source address is captured in getSrc(0).
650*03ce13f7SAndroid Build Coastguard Worker class InstLoad : public InstHighLevel {
651*03ce13f7SAndroid Build Coastguard Worker   InstLoad() = delete;
652*03ce13f7SAndroid Build Coastguard Worker   InstLoad(const InstLoad &) = delete;
653*03ce13f7SAndroid Build Coastguard Worker   InstLoad &operator=(const InstLoad &) = delete;
654*03ce13f7SAndroid Build Coastguard Worker 
655*03ce13f7SAndroid Build Coastguard Worker public:
656*03ce13f7SAndroid Build Coastguard Worker   static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
657*03ce13f7SAndroid Build Coastguard Worker                           uint32_t Align = 1) {
658*03ce13f7SAndroid Build Coastguard Worker     // TODO(kschimpf) Stop ignoring alignment specification.
659*03ce13f7SAndroid Build Coastguard Worker     (void)Align;
660*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
661*03ce13f7SAndroid Build Coastguard Worker   }
isMemoryWrite()662*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
663*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)664*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
665*03ce13f7SAndroid Build Coastguard Worker 
666*03ce13f7SAndroid Build Coastguard Worker private:
667*03ce13f7SAndroid Build Coastguard Worker   InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
668*03ce13f7SAndroid Build Coastguard Worker };
669*03ce13f7SAndroid Build Coastguard Worker 
670*03ce13f7SAndroid Build Coastguard Worker /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
671*03ce13f7SAndroid Build Coastguard Worker /// source operand is getSrc(I).
672*03ce13f7SAndroid Build Coastguard Worker class InstPhi : public InstHighLevel {
673*03ce13f7SAndroid Build Coastguard Worker   InstPhi() = delete;
674*03ce13f7SAndroid Build Coastguard Worker   InstPhi(const InstPhi &) = delete;
675*03ce13f7SAndroid Build Coastguard Worker   InstPhi &operator=(const InstPhi &) = delete;
676*03ce13f7SAndroid Build Coastguard Worker 
677*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,SizeT MaxSrcs,Variable * Dest)678*03ce13f7SAndroid Build Coastguard Worker   static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
679*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
680*03ce13f7SAndroid Build Coastguard Worker   }
681*03ce13f7SAndroid Build Coastguard Worker   void addArgument(Operand *Source, CfgNode *Label);
682*03ce13f7SAndroid Build Coastguard Worker   Operand *getOperandForTarget(CfgNode *Target) const;
683*03ce13f7SAndroid Build Coastguard Worker   void clearOperandForTarget(CfgNode *Target);
getLabel(SizeT Index)684*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
setLabel(SizeT Index,CfgNode * Label)685*03ce13f7SAndroid Build Coastguard Worker   void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
686*03ce13f7SAndroid Build Coastguard Worker   void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
687*03ce13f7SAndroid Build Coastguard Worker                           Liveness *Liveness);
688*03ce13f7SAndroid Build Coastguard Worker   Inst *lower(Cfg *Func);
isMemoryWrite()689*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
690*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)691*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
692*03ce13f7SAndroid Build Coastguard Worker 
693*03ce13f7SAndroid Build Coastguard Worker private:
694*03ce13f7SAndroid Build Coastguard Worker   InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
destroy(Cfg * Func)695*03ce13f7SAndroid Build Coastguard Worker   void destroy(Cfg *Func) override { Inst::destroy(Func); }
696*03ce13f7SAndroid Build Coastguard Worker 
697*03ce13f7SAndroid Build Coastguard Worker   /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
698*03ce13f7SAndroid Build Coastguard Worker   /// but the Phi instruction is created before InEdges[] is available, so it's
699*03ce13f7SAndroid Build Coastguard Worker   /// more complicated to share the list.
700*03ce13f7SAndroid Build Coastguard Worker   CfgVector<CfgNode *> Labels;
701*03ce13f7SAndroid Build Coastguard Worker };
702*03ce13f7SAndroid Build Coastguard Worker 
703*03ce13f7SAndroid Build Coastguard Worker /// Ret instruction. The return value is captured in getSrc(0), but if there is
704*03ce13f7SAndroid Build Coastguard Worker /// no return value (void-type function), then getSrcSize()==0 and
705*03ce13f7SAndroid Build Coastguard Worker /// hasRetValue()==false.
706*03ce13f7SAndroid Build Coastguard Worker class InstRet : public InstHighLevel {
707*03ce13f7SAndroid Build Coastguard Worker   InstRet() = delete;
708*03ce13f7SAndroid Build Coastguard Worker   InstRet(const InstRet &) = delete;
709*03ce13f7SAndroid Build Coastguard Worker   InstRet &operator=(const InstRet &) = delete;
710*03ce13f7SAndroid Build Coastguard Worker 
711*03ce13f7SAndroid Build Coastguard Worker public:
712*03ce13f7SAndroid Build Coastguard Worker   static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
713*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
714*03ce13f7SAndroid Build Coastguard Worker   }
hasRetValue()715*03ce13f7SAndroid Build Coastguard Worker   bool hasRetValue() const { return getSrcSize(); }
getRetValue()716*03ce13f7SAndroid Build Coastguard Worker   Operand *getRetValue() const {
717*03ce13f7SAndroid Build Coastguard Worker     assert(hasRetValue());
718*03ce13f7SAndroid Build Coastguard Worker     return getSrc(0);
719*03ce13f7SAndroid Build Coastguard Worker   }
getTerminatorEdges()720*03ce13f7SAndroid Build Coastguard Worker   NodeList getTerminatorEdges() const override { return NodeList(); }
isMemoryWrite()721*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
722*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)723*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
724*03ce13f7SAndroid Build Coastguard Worker 
725*03ce13f7SAndroid Build Coastguard Worker private:
726*03ce13f7SAndroid Build Coastguard Worker   InstRet(Cfg *Func, Operand *RetValue);
727*03ce13f7SAndroid Build Coastguard Worker };
728*03ce13f7SAndroid Build Coastguard Worker 
729*03ce13f7SAndroid Build Coastguard Worker /// Select instruction.  The condition, true, and false operands are captured.
730*03ce13f7SAndroid Build Coastguard Worker class InstSelect : public InstHighLevel {
731*03ce13f7SAndroid Build Coastguard Worker   InstSelect() = delete;
732*03ce13f7SAndroid Build Coastguard Worker   InstSelect(const InstSelect &) = delete;
733*03ce13f7SAndroid Build Coastguard Worker   InstSelect &operator=(const InstSelect &) = delete;
734*03ce13f7SAndroid Build Coastguard Worker 
735*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Variable * Dest,Operand * Condition,Operand * SourceTrue,Operand * SourceFalse)736*03ce13f7SAndroid Build Coastguard Worker   static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
737*03ce13f7SAndroid Build Coastguard Worker                             Operand *SourceTrue, Operand *SourceFalse) {
738*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstSelect>())
739*03ce13f7SAndroid Build Coastguard Worker         InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
740*03ce13f7SAndroid Build Coastguard Worker   }
getCondition()741*03ce13f7SAndroid Build Coastguard Worker   Operand *getCondition() const { return getSrc(0); }
getTrueOperand()742*03ce13f7SAndroid Build Coastguard Worker   Operand *getTrueOperand() const { return getSrc(1); }
getFalseOperand()743*03ce13f7SAndroid Build Coastguard Worker   Operand *getFalseOperand() const { return getSrc(2); }
isMemoryWrite()744*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
745*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)746*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
747*03ce13f7SAndroid Build Coastguard Worker 
748*03ce13f7SAndroid Build Coastguard Worker private:
749*03ce13f7SAndroid Build Coastguard Worker   InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
750*03ce13f7SAndroid Build Coastguard Worker              Operand *Source2);
751*03ce13f7SAndroid Build Coastguard Worker };
752*03ce13f7SAndroid Build Coastguard Worker 
753*03ce13f7SAndroid Build Coastguard Worker /// Store instruction. The address operand is captured, along with the data
754*03ce13f7SAndroid Build Coastguard Worker /// operand to be stored into the address.
755*03ce13f7SAndroid Build Coastguard Worker class InstStore : public InstHighLevel {
756*03ce13f7SAndroid Build Coastguard Worker   InstStore() = delete;
757*03ce13f7SAndroid Build Coastguard Worker   InstStore(const InstStore &) = delete;
758*03ce13f7SAndroid Build Coastguard Worker   InstStore &operator=(const InstStore &) = delete;
759*03ce13f7SAndroid Build Coastguard Worker 
760*03ce13f7SAndroid Build Coastguard Worker public:
761*03ce13f7SAndroid Build Coastguard Worker   static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
762*03ce13f7SAndroid Build Coastguard Worker                            uint32_t Align = 1) {
763*03ce13f7SAndroid Build Coastguard Worker     // TODO(kschimpf) Stop ignoring alignment specification.
764*03ce13f7SAndroid Build Coastguard Worker     (void)Align;
765*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
766*03ce13f7SAndroid Build Coastguard Worker   }
767*03ce13f7SAndroid Build Coastguard Worker   Variable *getRmwBeacon() const;
768*03ce13f7SAndroid Build Coastguard Worker   void setRmwBeacon(Variable *Beacon);
isMemoryWrite()769*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return true; }
770*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)771*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
772*03ce13f7SAndroid Build Coastguard Worker 
773*03ce13f7SAndroid Build Coastguard Worker private:
774*03ce13f7SAndroid Build Coastguard Worker   InstStore(Cfg *Func, Operand *Data, Operand *Addr);
775*03ce13f7SAndroid Build Coastguard Worker };
776*03ce13f7SAndroid Build Coastguard Worker 
777*03ce13f7SAndroid Build Coastguard Worker /// Switch instruction. The single source operand is captured as getSrc(0).
778*03ce13f7SAndroid Build Coastguard Worker class InstSwitch : public InstHighLevel {
779*03ce13f7SAndroid Build Coastguard Worker   InstSwitch() = delete;
780*03ce13f7SAndroid Build Coastguard Worker   InstSwitch(const InstSwitch &) = delete;
781*03ce13f7SAndroid Build Coastguard Worker   InstSwitch &operator=(const InstSwitch &) = delete;
782*03ce13f7SAndroid Build Coastguard Worker 
783*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,SizeT NumCases,Operand * Source,CfgNode * LabelDefault)784*03ce13f7SAndroid Build Coastguard Worker   static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
785*03ce13f7SAndroid Build Coastguard Worker                             CfgNode *LabelDefault) {
786*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstSwitch>())
787*03ce13f7SAndroid Build Coastguard Worker         InstSwitch(Func, NumCases, Source, LabelDefault);
788*03ce13f7SAndroid Build Coastguard Worker   }
getComparison()789*03ce13f7SAndroid Build Coastguard Worker   Operand *getComparison() const { return getSrc(0); }
getLabelDefault()790*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getLabelDefault() const { return LabelDefault; }
getNumCases()791*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumCases() const { return NumCases; }
getValue(SizeT I)792*03ce13f7SAndroid Build Coastguard Worker   uint64_t getValue(SizeT I) const {
793*03ce13f7SAndroid Build Coastguard Worker     assert(I < NumCases);
794*03ce13f7SAndroid Build Coastguard Worker     return Values[I];
795*03ce13f7SAndroid Build Coastguard Worker   }
getLabel(SizeT I)796*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getLabel(SizeT I) const {
797*03ce13f7SAndroid Build Coastguard Worker     assert(I < NumCases);
798*03ce13f7SAndroid Build Coastguard Worker     return Labels[I];
799*03ce13f7SAndroid Build Coastguard Worker   }
800*03ce13f7SAndroid Build Coastguard Worker   void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
801*03ce13f7SAndroid Build Coastguard Worker   NodeList getTerminatorEdges() const override;
802*03ce13f7SAndroid Build Coastguard Worker   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
isMemoryWrite()803*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
804*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)805*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
806*03ce13f7SAndroid Build Coastguard Worker 
807*03ce13f7SAndroid Build Coastguard Worker private:
808*03ce13f7SAndroid Build Coastguard Worker   InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
destroy(Cfg * Func)809*03ce13f7SAndroid Build Coastguard Worker   void destroy(Cfg *Func) override {
810*03ce13f7SAndroid Build Coastguard Worker     Func->deallocateArrayOf<uint64_t>(Values);
811*03ce13f7SAndroid Build Coastguard Worker     Func->deallocateArrayOf<CfgNode *>(Labels);
812*03ce13f7SAndroid Build Coastguard Worker     Inst::destroy(Func);
813*03ce13f7SAndroid Build Coastguard Worker   }
814*03ce13f7SAndroid Build Coastguard Worker 
815*03ce13f7SAndroid Build Coastguard Worker   CfgNode *LabelDefault;
816*03ce13f7SAndroid Build Coastguard Worker   SizeT NumCases;   /// not including the default case
817*03ce13f7SAndroid Build Coastguard Worker   uint64_t *Values; /// size is NumCases
818*03ce13f7SAndroid Build Coastguard Worker   CfgNode **Labels; /// size is NumCases
819*03ce13f7SAndroid Build Coastguard Worker };
820*03ce13f7SAndroid Build Coastguard Worker 
821*03ce13f7SAndroid Build Coastguard Worker /// Unreachable instruction. This is a terminator instruction with no operands.
822*03ce13f7SAndroid Build Coastguard Worker class InstUnreachable : public InstHighLevel {
823*03ce13f7SAndroid Build Coastguard Worker   InstUnreachable() = delete;
824*03ce13f7SAndroid Build Coastguard Worker   InstUnreachable(const InstUnreachable &) = delete;
825*03ce13f7SAndroid Build Coastguard Worker   InstUnreachable &operator=(const InstUnreachable &) = delete;
826*03ce13f7SAndroid Build Coastguard Worker 
827*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func)828*03ce13f7SAndroid Build Coastguard Worker   static InstUnreachable *create(Cfg *Func) {
829*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
830*03ce13f7SAndroid Build Coastguard Worker   }
getTerminatorEdges()831*03ce13f7SAndroid Build Coastguard Worker   NodeList getTerminatorEdges() const override { return NodeList(); }
isMemoryWrite()832*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
833*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)834*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
835*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == Unreachable;
836*03ce13f7SAndroid Build Coastguard Worker   }
837*03ce13f7SAndroid Build Coastguard Worker 
838*03ce13f7SAndroid Build Coastguard Worker private:
839*03ce13f7SAndroid Build Coastguard Worker   explicit InstUnreachable(Cfg *Func);
840*03ce13f7SAndroid Build Coastguard Worker };
841*03ce13f7SAndroid Build Coastguard Worker 
842*03ce13f7SAndroid Build Coastguard Worker /// FakeDef instruction. This creates a fake definition of a variable, which is
843*03ce13f7SAndroid Build Coastguard Worker /// how we represent the case when an instruction produces multiple results.
844*03ce13f7SAndroid Build Coastguard Worker /// This doesn't happen with high-level ICE instructions, but might with lowered
845*03ce13f7SAndroid Build Coastguard Worker /// instructions. For example, this would be a way to represent condition flags
846*03ce13f7SAndroid Build Coastguard Worker /// being modified by an instruction.
847*03ce13f7SAndroid Build Coastguard Worker ///
848*03ce13f7SAndroid Build Coastguard Worker /// It's generally useful to set the optional source operand to be the dest
849*03ce13f7SAndroid Build Coastguard Worker /// variable of the instruction that actually produces the FakeDef dest.
850*03ce13f7SAndroid Build Coastguard Worker /// Otherwise, the original instruction could be dead-code eliminated if its
851*03ce13f7SAndroid Build Coastguard Worker /// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
852*03ce13f7SAndroid Build Coastguard Worker /// initialized.
853*03ce13f7SAndroid Build Coastguard Worker class InstFakeDef : public InstHighLevel {
854*03ce13f7SAndroid Build Coastguard Worker   InstFakeDef() = delete;
855*03ce13f7SAndroid Build Coastguard Worker   InstFakeDef(const InstFakeDef &) = delete;
856*03ce13f7SAndroid Build Coastguard Worker   InstFakeDef &operator=(const InstFakeDef &) = delete;
857*03ce13f7SAndroid Build Coastguard Worker 
858*03ce13f7SAndroid Build Coastguard Worker public:
859*03ce13f7SAndroid Build Coastguard Worker   static InstFakeDef *create(Cfg *Func, Variable *Dest,
860*03ce13f7SAndroid Build Coastguard Worker                              Variable *Src = nullptr) {
861*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
862*03ce13f7SAndroid Build Coastguard Worker   }
863*03ce13f7SAndroid Build Coastguard Worker   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)864*03ce13f7SAndroid Build Coastguard Worker   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()865*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
866*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)867*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
868*03ce13f7SAndroid Build Coastguard Worker 
869*03ce13f7SAndroid Build Coastguard Worker private:
870*03ce13f7SAndroid Build Coastguard Worker   InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
871*03ce13f7SAndroid Build Coastguard Worker };
872*03ce13f7SAndroid Build Coastguard Worker 
873*03ce13f7SAndroid Build Coastguard Worker /// FakeUse instruction. This creates a fake use of a variable, to keep the
874*03ce13f7SAndroid Build Coastguard Worker /// instruction that produces that variable from being dead-code eliminated.
875*03ce13f7SAndroid Build Coastguard Worker /// This is useful in a variety of lowering situations. The FakeUse instruction
876*03ce13f7SAndroid Build Coastguard Worker /// has no dest, so it can itself never be dead-code eliminated.  A weight can
877*03ce13f7SAndroid Build Coastguard Worker /// be provided to provide extra bias to the register allocator - for simplicity
878*03ce13f7SAndroid Build Coastguard Worker /// of implementation, weight=N is handled by holding N copies of the variable
879*03ce13f7SAndroid Build Coastguard Worker /// as source operands.
880*03ce13f7SAndroid Build Coastguard Worker class InstFakeUse : public InstHighLevel {
881*03ce13f7SAndroid Build Coastguard Worker   InstFakeUse() = delete;
882*03ce13f7SAndroid Build Coastguard Worker   InstFakeUse(const InstFakeUse &) = delete;
883*03ce13f7SAndroid Build Coastguard Worker   InstFakeUse &operator=(const InstFakeUse &) = delete;
884*03ce13f7SAndroid Build Coastguard Worker 
885*03ce13f7SAndroid Build Coastguard Worker public:
886*03ce13f7SAndroid Build Coastguard Worker   static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
887*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
888*03ce13f7SAndroid Build Coastguard Worker   }
889*03ce13f7SAndroid Build Coastguard Worker   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)890*03ce13f7SAndroid Build Coastguard Worker   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()891*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
892*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)893*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
894*03ce13f7SAndroid Build Coastguard Worker 
895*03ce13f7SAndroid Build Coastguard Worker private:
896*03ce13f7SAndroid Build Coastguard Worker   InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
897*03ce13f7SAndroid Build Coastguard Worker };
898*03ce13f7SAndroid Build Coastguard Worker 
899*03ce13f7SAndroid Build Coastguard Worker /// FakeKill instruction. This "kills" a set of variables by modeling a trivial
900*03ce13f7SAndroid Build Coastguard Worker /// live range at this instruction for each (implicit) variable. The primary use
901*03ce13f7SAndroid Build Coastguard Worker /// is to indicate that scratch registers are killed after a call, so that the
902*03ce13f7SAndroid Build Coastguard Worker /// register allocator won't assign a scratch register to a variable whose live
903*03ce13f7SAndroid Build Coastguard Worker /// range spans a call.
904*03ce13f7SAndroid Build Coastguard Worker ///
905*03ce13f7SAndroid Build Coastguard Worker /// The FakeKill instruction also holds a pointer to the instruction that kills
906*03ce13f7SAndroid Build Coastguard Worker /// the set of variables, so that if that linked instruction gets dead-code
907*03ce13f7SAndroid Build Coastguard Worker /// eliminated, the FakeKill instruction will as well.
908*03ce13f7SAndroid Build Coastguard Worker class InstFakeKill : public InstHighLevel {
909*03ce13f7SAndroid Build Coastguard Worker   InstFakeKill() = delete;
910*03ce13f7SAndroid Build Coastguard Worker   InstFakeKill(const InstFakeKill &) = delete;
911*03ce13f7SAndroid Build Coastguard Worker   InstFakeKill &operator=(const InstFakeKill &) = delete;
912*03ce13f7SAndroid Build Coastguard Worker 
913*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,const Inst * Linked)914*03ce13f7SAndroid Build Coastguard Worker   static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
915*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
916*03ce13f7SAndroid Build Coastguard Worker   }
getLinked()917*03ce13f7SAndroid Build Coastguard Worker   const Inst *getLinked() const { return Linked; }
918*03ce13f7SAndroid Build Coastguard Worker   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)919*03ce13f7SAndroid Build Coastguard Worker   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()920*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
921*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)922*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
923*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == FakeKill;
924*03ce13f7SAndroid Build Coastguard Worker   }
925*03ce13f7SAndroid Build Coastguard Worker 
926*03ce13f7SAndroid Build Coastguard Worker private:
927*03ce13f7SAndroid Build Coastguard Worker   InstFakeKill(Cfg *Func, const Inst *Linked);
928*03ce13f7SAndroid Build Coastguard Worker 
929*03ce13f7SAndroid Build Coastguard Worker   /// This instruction is ignored if Linked->isDeleted() is true.
930*03ce13f7SAndroid Build Coastguard Worker   const Inst *Linked;
931*03ce13f7SAndroid Build Coastguard Worker };
932*03ce13f7SAndroid Build Coastguard Worker 
933*03ce13f7SAndroid Build Coastguard Worker /// ShuffleVector instruction. This represents a shuffle operation on vector
934*03ce13f7SAndroid Build Coastguard Worker /// types. This instruction is not part of the PNaCl bitcode: it is generated
935*03ce13f7SAndroid Build Coastguard Worker /// by Subzero when it matches the pattern used by pnacl-clang when compiling
936*03ce13f7SAndroid Build Coastguard Worker /// to bitcode.
937*03ce13f7SAndroid Build Coastguard Worker class InstShuffleVector : public InstHighLevel {
938*03ce13f7SAndroid Build Coastguard Worker   InstShuffleVector() = delete;
939*03ce13f7SAndroid Build Coastguard Worker   InstShuffleVector(const InstShuffleVector &) = delete;
940*03ce13f7SAndroid Build Coastguard Worker   InstShuffleVector &operator=(const InstShuffleVector &) = delete;
941*03ce13f7SAndroid Build Coastguard Worker 
942*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1)943*03ce13f7SAndroid Build Coastguard Worker   static InstShuffleVector *create(Cfg *Func, Variable *Dest, Operand *Src0,
944*03ce13f7SAndroid Build Coastguard Worker                                    Operand *Src1) {
945*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstShuffleVector>())
946*03ce13f7SAndroid Build Coastguard Worker         InstShuffleVector(Func, Dest, Src0, Src1);
947*03ce13f7SAndroid Build Coastguard Worker   }
948*03ce13f7SAndroid Build Coastguard Worker 
getNumIndexes()949*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumIndexes() const { return NumIndexes; }
950*03ce13f7SAndroid Build Coastguard Worker 
addIndex(ConstantInteger32 * Index)951*03ce13f7SAndroid Build Coastguard Worker   void addIndex(ConstantInteger32 *Index) {
952*03ce13f7SAndroid Build Coastguard Worker     assert(CurrentIndex < NumIndexes);
953*03ce13f7SAndroid Build Coastguard Worker     Indexes[CurrentIndex++] = Index;
954*03ce13f7SAndroid Build Coastguard Worker   }
955*03ce13f7SAndroid Build Coastguard Worker 
getIndex(SizeT Pos)956*03ce13f7SAndroid Build Coastguard Worker   ConstantInteger32 *getIndex(SizeT Pos) const {
957*03ce13f7SAndroid Build Coastguard Worker     assert(Pos < NumIndexes);
958*03ce13f7SAndroid Build Coastguard Worker     return Indexes[Pos];
959*03ce13f7SAndroid Build Coastguard Worker   }
960*03ce13f7SAndroid Build Coastguard Worker 
getIndexValue(SizeT Pos)961*03ce13f7SAndroid Build Coastguard Worker   int32_t getIndexValue(SizeT Pos) const { return getIndex(Pos)->getValue(); }
962*03ce13f7SAndroid Build Coastguard Worker 
indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3)963*03ce13f7SAndroid Build Coastguard Worker   bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3) const {
964*03ce13f7SAndroid Build Coastguard Worker     static constexpr SizeT ExpectedNumElements = 4;
965*03ce13f7SAndroid Build Coastguard Worker     assert(ExpectedNumElements == getNumIndexes());
966*03ce13f7SAndroid Build Coastguard Worker     (void)ExpectedNumElements;
967*03ce13f7SAndroid Build Coastguard Worker 
968*03ce13f7SAndroid Build Coastguard Worker     return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
969*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(2) == i2 && getIndexValue(3) == i3;
970*03ce13f7SAndroid Build Coastguard Worker   }
971*03ce13f7SAndroid Build Coastguard Worker 
indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3,int32_t i4,int32_t i5,int32_t i6,int32_t i7)972*03ce13f7SAndroid Build Coastguard Worker   bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
973*03ce13f7SAndroid Build Coastguard Worker                   int32_t i5, int32_t i6, int32_t i7) const {
974*03ce13f7SAndroid Build Coastguard Worker     static constexpr SizeT ExpectedNumElements = 8;
975*03ce13f7SAndroid Build Coastguard Worker     assert(ExpectedNumElements == getNumIndexes());
976*03ce13f7SAndroid Build Coastguard Worker     (void)ExpectedNumElements;
977*03ce13f7SAndroid Build Coastguard Worker 
978*03ce13f7SAndroid Build Coastguard Worker     return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
979*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
980*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
981*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(6) == i6 && getIndexValue(7) == i7;
982*03ce13f7SAndroid Build Coastguard Worker   }
983*03ce13f7SAndroid Build Coastguard Worker 
indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3,int32_t i4,int32_t i5,int32_t i6,int32_t i7,int32_t i8,int32_t i9,int32_t i10,int32_t i11,int32_t i12,int32_t i13,int32_t i14,int32_t i15)984*03ce13f7SAndroid Build Coastguard Worker   bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
985*03ce13f7SAndroid Build Coastguard Worker                   int32_t i5, int32_t i6, int32_t i7, int32_t i8, int32_t i9,
986*03ce13f7SAndroid Build Coastguard Worker                   int32_t i10, int32_t i11, int32_t i12, int32_t i13,
987*03ce13f7SAndroid Build Coastguard Worker                   int32_t i14, int32_t i15) const {
988*03ce13f7SAndroid Build Coastguard Worker     static constexpr SizeT ExpectedNumElements = 16;
989*03ce13f7SAndroid Build Coastguard Worker     assert(ExpectedNumElements == getNumIndexes());
990*03ce13f7SAndroid Build Coastguard Worker     (void)ExpectedNumElements;
991*03ce13f7SAndroid Build Coastguard Worker 
992*03ce13f7SAndroid Build Coastguard Worker     return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
993*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
994*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
995*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(6) == i6 && getIndexValue(7) == i7 &&
996*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(8) == i8 && getIndexValue(9) == i9 &&
997*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(10) == i10 && getIndexValue(11) == i11 &&
998*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(12) == i12 && getIndexValue(13) == i13 &&
999*03ce13f7SAndroid Build Coastguard Worker            getIndexValue(14) == i14 && getIndexValue(15) == i15;
1000*03ce13f7SAndroid Build Coastguard Worker   }
1001*03ce13f7SAndroid Build Coastguard Worker 
isMemoryWrite()1002*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
1003*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1004*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
1005*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == ShuffleVector;
1006*03ce13f7SAndroid Build Coastguard Worker   }
1007*03ce13f7SAndroid Build Coastguard Worker 
1008*03ce13f7SAndroid Build Coastguard Worker private:
1009*03ce13f7SAndroid Build Coastguard Worker   InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1);
1010*03ce13f7SAndroid Build Coastguard Worker 
destroy(Cfg * Func)1011*03ce13f7SAndroid Build Coastguard Worker   void destroy(Cfg *Func) override {
1012*03ce13f7SAndroid Build Coastguard Worker     Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
1013*03ce13f7SAndroid Build Coastguard Worker     Inst::destroy(Func);
1014*03ce13f7SAndroid Build Coastguard Worker   }
1015*03ce13f7SAndroid Build Coastguard Worker 
1016*03ce13f7SAndroid Build Coastguard Worker   ConstantInteger32 **Indexes;
1017*03ce13f7SAndroid Build Coastguard Worker   SizeT CurrentIndex = 0;
1018*03ce13f7SAndroid Build Coastguard Worker   const SizeT NumIndexes;
1019*03ce13f7SAndroid Build Coastguard Worker };
1020*03ce13f7SAndroid Build Coastguard Worker 
1021*03ce13f7SAndroid Build Coastguard Worker /// JumpTable instruction. This represents a jump table that will be stored in
1022*03ce13f7SAndroid Build Coastguard Worker /// the .rodata section. This is used to track and repoint the target CfgNodes
1023*03ce13f7SAndroid Build Coastguard Worker /// which may change, for example due to splitting for phi lowering.
1024*03ce13f7SAndroid Build Coastguard Worker class InstJumpTable : public InstHighLevel {
1025*03ce13f7SAndroid Build Coastguard Worker   InstJumpTable() = delete;
1026*03ce13f7SAndroid Build Coastguard Worker   InstJumpTable(const InstJumpTable &) = delete;
1027*03ce13f7SAndroid Build Coastguard Worker   InstJumpTable &operator=(const InstJumpTable &) = delete;
1028*03ce13f7SAndroid Build Coastguard Worker 
1029*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,SizeT NumTargets,CfgNode * Default)1030*03ce13f7SAndroid Build Coastguard Worker   static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
1031*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstJumpTable>())
1032*03ce13f7SAndroid Build Coastguard Worker         InstJumpTable(Func, NumTargets, Default);
1033*03ce13f7SAndroid Build Coastguard Worker   }
addTarget(SizeT TargetIndex,CfgNode * Target)1034*03ce13f7SAndroid Build Coastguard Worker   void addTarget(SizeT TargetIndex, CfgNode *Target) {
1035*03ce13f7SAndroid Build Coastguard Worker     assert(TargetIndex < NumTargets);
1036*03ce13f7SAndroid Build Coastguard Worker     Targets[TargetIndex] = Target;
1037*03ce13f7SAndroid Build Coastguard Worker   }
1038*03ce13f7SAndroid Build Coastguard Worker   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
getId()1039*03ce13f7SAndroid Build Coastguard Worker   SizeT getId() const { return Id; }
getNumTargets()1040*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumTargets() const { return NumTargets; }
getTarget(SizeT I)1041*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getTarget(SizeT I) const {
1042*03ce13f7SAndroid Build Coastguard Worker     assert(I < NumTargets);
1043*03ce13f7SAndroid Build Coastguard Worker     return Targets[I];
1044*03ce13f7SAndroid Build Coastguard Worker   }
isMemoryWrite()1045*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
1046*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1047*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
1048*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == JumpTable;
1049*03ce13f7SAndroid Build Coastguard Worker   }
1050*03ce13f7SAndroid Build Coastguard Worker   // Creates a JumpTableData struct (used for ELF emission) that represents this
1051*03ce13f7SAndroid Build Coastguard Worker   // InstJumpTable.
1052*03ce13f7SAndroid Build Coastguard Worker   JumpTableData toJumpTableData(Assembler *Asm) const;
1053*03ce13f7SAndroid Build Coastguard Worker 
1054*03ce13f7SAndroid Build Coastguard Worker   // InstJumpTable is just a placeholder for the switch targets, and it does not
1055*03ce13f7SAndroid Build Coastguard Worker   // need to emit any code, so we redefine emit and emitIAS to do nothing.
emit(const Cfg *)1056*03ce13f7SAndroid Build Coastguard Worker   void emit(const Cfg *) const override {}
emitIAS(const Cfg *)1057*03ce13f7SAndroid Build Coastguard Worker   void emitIAS(const Cfg * /* Func */) const override {}
1058*03ce13f7SAndroid Build Coastguard Worker 
getName()1059*03ce13f7SAndroid Build Coastguard Worker   const std::string getName() const {
1060*03ce13f7SAndroid Build Coastguard Worker     assert(Name.hasStdString());
1061*03ce13f7SAndroid Build Coastguard Worker     return Name.toString();
1062*03ce13f7SAndroid Build Coastguard Worker   }
1063*03ce13f7SAndroid Build Coastguard Worker 
getSectionName()1064*03ce13f7SAndroid Build Coastguard Worker   std::string getSectionName() const {
1065*03ce13f7SAndroid Build Coastguard Worker     return JumpTableData::createSectionName(FuncName);
1066*03ce13f7SAndroid Build Coastguard Worker   }
1067*03ce13f7SAndroid Build Coastguard Worker 
1068*03ce13f7SAndroid Build Coastguard Worker private:
1069*03ce13f7SAndroid Build Coastguard Worker   InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
destroy(Cfg * Func)1070*03ce13f7SAndroid Build Coastguard Worker   void destroy(Cfg *Func) override {
1071*03ce13f7SAndroid Build Coastguard Worker     Func->deallocateArrayOf<CfgNode *>(Targets);
1072*03ce13f7SAndroid Build Coastguard Worker     Inst::destroy(Func);
1073*03ce13f7SAndroid Build Coastguard Worker   }
1074*03ce13f7SAndroid Build Coastguard Worker 
1075*03ce13f7SAndroid Build Coastguard Worker   const SizeT Id;
1076*03ce13f7SAndroid Build Coastguard Worker   const SizeT NumTargets;
1077*03ce13f7SAndroid Build Coastguard Worker   CfgNode **Targets;
1078*03ce13f7SAndroid Build Coastguard Worker   GlobalString Name; // This JumpTable's name in the output.
1079*03ce13f7SAndroid Build Coastguard Worker   GlobalString FuncName;
1080*03ce13f7SAndroid Build Coastguard Worker };
1081*03ce13f7SAndroid Build Coastguard Worker 
1082*03ce13f7SAndroid Build Coastguard Worker /// This instruction inserts an unconditional breakpoint.
1083*03ce13f7SAndroid Build Coastguard Worker ///
1084*03ce13f7SAndroid Build Coastguard Worker /// On x86, this assembles into an INT 3 instruction.
1085*03ce13f7SAndroid Build Coastguard Worker ///
1086*03ce13f7SAndroid Build Coastguard Worker /// This instruction is primarily meant for debugging the code generator.
1087*03ce13f7SAndroid Build Coastguard Worker class InstBreakpoint : public InstHighLevel {
1088*03ce13f7SAndroid Build Coastguard Worker public:
1089*03ce13f7SAndroid Build Coastguard Worker   InstBreakpoint() = delete;
1090*03ce13f7SAndroid Build Coastguard Worker   InstBreakpoint(const InstBreakpoint &) = delete;
1091*03ce13f7SAndroid Build Coastguard Worker   InstBreakpoint &operator=(const InstBreakpoint &) = delete;
1092*03ce13f7SAndroid Build Coastguard Worker 
1093*03ce13f7SAndroid Build Coastguard Worker   explicit InstBreakpoint(Cfg *Func);
isMemoryWrite()1094*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override { return false; }
1095*03ce13f7SAndroid Build Coastguard Worker 
1096*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func)1097*03ce13f7SAndroid Build Coastguard Worker   static InstBreakpoint *create(Cfg *Func) {
1098*03ce13f7SAndroid Build Coastguard Worker     return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
1099*03ce13f7SAndroid Build Coastguard Worker   }
1100*03ce13f7SAndroid Build Coastguard Worker 
classof(const Inst * Instr)1101*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) {
1102*03ce13f7SAndroid Build Coastguard Worker     return Instr->getKind() == Breakpoint;
1103*03ce13f7SAndroid Build Coastguard Worker   }
1104*03ce13f7SAndroid Build Coastguard Worker };
1105*03ce13f7SAndroid Build Coastguard Worker 
1106*03ce13f7SAndroid Build Coastguard Worker /// The Target instruction is the base class for all target-specific
1107*03ce13f7SAndroid Build Coastguard Worker /// instructions.
1108*03ce13f7SAndroid Build Coastguard Worker class InstTarget : public Inst {
1109*03ce13f7SAndroid Build Coastguard Worker   InstTarget() = delete;
1110*03ce13f7SAndroid Build Coastguard Worker   InstTarget(const InstTarget &) = delete;
1111*03ce13f7SAndroid Build Coastguard Worker   InstTarget &operator=(const InstTarget &) = delete;
1112*03ce13f7SAndroid Build Coastguard Worker 
1113*03ce13f7SAndroid Build Coastguard Worker public:
getEmitInstCount()1114*03ce13f7SAndroid Build Coastguard Worker   uint32_t getEmitInstCount() const override { return 1; }
isMemoryWrite()1115*03ce13f7SAndroid Build Coastguard Worker   bool isMemoryWrite() const override {
1116*03ce13f7SAndroid Build Coastguard Worker     return true; // conservative answer
1117*03ce13f7SAndroid Build Coastguard Worker   }
1118*03ce13f7SAndroid Build Coastguard Worker   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1119*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
1120*03ce13f7SAndroid Build Coastguard Worker 
1121*03ce13f7SAndroid Build Coastguard Worker protected:
InstTarget(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)1122*03ce13f7SAndroid Build Coastguard Worker   InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
1123*03ce13f7SAndroid Build Coastguard Worker       : Inst(Func, Kind, MaxSrcs, Dest) {
1124*03ce13f7SAndroid Build Coastguard Worker     assert(Kind >= Target);
1125*03ce13f7SAndroid Build Coastguard Worker     assert(Kind <= Target_Max);
1126*03ce13f7SAndroid Build Coastguard Worker   }
1127*03ce13f7SAndroid Build Coastguard Worker };
1128*03ce13f7SAndroid Build Coastguard Worker 
1129*03ce13f7SAndroid Build Coastguard Worker bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
1130*03ce13f7SAndroid Build Coastguard Worker 
1131*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1132*03ce13f7SAndroid Build Coastguard Worker 
1133*03ce13f7SAndroid Build Coastguard Worker #ifdef PNACL_LLVM
1134*03ce13f7SAndroid Build Coastguard Worker namespace llvm {
1135*03ce13f7SAndroid Build Coastguard Worker 
1136*03ce13f7SAndroid Build Coastguard Worker /// Override the default ilist traits so that Inst's private ctor and deleted
1137*03ce13f7SAndroid Build Coastguard Worker /// dtor aren't invoked.
1138*03ce13f7SAndroid Build Coastguard Worker template <>
1139*03ce13f7SAndroid Build Coastguard Worker struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
1140*03ce13f7SAndroid Build Coastguard Worker   Ice::Inst *createSentinel() const {
1141*03ce13f7SAndroid Build Coastguard Worker     return static_cast<Ice::Inst *>(&Sentinel);
1142*03ce13f7SAndroid Build Coastguard Worker   }
1143*03ce13f7SAndroid Build Coastguard Worker   static void destroySentinel(Ice::Inst *) {}
1144*03ce13f7SAndroid Build Coastguard Worker   Ice::Inst *provideInitialHead() const { return createSentinel(); }
1145*03ce13f7SAndroid Build Coastguard Worker   Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
1146*03ce13f7SAndroid Build Coastguard Worker   static void noteHead(Ice::Inst *, Ice::Inst *) {}
1147*03ce13f7SAndroid Build Coastguard Worker   void deleteNode(Ice::Inst *) {}
1148*03ce13f7SAndroid Build Coastguard Worker 
1149*03ce13f7SAndroid Build Coastguard Worker private:
1150*03ce13f7SAndroid Build Coastguard Worker   mutable ilist_half_node<Ice::Inst> Sentinel;
1151*03ce13f7SAndroid Build Coastguard Worker };
1152*03ce13f7SAndroid Build Coastguard Worker 
1153*03ce13f7SAndroid Build Coastguard Worker } // end of namespace llvm
1154*03ce13f7SAndroid Build Coastguard Worker #endif // PNACL_LLVM
1155*03ce13f7SAndroid Build Coastguard Worker 
1156*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
1157*03ce13f7SAndroid Build Coastguard Worker 
1158*03ce13f7SAndroid Build Coastguard Worker inline InstList::iterator instToIterator(Inst *Instr) {
1159*03ce13f7SAndroid Build Coastguard Worker #ifdef PNACL_LLVM
1160*03ce13f7SAndroid Build Coastguard Worker   return Instr;
1161*03ce13f7SAndroid Build Coastguard Worker #else  // !PNACL_LLVM
1162*03ce13f7SAndroid Build Coastguard Worker   return Instr->getIterator();
1163*03ce13f7SAndroid Build Coastguard Worker #endif // !PNACL_LLVM
1164*03ce13f7SAndroid Build Coastguard Worker }
1165*03ce13f7SAndroid Build Coastguard Worker 
1166*03ce13f7SAndroid Build Coastguard Worker inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; }
1167*03ce13f7SAndroid Build Coastguard Worker 
1168*03ce13f7SAndroid Build Coastguard Worker inline const Inst *iteratorToInst(InstList::const_iterator Iter) {
1169*03ce13f7SAndroid Build Coastguard Worker   return &*Iter;
1170*03ce13f7SAndroid Build Coastguard Worker }
1171*03ce13f7SAndroid Build Coastguard Worker 
1172*03ce13f7SAndroid Build Coastguard Worker inline InstList::iterator
1173*03ce13f7SAndroid Build Coastguard Worker reverseToForwardIterator(InstList::reverse_iterator RI) {
1174*03ce13f7SAndroid Build Coastguard Worker #ifdef PNACL_LLVM
1175*03ce13f7SAndroid Build Coastguard Worker   return RI.base();
1176*03ce13f7SAndroid Build Coastguard Worker #else  // !PNACL_LLVM
1177*03ce13f7SAndroid Build Coastguard Worker   return ++RI.getReverse();
1178*03ce13f7SAndroid Build Coastguard Worker #endif // !PNACL_LLVM
1179*03ce13f7SAndroid Build Coastguard Worker }
1180*03ce13f7SAndroid Build Coastguard Worker 
1181*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1182*03ce13f7SAndroid Build Coastguard Worker 
1183*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEINST_H
1184