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