• 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 
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     /// Set HasSideEffects to true so that the call instruction can't be
431     /// dead-code eliminated. IntrinsicCalls can override this if the particular
432     /// intrinsic is deletable and has no side-effects.
433     constexpr bool HasSideEffects = true;
434     constexpr InstKind Kind = Inst::Call;
435     return new (Func->allocate<InstCall>())
436         InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
437                  IsTargetHelperCall, HasSideEffects, Kind);
438   }
addArg(Operand * Arg)439   void addArg(Operand *Arg) { addSource(Arg); }
getCallTarget()440   Operand *getCallTarget() const { return getSrc(0); }
getArg(SizeT I)441   Operand *getArg(SizeT I) const { return getSrc(I + 1); }
getNumArgs()442   SizeT getNumArgs() const { return getSrcSize() - 1; }
isTailcall()443   bool isTailcall() const { return HasTailCall; }
isTargetHelperCall()444   bool isTargetHelperCall() const { return IsTargetHelperCall; }
isMemoryWrite()445   bool isMemoryWrite() const override { return true; }
446   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)447   static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
448   Type getReturnType() const;
449 
450 protected:
InstCall(Cfg * Func,SizeT NumArgs,Variable * Dest,Operand * CallTarget,bool HasTailCall,bool IsTargetHelperCall,bool HasSideEff,InstKind Kind)451   InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
452            bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
453            InstKind Kind)
454       : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
455         IsTargetHelperCall(IsTargetHelperCall) {
456     HasSideEffects = HasSideEff;
457     addSource(CallTarget);
458   }
459 
460 private:
461   const bool HasTailCall;
462   const bool IsTargetHelperCall;
463 };
464 
465 /// Cast instruction (a.k.a. conversion operation).
466 class InstCast : public InstHighLevel {
467   InstCast() = delete;
468   InstCast(const InstCast &) = delete;
469   InstCast &operator=(const InstCast &) = delete;
470 
471 public:
472   enum OpKind {
473 #define X(tag, str) tag,
474     ICEINSTCAST_TABLE
475 #undef X
476         _num
477   };
478 
479   static const char *getCastName(OpKind Kind);
480 
create(Cfg * Func,OpKind CastKind,Variable * Dest,Operand * Source)481   static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
482                           Operand *Source) {
483     return new (Func->allocate<InstCast>())
484         InstCast(Func, CastKind, Dest, Source);
485   }
getCastKind()486   OpKind getCastKind() const { return CastKind; }
isMemoryWrite()487   bool isMemoryWrite() const override { return false; }
488   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)489   static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
490 
491 private:
492   InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
493 
494   const OpKind CastKind;
495 };
496 
497 /// ExtractElement instruction.
498 class InstExtractElement : public InstHighLevel {
499   InstExtractElement() = delete;
500   InstExtractElement(const InstExtractElement &) = delete;
501   InstExtractElement &operator=(const InstExtractElement &) = delete;
502 
503 public:
create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)504   static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
505                                     Operand *Source2) {
506     return new (Func->allocate<InstExtractElement>())
507         InstExtractElement(Func, Dest, Source1, Source2);
508   }
509 
isMemoryWrite()510   bool isMemoryWrite() const override { return false; }
511   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)512   static bool classof(const Inst *Instr) {
513     return Instr->getKind() == ExtractElement;
514   }
515 
516 private:
517   InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
518                      Operand *Source2);
519 };
520 
521 /// Floating-point comparison instruction. The source operands are captured in
522 /// getSrc(0) and getSrc(1).
523 class InstFcmp : public InstHighLevel {
524   InstFcmp() = delete;
525   InstFcmp(const InstFcmp &) = delete;
526   InstFcmp &operator=(const InstFcmp &) = delete;
527 
528 public:
529   enum FCond {
530 #define X(tag, str) tag,
531     ICEINSTFCMP_TABLE
532 #undef X
533         _num
534   };
535 
create(Cfg * Func,FCond Condition,Variable * Dest,Operand * Source1,Operand * Source2)536   static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
537                           Operand *Source1, Operand *Source2) {
538     return new (Func->allocate<InstFcmp>())
539         InstFcmp(Func, Condition, Dest, Source1, Source2);
540   }
getCondition()541   FCond getCondition() const { return Condition; }
isMemoryWrite()542   bool isMemoryWrite() const override { return false; }
543   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)544   static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
545 
546 private:
547   InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
548            Operand *Source2);
549 
550   const FCond Condition;
551 };
552 
553 /// Integer comparison instruction. The source operands are captured in
554 /// getSrc(0) and getSrc(1).
555 class InstIcmp : public InstHighLevel {
556   InstIcmp() = delete;
557   InstIcmp(const InstIcmp &) = delete;
558   InstIcmp &operator=(const InstIcmp &) = delete;
559 
560 public:
561   enum ICond {
562 #define X(tag, inverse, str) tag,
563     ICEINSTICMP_TABLE
564 #undef X
565         _num
566   };
567 
create(Cfg * Func,ICond Condition,Variable * Dest,Operand * Source1,Operand * Source2)568   static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
569                           Operand *Source1, Operand *Source2) {
570     return new (Func->allocate<InstIcmp>())
571         InstIcmp(Func, Condition, Dest, Source1, Source2);
572   }
getCondition()573   ICond getCondition() const { return Condition; }
574   void reverseConditionAndOperands();
isMemoryWrite()575   bool isMemoryWrite() const override { return false; }
576   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)577   static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
578 
579 private:
580   InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
581            Operand *Source2);
582 
583   ICond Condition;
584 };
585 
586 /// InsertElement instruction.
587 class InstInsertElement : public InstHighLevel {
588   InstInsertElement() = delete;
589   InstInsertElement(const InstInsertElement &) = delete;
590   InstInsertElement &operator=(const InstInsertElement &) = delete;
591 
592 public:
create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2,Operand * Source3)593   static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
594                                    Operand *Source2, Operand *Source3) {
595     return new (Func->allocate<InstInsertElement>())
596         InstInsertElement(Func, Dest, Source1, Source2, Source3);
597   }
598 
isMemoryWrite()599   bool isMemoryWrite() const override { return false; }
600   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)601   static bool classof(const Inst *Instr) {
602     return Instr->getKind() == InsertElement;
603   }
604 
605 private:
606   InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
607                     Operand *Source2, Operand *Source3);
608 };
609 
610 /// Call to an intrinsic function. The call target is captured as getSrc(0), and
611 /// arg I is captured as getSrc(I+1).
612 class InstIntrinsicCall : public InstCall {
613   InstIntrinsicCall() = delete;
614   InstIntrinsicCall(const InstIntrinsicCall &) = delete;
615   InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
616 
617 public:
create(Cfg * Func,SizeT NumArgs,Variable * Dest,Operand * CallTarget,const Intrinsics::IntrinsicInfo & Info)618   static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
619                                    Operand *CallTarget,
620                                    const Intrinsics::IntrinsicInfo &Info) {
621     return new (Func->allocate<InstIntrinsicCall>())
622         InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
623   }
classof(const Inst * Instr)624   static bool classof(const Inst *Instr) {
625     return Instr->getKind() == IntrinsicCall;
626   }
627 
getIntrinsicInfo()628   Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
isMemoryWrite()629   bool isMemoryWrite() const override {
630     return getIntrinsicInfo().IsMemoryWrite;
631   }
632 
633 private:
InstIntrinsicCall(Cfg * Func,SizeT NumArgs,Variable * Dest,Operand * CallTarget,const Intrinsics::IntrinsicInfo & Info)634   InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
635                     Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
636       : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
637                  Info.HasSideEffects, Inst::IntrinsicCall),
638         Info(Info) {}
639 
640   const Intrinsics::IntrinsicInfo Info;
641 };
642 
643 /// Load instruction. The source address is captured in getSrc(0).
644 class InstLoad : public InstHighLevel {
645   InstLoad() = delete;
646   InstLoad(const InstLoad &) = delete;
647   InstLoad &operator=(const InstLoad &) = delete;
648 
649 public:
650   static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
651                           uint32_t Align = 1) {
652     // TODO(kschimpf) Stop ignoring alignment specification.
653     (void)Align;
654     return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
655   }
getSourceAddress()656   Operand *getSourceAddress() const { return getSrc(0); }
isMemoryWrite()657   bool isMemoryWrite() const override { return false; }
658   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)659   static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
660 
661 private:
662   InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
663 };
664 
665 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
666 /// source operand is getSrc(I).
667 class InstPhi : public InstHighLevel {
668   InstPhi() = delete;
669   InstPhi(const InstPhi &) = delete;
670   InstPhi &operator=(const InstPhi &) = delete;
671 
672 public:
create(Cfg * Func,SizeT MaxSrcs,Variable * Dest)673   static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
674     return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
675   }
676   void addArgument(Operand *Source, CfgNode *Label);
677   Operand *getOperandForTarget(CfgNode *Target) const;
678   void clearOperandForTarget(CfgNode *Target);
getLabel(SizeT Index)679   CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
setLabel(SizeT Index,CfgNode * Label)680   void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
681   void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
682                           Liveness *Liveness);
683   Inst *lower(Cfg *Func);
isMemoryWrite()684   bool isMemoryWrite() const override { return false; }
685   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)686   static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
687 
688 private:
689   InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
destroy(Cfg * Func)690   void destroy(Cfg *Func) override { Inst::destroy(Func); }
691 
692   /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
693   /// but the Phi instruction is created before InEdges[] is available, so it's
694   /// more complicated to share the list.
695   CfgVector<CfgNode *> Labels;
696 };
697 
698 /// Ret instruction. The return value is captured in getSrc(0), but if there is
699 /// no return value (void-type function), then getSrcSize()==0 and
700 /// hasRetValue()==false.
701 class InstRet : public InstHighLevel {
702   InstRet() = delete;
703   InstRet(const InstRet &) = delete;
704   InstRet &operator=(const InstRet &) = delete;
705 
706 public:
707   static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
708     return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
709   }
hasRetValue()710   bool hasRetValue() const { return getSrcSize(); }
getRetValue()711   Operand *getRetValue() const {
712     assert(hasRetValue());
713     return getSrc(0);
714   }
getTerminatorEdges()715   NodeList getTerminatorEdges() const override { return NodeList(); }
isMemoryWrite()716   bool isMemoryWrite() const override { return false; }
717   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)718   static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
719 
720 private:
721   InstRet(Cfg *Func, Operand *RetValue);
722 };
723 
724 /// Select instruction.  The condition, true, and false operands are captured.
725 class InstSelect : public InstHighLevel {
726   InstSelect() = delete;
727   InstSelect(const InstSelect &) = delete;
728   InstSelect &operator=(const InstSelect &) = delete;
729 
730 public:
create(Cfg * Func,Variable * Dest,Operand * Condition,Operand * SourceTrue,Operand * SourceFalse)731   static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
732                             Operand *SourceTrue, Operand *SourceFalse) {
733     return new (Func->allocate<InstSelect>())
734         InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
735   }
getCondition()736   Operand *getCondition() const { return getSrc(0); }
getTrueOperand()737   Operand *getTrueOperand() const { return getSrc(1); }
getFalseOperand()738   Operand *getFalseOperand() const { return getSrc(2); }
isMemoryWrite()739   bool isMemoryWrite() const override { return false; }
740   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)741   static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
742 
743 private:
744   InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
745              Operand *Source2);
746 };
747 
748 /// Store instruction. The address operand is captured, along with the data
749 /// operand to be stored into the address.
750 class InstStore : public InstHighLevel {
751   InstStore() = delete;
752   InstStore(const InstStore &) = delete;
753   InstStore &operator=(const InstStore &) = delete;
754 
755 public:
756   static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
757                            uint32_t Align = 1) {
758     // TODO(kschimpf) Stop ignoring alignment specification.
759     (void)Align;
760     return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
761   }
getAddr()762   Operand *getAddr() const { return getSrc(1); }
getData()763   Operand *getData() const { return getSrc(0); }
764   Variable *getRmwBeacon() const;
765   void setRmwBeacon(Variable *Beacon);
isMemoryWrite()766   bool isMemoryWrite() const override { return true; }
767   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)768   static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
769 
770 private:
771   InstStore(Cfg *Func, Operand *Data, Operand *Addr);
772 };
773 
774 /// Switch instruction. The single source operand is captured as getSrc(0).
775 class InstSwitch : public InstHighLevel {
776   InstSwitch() = delete;
777   InstSwitch(const InstSwitch &) = delete;
778   InstSwitch &operator=(const InstSwitch &) = delete;
779 
780 public:
create(Cfg * Func,SizeT NumCases,Operand * Source,CfgNode * LabelDefault)781   static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
782                             CfgNode *LabelDefault) {
783     return new (Func->allocate<InstSwitch>())
784         InstSwitch(Func, NumCases, Source, LabelDefault);
785   }
getComparison()786   Operand *getComparison() const { return getSrc(0); }
getLabelDefault()787   CfgNode *getLabelDefault() const { return LabelDefault; }
getNumCases()788   SizeT getNumCases() const { return NumCases; }
getValue(SizeT I)789   uint64_t getValue(SizeT I) const {
790     assert(I < NumCases);
791     return Values[I];
792   }
getLabel(SizeT I)793   CfgNode *getLabel(SizeT I) const {
794     assert(I < NumCases);
795     return Labels[I];
796   }
797   void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
798   NodeList getTerminatorEdges() const override;
799   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
isMemoryWrite()800   bool isMemoryWrite() const override { return false; }
801   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)802   static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
803 
804 private:
805   InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
destroy(Cfg * Func)806   void destroy(Cfg *Func) override {
807     Func->deallocateArrayOf<uint64_t>(Values);
808     Func->deallocateArrayOf<CfgNode *>(Labels);
809     Inst::destroy(Func);
810   }
811 
812   CfgNode *LabelDefault;
813   SizeT NumCases;   /// not including the default case
814   uint64_t *Values; /// size is NumCases
815   CfgNode **Labels; /// size is NumCases
816 };
817 
818 /// Unreachable instruction. This is a terminator instruction with no operands.
819 class InstUnreachable : public InstHighLevel {
820   InstUnreachable() = delete;
821   InstUnreachable(const InstUnreachable &) = delete;
822   InstUnreachable &operator=(const InstUnreachable &) = delete;
823 
824 public:
create(Cfg * Func)825   static InstUnreachable *create(Cfg *Func) {
826     return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
827   }
getTerminatorEdges()828   NodeList getTerminatorEdges() const override { return NodeList(); }
isMemoryWrite()829   bool isMemoryWrite() const override { return false; }
830   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)831   static bool classof(const Inst *Instr) {
832     return Instr->getKind() == Unreachable;
833   }
834 
835 private:
836   explicit InstUnreachable(Cfg *Func);
837 };
838 
839 /// BundleLock instruction.  There are no operands. Contains an option
840 /// indicating whether align_to_end is specified.
841 class InstBundleLock : public InstHighLevel {
842   InstBundleLock() = delete;
843   InstBundleLock(const InstBundleLock &) = delete;
844   InstBundleLock &operator=(const InstBundleLock &) = delete;
845 
846 public:
847   enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
create(Cfg * Func,Option BundleOption)848   static InstBundleLock *create(Cfg *Func, Option BundleOption) {
849     return new (Func->allocate<InstBundleLock>())
850         InstBundleLock(Func, BundleOption);
851   }
852   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)853   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()854   bool isMemoryWrite() const override { return false; }
855   void dump(const Cfg *Func) const override;
getOption()856   Option getOption() const { return BundleOption; }
classof(const Inst * Instr)857   static bool classof(const Inst *Instr) {
858     return Instr->getKind() == BundleLock;
859   }
860 
861 private:
862   Option BundleOption;
863   InstBundleLock(Cfg *Func, Option BundleOption);
864 };
865 
866 /// BundleUnlock instruction. There are no operands.
867 class InstBundleUnlock : public InstHighLevel {
868   InstBundleUnlock() = delete;
869   InstBundleUnlock(const InstBundleUnlock &) = delete;
870   InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
871 
872 public:
create(Cfg * Func)873   static InstBundleUnlock *create(Cfg *Func) {
874     return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
875   }
876   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)877   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()878   bool isMemoryWrite() const override { return false; }
879   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)880   static bool classof(const Inst *Instr) {
881     return Instr->getKind() == BundleUnlock;
882   }
883 
884 private:
885   explicit InstBundleUnlock(Cfg *Func);
886 };
887 
888 /// FakeDef instruction. This creates a fake definition of a variable, which is
889 /// how we represent the case when an instruction produces multiple results.
890 /// This doesn't happen with high-level ICE instructions, but might with lowered
891 /// instructions. For example, this would be a way to represent condition flags
892 /// being modified by an instruction.
893 ///
894 /// It's generally useful to set the optional source operand to be the dest
895 /// variable of the instruction that actually produces the FakeDef dest.
896 /// Otherwise, the original instruction could be dead-code eliminated if its
897 /// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
898 /// initialized.
899 class InstFakeDef : public InstHighLevel {
900   InstFakeDef() = delete;
901   InstFakeDef(const InstFakeDef &) = delete;
902   InstFakeDef &operator=(const InstFakeDef &) = delete;
903 
904 public:
905   static InstFakeDef *create(Cfg *Func, Variable *Dest,
906                              Variable *Src = nullptr) {
907     return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
908   }
909   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)910   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()911   bool isMemoryWrite() const override { return false; }
912   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)913   static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
914 
915 private:
916   InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
917 };
918 
919 /// FakeUse instruction. This creates a fake use of a variable, to keep the
920 /// instruction that produces that variable from being dead-code eliminated.
921 /// This is useful in a variety of lowering situations. The FakeUse instruction
922 /// has no dest, so it can itself never be dead-code eliminated.  A weight can
923 /// be provided to provide extra bias to the register allocator - for simplicity
924 /// of implementation, weight=N is handled by holding N copies of the variable
925 /// as source operands.
926 class InstFakeUse : public InstHighLevel {
927   InstFakeUse() = delete;
928   InstFakeUse(const InstFakeUse &) = delete;
929   InstFakeUse &operator=(const InstFakeUse &) = delete;
930 
931 public:
932   static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
933     return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
934   }
935   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)936   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()937   bool isMemoryWrite() const override { return false; }
938   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)939   static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
940 
941 private:
942   InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
943 };
944 
945 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial
946 /// live range at this instruction for each (implicit) variable. The primary use
947 /// is to indicate that scratch registers are killed after a call, so that the
948 /// register allocator won't assign a scratch register to a variable whose live
949 /// range spans a call.
950 ///
951 /// The FakeKill instruction also holds a pointer to the instruction that kills
952 /// the set of variables, so that if that linked instruction gets dead-code
953 /// eliminated, the FakeKill instruction will as well.
954 class InstFakeKill : public InstHighLevel {
955   InstFakeKill() = delete;
956   InstFakeKill(const InstFakeKill &) = delete;
957   InstFakeKill &operator=(const InstFakeKill &) = delete;
958 
959 public:
create(Cfg * Func,const Inst * Linked)960   static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
961     return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
962   }
getLinked()963   const Inst *getLinked() const { return Linked; }
964   void emit(const Cfg *Func) const override;
emitIAS(const Cfg *)965   void emitIAS(const Cfg * /* Func */) const override {}
isMemoryWrite()966   bool isMemoryWrite() const override { return false; }
967   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)968   static bool classof(const Inst *Instr) {
969     return Instr->getKind() == FakeKill;
970   }
971 
972 private:
973   InstFakeKill(Cfg *Func, const Inst *Linked);
974 
975   /// This instruction is ignored if Linked->isDeleted() is true.
976   const Inst *Linked;
977 };
978 
979 /// ShuffleVector instruction. This represents a shuffle operation on vector
980 /// types. This instruction is not part of the PNaCl bitcode: it is generated
981 /// by Subzero when it matches the pattern used by pnacl-clang when compiling
982 /// to bitcode.
983 class InstShuffleVector : public InstHighLevel {
984   InstShuffleVector() = delete;
985   InstShuffleVector(const InstShuffleVector &) = delete;
986   InstShuffleVector &operator=(const InstShuffleVector &) = delete;
987 
988 public:
create(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1)989   static InstShuffleVector *create(Cfg *Func, Variable *Dest, Operand *Src0,
990                                    Operand *Src1) {
991     return new (Func->allocate<InstShuffleVector>())
992         InstShuffleVector(Func, Dest, Src0, Src1);
993   }
994 
getNumIndexes()995   SizeT getNumIndexes() const { return NumIndexes; }
996 
addIndex(ConstantInteger32 * Index)997   void addIndex(ConstantInteger32 *Index) {
998     assert(CurrentIndex < NumIndexes);
999     Indexes[CurrentIndex++] = Index;
1000   }
1001 
getIndex(SizeT Pos)1002   ConstantInteger32 *getIndex(SizeT Pos) const {
1003     assert(Pos < NumIndexes);
1004     return Indexes[Pos];
1005   }
1006 
getIndexValue(SizeT Pos)1007   int32_t getIndexValue(SizeT Pos) const { return getIndex(Pos)->getValue(); }
1008 
indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3)1009   bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3) const {
1010     static constexpr SizeT ExpectedNumElements = 4;
1011     assert(ExpectedNumElements == getNumIndexes());
1012     (void)ExpectedNumElements;
1013 
1014     return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
1015            getIndexValue(2) == i2 && getIndexValue(3) == i3;
1016   }
1017 
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)1018   bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
1019                   int32_t i5, int32_t i6, int32_t i7) const {
1020     static constexpr SizeT ExpectedNumElements = 8;
1021     assert(ExpectedNumElements == getNumIndexes());
1022     (void)ExpectedNumElements;
1023 
1024     return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
1025            getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
1026            getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
1027            getIndexValue(6) == i6 && getIndexValue(7) == i7;
1028   }
1029 
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)1030   bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
1031                   int32_t i5, int32_t i6, int32_t i7, int32_t i8, int32_t i9,
1032                   int32_t i10, int32_t i11, int32_t i12, int32_t i13,
1033                   int32_t i14, int32_t i15) const {
1034     static constexpr SizeT ExpectedNumElements = 16;
1035     assert(ExpectedNumElements == getNumIndexes());
1036     (void)ExpectedNumElements;
1037 
1038     return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
1039            getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
1040            getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
1041            getIndexValue(6) == i6 && getIndexValue(7) == i7 &&
1042            getIndexValue(8) == i8 && getIndexValue(9) == i9 &&
1043            getIndexValue(10) == i10 && getIndexValue(11) == i11 &&
1044            getIndexValue(12) == i12 && getIndexValue(13) == i13 &&
1045            getIndexValue(14) == i14 && getIndexValue(15) == i15;
1046   }
1047 
isMemoryWrite()1048   bool isMemoryWrite() const override { return false; }
1049   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1050   static bool classof(const Inst *Instr) {
1051     return Instr->getKind() == ShuffleVector;
1052   }
1053 
1054 private:
1055   InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1);
1056 
destroy(Cfg * Func)1057   void destroy(Cfg *Func) override {
1058     Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
1059     Inst::destroy(Func);
1060   }
1061 
1062   ConstantInteger32 **Indexes;
1063   SizeT CurrentIndex = 0;
1064   const SizeT NumIndexes;
1065 };
1066 
1067 /// JumpTable instruction. This represents a jump table that will be stored in
1068 /// the .rodata section. This is used to track and repoint the target CfgNodes
1069 /// which may change, for example due to splitting for phi lowering.
1070 class InstJumpTable : public InstHighLevel {
1071   InstJumpTable() = delete;
1072   InstJumpTable(const InstJumpTable &) = delete;
1073   InstJumpTable &operator=(const InstJumpTable &) = delete;
1074 
1075 public:
create(Cfg * Func,SizeT NumTargets,CfgNode * Default)1076   static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
1077     return new (Func->allocate<InstJumpTable>())
1078         InstJumpTable(Func, NumTargets, Default);
1079   }
addTarget(SizeT TargetIndex,CfgNode * Target)1080   void addTarget(SizeT TargetIndex, CfgNode *Target) {
1081     assert(TargetIndex < NumTargets);
1082     Targets[TargetIndex] = Target;
1083   }
1084   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
getId()1085   SizeT getId() const { return Id; }
getNumTargets()1086   SizeT getNumTargets() const { return NumTargets; }
getTarget(SizeT I)1087   CfgNode *getTarget(SizeT I) const {
1088     assert(I < NumTargets);
1089     return Targets[I];
1090   }
isMemoryWrite()1091   bool isMemoryWrite() const override { return false; }
1092   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1093   static bool classof(const Inst *Instr) {
1094     return Instr->getKind() == JumpTable;
1095   }
1096   // Creates a JumpTableData struct (used for ELF emission) that represents this
1097   // InstJumpTable.
1098   JumpTableData toJumpTableData(Assembler *Asm) const;
1099 
1100   // InstJumpTable is just a placeholder for the switch targets, and it does not
1101   // need to emit any code, so we redefine emit and emitIAS to do nothing.
emit(const Cfg *)1102   void emit(const Cfg *) const override {}
emitIAS(const Cfg *)1103   void emitIAS(const Cfg * /* Func */) const override {}
1104 
getName()1105   const std::string getName() const {
1106     assert(Name.hasStdString());
1107     return Name.toString();
1108   }
1109 
getSectionName()1110   std::string getSectionName() const {
1111     return JumpTableData::createSectionName(FuncName);
1112   }
1113 
1114 private:
1115   InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
destroy(Cfg * Func)1116   void destroy(Cfg *Func) override {
1117     Func->deallocateArrayOf<CfgNode *>(Targets);
1118     Inst::destroy(Func);
1119   }
1120 
1121   const SizeT Id;
1122   const SizeT NumTargets;
1123   CfgNode **Targets;
1124   GlobalString Name; // This JumpTable's name in the output.
1125   GlobalString FuncName;
1126 };
1127 
1128 /// This instruction inserts an unconditional breakpoint.
1129 ///
1130 /// On x86, this assembles into an INT 3 instruction.
1131 ///
1132 /// This instruction is primarily meant for debugging the code generator.
1133 class InstBreakpoint : public InstHighLevel {
1134 public:
1135   InstBreakpoint() = delete;
1136   InstBreakpoint(const InstBreakpoint &) = delete;
1137   InstBreakpoint &operator=(const InstBreakpoint &) = delete;
1138 
1139   explicit InstBreakpoint(Cfg *Func);
isMemoryWrite()1140   bool isMemoryWrite() const override { return false; }
1141 
1142 public:
create(Cfg * Func)1143   static InstBreakpoint *create(Cfg *Func) {
1144     return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
1145   }
1146 
classof(const Inst * Instr)1147   static bool classof(const Inst *Instr) {
1148     return Instr->getKind() == Breakpoint;
1149   }
1150 };
1151 
1152 /// The Target instruction is the base class for all target-specific
1153 /// instructions.
1154 class InstTarget : public Inst {
1155   InstTarget() = delete;
1156   InstTarget(const InstTarget &) = delete;
1157   InstTarget &operator=(const InstTarget &) = delete;
1158 
1159 public:
getEmitInstCount()1160   uint32_t getEmitInstCount() const override { return 1; }
isMemoryWrite()1161   bool isMemoryWrite() const override {
1162     return true; // conservative answer
1163   }
1164   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1165   static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
1166 
1167 protected:
InstTarget(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)1168   InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
1169       : Inst(Func, Kind, MaxSrcs, Dest) {
1170     assert(Kind >= Target);
1171     assert(Kind <= Target_Max);
1172   }
1173 };
1174 
1175 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
1176 
1177 } // end of namespace Ice
1178 
1179 #ifdef PNACL_LLVM
1180 namespace llvm {
1181 
1182 /// Override the default ilist traits so that Inst's private ctor and deleted
1183 /// dtor aren't invoked.
1184 template <>
1185 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
1186   Ice::Inst *createSentinel() const {
1187     return static_cast<Ice::Inst *>(&Sentinel);
1188   }
1189   static void destroySentinel(Ice::Inst *) {}
1190   Ice::Inst *provideInitialHead() const { return createSentinel(); }
1191   Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
1192   static void noteHead(Ice::Inst *, Ice::Inst *) {}
1193   void deleteNode(Ice::Inst *) {}
1194 
1195 private:
1196   mutable ilist_half_node<Ice::Inst> Sentinel;
1197 };
1198 
1199 } // end of namespace llvm
1200 #endif // PNACL_LLVM
1201 
1202 namespace Ice {
1203 
1204 inline InstList::iterator instToIterator(Inst *Instr) {
1205 #ifdef PNACL_LLVM
1206   return Instr;
1207 #else  // !PNACL_LLVM
1208   return Instr->getIterator();
1209 #endif // !PNACL_LLVM
1210 }
1211 
1212 inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; }
1213 
1214 inline const Inst *iteratorToInst(InstList::const_iterator Iter) {
1215   return &*Iter;
1216 }
1217 
1218 inline InstList::iterator
1219 reverseToForwardIterator(InstList::reverse_iterator RI) {
1220 #ifdef PNACL_LLVM
1221   return RI.base();
1222 #else  // !PNACL_LLVM
1223   return ++RI.getReverse();
1224 #endif // !PNACL_LLVM
1225 }
1226 
1227 } // end of namespace Ice
1228 
1229 #endif // SUBZERO_SRC_ICEINST_H
1230