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