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