IceInst.h revision bf170370805150026104a9e42e07fb17b0971ad7
1f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===//
2f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
3f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//                        The Subzero Code Generator
4f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
5f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// This file is distributed under the University of Illinois Open Source
6f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// License. See LICENSE.TXT for details.
7f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
8f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
9f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
10f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// This file declares the Inst class and its target-independent
11f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// subclasses, which represent the high-level Vanilla ICE instructions
12f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// and map roughly 1:1 to LLVM instructions.
13f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
14f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
15f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
16f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#ifndef SUBZERO_SRC_ICEINST_H
17f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define SUBZERO_SRC_ICEINST_H
18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
19f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceDefs.h"
20f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.def"
213bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung#include "IceIntrinsics.h"
22f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h"
23f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
24f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be
25f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// validated for things like valid operand types, valid branch
26f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// targets, proper ordering of Phi and non-Phi instructions, etc.
27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Most of the validity checking will be done in the bitcode reader.
28f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// We need a list of everything that should be validated, and tests
29f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// for each.
30f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
31f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice {
32f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
33b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// Base instruction class for ICE.  Inst has two subclasses:
34b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// InstHighLevel and InstTarget.  High-level ICE instructions inherit
35b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// from InstHighLevel, and low-level (target-specific) ICE
36b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// instructions inherit from InstTarget.
37607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> {
387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst(const Inst &) = delete;
397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst &operator=(const Inst &) = delete;
407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
41f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
42f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum InstKind {
43f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // Arbitrary (alphabetical) order, except put Unreachable first.
44f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Unreachable,
45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Alloca,
46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Arithmetic,
47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Assign, // not part of LLVM/PNaCl bitcode
48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Br,
49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Call,
50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Cast,
5149889239d4c7ab296c7430722d36032d905110b6Matt Wala    ExtractElement,
52f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Fcmp,
53f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Icmp,
543bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    IntrinsicCall,
5549889239d4c7ab296c7430722d36032d905110b6Matt Wala    InsertElement,
56f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Load,
57f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Phi,
58f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Ret,
59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Select,
60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Store,
615bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Switch,
625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    FakeDef,  // not part of LLVM/PNaCl bitcode
635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    FakeUse,  // not part of LLVM/PNaCl bitcode
645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    FakeKill, // not part of LLVM/PNaCl bitcode
655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Target    // target-specific low-level ICE
665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth              // Anything >= Target is an InstTarget subclass.
67f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
68f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstKind getKind() const { return Kind; }
69f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
70d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT getNumber() const { return Number; }
71d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void renumber(Cfg *Func);
72e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  enum {
73e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberDeleted = -1,
74e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberSentinel = 0,
75e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberInitial = 2,
76e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberExtended = NumberInitial - 1
77e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  };
78f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
79f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isDeleted() const { return Deleted; }
80f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void setDeleted() { Deleted = true; }
81d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void deleteIfDead();
82f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
83f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasSideEffects() const { return HasSideEffects; }
84f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
854775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  bool isDestNonKillable() const { return IsDestNonKillable; }
864775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void setDestNonKillable() { IsDestNonKillable = true; }
874775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth
88f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *getDest() const { return Dest; }
89f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
90f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getSrcSize() const { return NumSrcs; }
91f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSrc(SizeT I) const {
92f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < getSrcSize());
93f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Srcs[I];
94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
96d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool isLastUse(const Operand *Src) const;
97d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
98f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Returns a list of out-edges corresponding to a terminator
99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // instruction, which is the last instruction of the block.
100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual NodeList getTerminatorEdges() const {
101f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // All valid terminator instructions override this method.  For
102f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // the default implementation, we assert in case some CfgNode
103f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // is constructed without a terminator instruction at the end.
104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    llvm_unreachable(
105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        "getTerminatorEdges() called on a non-terminator instruction");
106f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return NodeList();
107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
108336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool isUnconditionalBranch() const { return false; }
109336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // If the instruction is a branch-type instruction with OldNode as a
110336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // target, repoint it to NewNode and return true, otherwise return
111336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // false.  Only repoint one instance, even if the instruction has
112336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // multiple instances of OldNode as a target.
113336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
114336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)OldNode;
115336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)NewNode;
116336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    return false;
117336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
119ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  virtual bool isSimpleAssign() const { return false; }
120ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
1214775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessLightweight(Cfg *Func, LivenessBV &Live);
122336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // Calculates liveness for this instruction.  Returns true if this
123336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // instruction is (tentatively) still live and should be retained,
124336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // and false if this instruction is (tentatively) dead and should be
125336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // deleted.  The decision is tentative until the liveness dataflow
126336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // algorithm has converged, and then a separate pass permanently
127336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // deletes dead instructions.
128336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
1294775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
1301873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth
1311873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // Get the number of native instructions that this instruction
1321873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // ultimately emits.  By default, high-level instructions don't
1331873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // result in any native instructions, and a target-specific
1341873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // instruction results in a single native instruction.
1351873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  virtual uint32_t getEmitInstCount() const { return 0; }
136dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // TODO(stichnot): Change Inst back to abstract once the g++ build
137dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // issue is fixed.  llvm::ilist<Ice::Inst> doesn't work under g++
138dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // because the resize(size_t, Ice::Inst) method is incorrectly
139dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // declared and thus doesn't allow the abstract class Ice::Inst.
140dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // The method should be declared resize(size_t, const Ice::Inst &).
141dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // virtual void emit(const Cfg *Func) const = 0;
142dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // virtual void emitIAS(const Cfg *Func) const = 0;
143dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emit(const Cfg *) const {
144dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth    llvm_unreachable("emit on abstract class");
145dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  }
146dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
147f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void dump(const Cfg *Func) const;
148d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  virtual void dumpExtras(const Cfg *Func) const;
149f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDecorated(const Cfg *Func) const;
1505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  void emitSources(const Cfg *Func) const;
151f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpSources(const Cfg *Func) const;
152f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDest(const Cfg *Func) const;
1535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  virtual bool isRedundantAssign() const { return false; }
154f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
155f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual ~Inst() {}
156f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
157f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected:
158f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
159f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addSource(Operand *Src) {
160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(Src);
161f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(NumSrcs < MaxSrcs);
162f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Srcs[NumSrcs++] = Src;
163f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
164d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void setLastUse(SizeT VarIndex) {
165d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
166d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
167d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
168d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void resetLastUses() { LiveRangesEnded = 0; }
169f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // The destroy() method lets the instruction cleanly release any
170f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // memory that was allocated via the Cfg's allocator.
171f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
172f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
173f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const InstKind Kind;
174f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Number is the instruction number for describing live ranges.
175d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT Number;
176f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Deleted means irrevocably deleted.
177f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool Deleted;
178d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // Dead means pending deletion after liveness analysis converges.
179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool Dead;
180f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // HasSideEffects means the instruction is something like a function
181f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // call or a volatile load that can't be removed even if its Dest
182f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // variable is not live.
183f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool HasSideEffects;
1844775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  // IsDestNonKillable means that liveness analysis shouldn't consider
1854775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  // this instruction to kill the Dest variable.  This is used when
1864775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  // lowering produces two assignments to the same variable.
1874775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  bool IsDestNonKillable;
188f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
189f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *Dest;
190f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const SizeT MaxSrcs; // only used for assert
191f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT NumSrcs;
192f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand **Srcs;
193f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
194d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // LiveRangesEnded marks which Variables' live ranges end in this
195d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // instruction.  An instruction can have an arbitrary number of
196d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // source operands (e.g. a call instruction), and each source
197d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // operand can contain 0 or 1 Variable (and target-specific operands
198d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // could contain more than 1 Variable).  All the variables in an
199d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // instruction are conceptually flattened and each variable is
200d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // mapped to one bit position of the LiveRangesEnded bit vector.
201d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // Only the first CHAR_BIT * sizeof(LREndedBits) variables are
202d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // tracked this way.
203d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
204d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  LREndedBits LiveRangesEnded;
205f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
206f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
207b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst {
2080795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel(const InstHighLevel &) = delete;
2090795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel &operator=(const InstHighLevel &) = delete;
210b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
211b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected:
212b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
213b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {}
214b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg * /*Func*/) const override {
215b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emit() called on a non-lowered instruction");
216b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
217b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emitIAS(const Cfg * /*Func*/) const override {
218b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emitIAS() called on a non-lowered instruction");
219b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
220b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstHighLevel() override {}
221b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth};
222b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
223f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Alloca instruction.  This captures the size in bytes as getSrc(0),
224f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// and the required alignment in bytes.  The alignment must be either
225f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 0 (no alignment required) or a power of 2.
226b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel {
2277b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca(const InstAlloca &) = delete;
2287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca &operator=(const InstAlloca &) = delete;
2297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
230f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
231f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAlloca *create(Cfg *Func, Operand *ByteCount,
232f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            uint32_t AlignInBytes, Variable *Dest) {
233f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstAlloca>())
234f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstAlloca(Func, ByteCount, AlignInBytes, Dest);
235f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
236f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint32_t getAlignInBytes() const { return AlignInBytes; }
237f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSizeInBytes() const { return getSrc(0); }
238b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
239f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
240f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
241f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
242f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
243f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Variable *Dest);
244b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstAlloca() override {}
245f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const uint32_t AlignInBytes;
246f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
247f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
248f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Binary arithmetic instruction.  The source operands are captured in
249f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0) and getSrc(1).
250b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel {
2517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic(const InstArithmetic &) = delete;
2527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic &operator=(const InstArithmetic &) = delete;
2537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
254f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
256f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag,
257f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTARITHMETIC_TABLE
258f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
2594376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
260f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
2615bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
262f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
263f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                                Operand *Source1, Operand *Source2) {
264f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstArithmetic>())
265f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstArithmetic(Func, Op, Dest, Source1, Source2);
266f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
267f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getOp() const { return Op; }
268d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf  static const char *getOpName(OpKind Op);
269f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isCommutative() const;
270b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
271f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) {
272f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Inst->getKind() == Arithmetic;
273f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
275f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
276f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
277f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                 Operand *Source2);
278b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstArithmetic() override {}
279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
280f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind Op;
281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
283f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Assignment instruction.  The source operand is captured in
284f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0).  This is not part of the LLVM bitcode, but is a useful
285f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// abstraction for some of the lowering.  E.g., if Phi instruction
286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// lowering happens before target lowering, or for representing an
287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Inttoptr instruction, or as an intermediate step for lowering a
288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Load instruction.
289b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel {
2907b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign(const InstAssign &) = delete;
2917b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign &operator=(const InstAssign &) = delete;
2927b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
293f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstAssign>())
296f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstAssign(Func, Dest, Source);
297f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
298b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  bool isSimpleAssign() const override { return true; }
299b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
302f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
304b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstAssign() override {}
305f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
306f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
307f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Branch instruction.  This represents both conditional and
308f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// unconditional branches.
309b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel {
3107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr(const InstBr &) = delete;
3117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr &operator=(const InstBr &) = delete;
3127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
313f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
314f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Create a conditional branch.  If TargetTrue==TargetFalse, it is
315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // optimized to an unconditional branch.
316f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
317f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                        CfgNode *TargetFalse) {
318f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstBr>())
319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstBr(Func, Source, TargetTrue, TargetFalse);
320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Create an unconditional branch.
322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, CfgNode *Target) {
323f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstBr>()) InstBr(Func, Target);
324f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
325f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isUnconditional() const { return getTargetTrue() == NULL; }
326f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const {
327f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(!isUnconditional());
328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
329f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
330f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetTrue() const { return TargetTrue; }
331f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetFalse() const { return TargetFalse; }
332f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetUnconditional() const {
333f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(isUnconditional());
334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getTargetFalse();
335f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
336b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
337336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool isUnconditionalBranch() const override { return isUnconditional(); }
338336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
339b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
340f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
341f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
343f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Conditional branch
344f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Unconditional branch
346f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, CfgNode *Target);
347b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstBr() override {}
348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
349336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  CfgNode *TargetFalse; // Doubles as unconditional branch target
350336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  CfgNode *TargetTrue;  // NULL if unconditional branch
351f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Call instruction.  The call target is captured as getSrc(0), and
354f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// arg I is captured as getSrc(I+1).
355b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel {
3567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall(const InstCall &) = delete;
3577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall &operator=(const InstCall &) = delete;
3587b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
3618df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf                          Operand *CallTarget, bool HasTailCall) {
3623bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    // Set HasSideEffects to true so that the call instruction can't be
3633bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    // dead-code eliminated. IntrinsicCalls can override this if the
3643bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    // particular intrinsic is deletable and has no side-effects.
3653bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    const bool HasSideEffects = true;
3663bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    const InstKind Kind = Inst::Call;
3678df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf    return new (Func->allocateInst<InstCall>()) InstCall(
3688df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf        Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
370f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArg(Operand *Arg) { addSource(Arg); }
371f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCallTarget() const { return getSrc(0); }
372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
373f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumArgs() const { return getSrcSize() - 1; }
3748df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool isTailcall() const { return HasTailCall; }
375b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const;
376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
3778df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  Type getReturnType() const;
378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
3793bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected:
3803bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
3818df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf           bool HasTailCall, bool HasSideEff, InstKind Kind)
382b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
3833bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    HasSideEffects = HasSideEff;
384f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    addSource(CallTarget);
385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
386b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstCall() override {}
3873bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
3883bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
3898df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool HasTailCall;
390f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
392f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Cast instruction (a.k.a. conversion operation).
393b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel {
3947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast(const InstCast &) = delete;
3957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast &operator=(const InstCast &) = delete;
3967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
397f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
398f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
399f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
400f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTCAST_TABLE
401f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4024376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
403f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
405bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf  static const char *getCastName(OpKind Kind);
406bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf
407f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
408f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source) {
409f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstCast>())
410f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstCast(Func, CastKind, Dest, Source);
411f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
412f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getCastKind() const { return CastKind; }
413b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
414f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
415f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
416f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
417f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
418b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstCast() override {}
419f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind CastKind;
420f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
421f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
42249889239d4c7ab296c7430722d36032d905110b6Matt Wala// ExtractElement instruction.
423b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel {
4247b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement(const InstExtractElement &) = delete;
4257b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement &operator=(const InstExtractElement &) = delete;
4267b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
42749889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
42849889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
42949889239d4c7ab296c7430722d36032d905110b6Matt Wala                                    Operand *Source2) {
43049889239d4c7ab296c7430722d36032d905110b6Matt Wala    return new (Func->allocateInst<InstExtractElement>())
43149889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstExtractElement(Func, Dest, Source1, Source2);
43249889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
43349889239d4c7ab296c7430722d36032d905110b6Matt Wala
434b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
43549889239d4c7ab296c7430722d36032d905110b6Matt Wala  static bool classof(const Inst *Inst) {
43649889239d4c7ab296c7430722d36032d905110b6Matt Wala    return Inst->getKind() == ExtractElement;
43749889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
43849889239d4c7ab296c7430722d36032d905110b6Matt Wala
43949889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
44049889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
44149889239d4c7ab296c7430722d36032d905110b6Matt Wala                     Operand *Source2);
442b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstExtractElement() override {}
44349889239d4c7ab296c7430722d36032d905110b6Matt Wala};
44449889239d4c7ab296c7430722d36032d905110b6Matt Wala
445f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Floating-point comparison instruction.  The source operands are
446f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// captured in getSrc(0) and getSrc(1).
447b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel {
4487b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp(const InstFcmp &) = delete;
4497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp &operator=(const InstFcmp &) = delete;
4507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
451f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
452f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum FCond {
453f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
454f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTFCMP_TABLE
455f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4564376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
457f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
459f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
460f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
461f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstFcmp>())
462f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstFcmp(Func, Condition, Dest, Source1, Source2);
463f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
464f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  FCond getCondition() const { return Condition; }
465b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
466f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
467f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
468f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
469f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
471b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstFcmp() override {}
472f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const FCond Condition;
473f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
474f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
475f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Integer comparison instruction.  The source operands are captured
476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// in getSrc(0) and getSrc(1).
477b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel {
4787b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp(const InstIcmp &) = delete;
4797b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp &operator=(const InstIcmp &) = delete;
4807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
481f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
482f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum ICond {
483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
484f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTICMP_TABLE
485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4864376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4885bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
490f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
491f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstIcmp>())
492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstIcmp(Func, Condition, Dest, Source1, Source2);
493f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
494f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  ICond getCondition() const { return Condition; }
495b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
496f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
497f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
498f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
499f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
500f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
501b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstIcmp() override {}
502f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const ICond Condition;
503f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
504f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
50549889239d4c7ab296c7430722d36032d905110b6Matt Wala// InsertElement instruction.
506b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel {
5077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement(const InstInsertElement &) = delete;
5087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement &operator=(const InstInsertElement &) = delete;
5097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
51049889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
51149889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
51249889239d4c7ab296c7430722d36032d905110b6Matt Wala                                   Operand *Source2, Operand *Source3) {
51349889239d4c7ab296c7430722d36032d905110b6Matt Wala    return new (Func->allocateInst<InstInsertElement>())
51449889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstInsertElement(Func, Dest, Source1, Source2, Source3);
51549889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
51649889239d4c7ab296c7430722d36032d905110b6Matt Wala
517b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
51849889239d4c7ab296c7430722d36032d905110b6Matt Wala  static bool classof(const Inst *Inst) {
51949889239d4c7ab296c7430722d36032d905110b6Matt Wala    return Inst->getKind() == InsertElement;
52049889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
52149889239d4c7ab296c7430722d36032d905110b6Matt Wala
52249889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
52349889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
52449889239d4c7ab296c7430722d36032d905110b6Matt Wala                    Operand *Source2, Operand *Source3);
525b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstInsertElement() override {}
52649889239d4c7ab296c7430722d36032d905110b6Matt Wala};
52749889239d4c7ab296c7430722d36032d905110b6Matt Wala
5283bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung// Call to an intrinsic function.  The call target is captured as getSrc(0),
5293bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung// and arg I is captured as getSrc(I+1).
5303bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall {
5317b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall(const InstIntrinsicCall &) = delete;
5327b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
5337b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
5343bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic:
5353bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
5363bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   Operand *CallTarget,
5373bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   const Intrinsics::IntrinsicInfo &Info) {
5383bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    return new (Func->allocateInst<InstIntrinsicCall>())
5393bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
5403bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5413bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static bool classof(const Inst *Inst) {
5423bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    return Inst->getKind() == IntrinsicCall;
5433bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5443bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5453bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
5463bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5473bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
5483bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
5493bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                    Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
5508df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf      : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
5513bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                 Inst::IntrinsicCall),
5523bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        Info(Info) {}
553b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstIntrinsicCall() override {}
5543bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  const Intrinsics::IntrinsicInfo Info;
5553bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung};
5563bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
557f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Load instruction.  The source address is captured in getSrc(0).
558b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel {
5597b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad(const InstLoad &) = delete;
5607b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad &operator=(const InstLoad &) = delete;
5617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
562f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
56341689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
564c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth                          uint32_t Align = 1) {
56541689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
566c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    (void)Align;
567f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstLoad>())
568f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstLoad(Func, Dest, SourceAddr);
569f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
570f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSourceAddress() const { return getSrc(0); }
571b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
572f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
573f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
574f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
575f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
576b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstLoad() override {}
577f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
578f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
579f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Phi instruction.  For incoming edge I, the node is Labels[I] and
580f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// the Phi source operand is getSrc(I).
581b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel {
5827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi(const InstPhi &) = delete;
5837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi &operator=(const InstPhi &) = delete;
5847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
585f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
586f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
587f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
588f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
589f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArgument(Operand *Source, CfgNode *Label);
5905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  Operand *getOperandForTarget(CfgNode *Target) const;
59198712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
5924775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
593d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth                          Liveness *Liveness);
594144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Inst *lower(Cfg *Func);
595b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
596f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
597f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
598f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
599f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
600b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
601f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
602f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
603f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
604b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstPhi() override {}
605f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
606f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Labels[] duplicates the InEdges[] information in the enclosing
607f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // CfgNode, but the Phi instruction is created before InEdges[]
608f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // is available, so it's more complicated to share the list.
609f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode **Labels;
610f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
611f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
612f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Ret instruction.  The return value is captured in getSrc(0), but if
613f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// there is no return value (void-type function), then
614f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrcSize()==0 and hasRetValue()==false.
615b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel {
6167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet(const InstRet &) = delete;
6177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet &operator=(const InstRet &) = delete;
6187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
619f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
620f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstRet *create(Cfg *Func, Operand *RetValue = NULL) {
621f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstRet>()) InstRet(Func, RetValue);
622f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
623f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasRetValue() const { return getSrcSize(); }
624f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getRetValue() const {
625f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(hasRetValue());
626f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
627f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
628b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
629b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
630f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
631f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
632f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
633f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstRet(Cfg *Func, Operand *RetValue);
634b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstRet() override {}
635f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
636f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
637f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Select instruction.  The condition, true, and false operands are captured.
638b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel {
6397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect(const InstSelect &) = delete;
6407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect &operator=(const InstSelect &) = delete;
6417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
644f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            Operand *SourceTrue, Operand *SourceFalse) {
645f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstSelect>())
646f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
647f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const { return getSrc(0); }
649f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getTrueOperand() const { return getSrc(1); }
650f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getFalseOperand() const { return getSrc(2); }
651b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
652f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
655f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Operand *Source2);
657b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstSelect() override {}
658f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
659f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
660f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Store instruction.  The address operand is captured, along with the
661f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// data operand to be stored into the address.
662b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel {
6637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore(const InstStore &) = delete;
6647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore &operator=(const InstStore &) = delete;
6657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
66741689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
66841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf                           uint32_t align = 1) {
66941689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
67041689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    (void)align;
671f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstStore>()) InstStore(Func, Data, Addr);
672f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getAddr() const { return getSrc(1); }
674f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getData() const { return getSrc(0); }
675b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
676f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
679f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
680b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstStore() override {}
681f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
683f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Switch instruction.  The single source operand is captured as
684f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0).
685b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel {
6867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch(const InstSwitch &) = delete;
6877b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch &operator=(const InstSwitch &) = delete;
6887b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
689f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
690f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
691f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            CfgNode *LabelDefault) {
692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstSwitch>())
693f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSwitch(Func, NumCases, Source, LabelDefault);
694f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
695f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getComparison() const { return getSrc(0); }
696f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabelDefault() const { return LabelDefault; }
697f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumCases() const { return NumCases; }
698f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t getValue(SizeT I) const {
699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Values[I];
701f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabel(SizeT I) const {
703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
704f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Labels[I];
705f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
707b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
708336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
709b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
710f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
711f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
712f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
714b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<uint64_t>(Values);
716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
719b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstSwitch() override {}
720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
721f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *LabelDefault;
722f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT NumCases;   // not including the default case
723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t *Values; // size is NumCases
724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode **Labels; // size is NumCases
725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
727f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Unreachable instruction.  This is a terminator instruction with no
728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// operands.
729b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel {
7307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable(const InstUnreachable &) = delete;
7317b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable &operator=(const InstUnreachable &) = delete;
7327b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
734f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstUnreachable *create(Cfg *Func) {
735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return new (Func->allocateInst<InstUnreachable>()) InstUnreachable(Func);
736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
737b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
738b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) {
740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Inst->getKind() == Unreachable;
741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
742f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
743f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
744f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstUnreachable(Cfg *Func);
745b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstUnreachable() override {}
746f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
7485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// FakeDef instruction.  This creates a fake definition of a variable,
7495bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// which is how we represent the case when an instruction produces
7505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// multiple results.  This doesn't happen with high-level ICE
7515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// instructions, but might with lowered instructions.  For example,
7525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// this would be a way to represent condition flags being modified by
7535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// an instruction.
7545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth//
7555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// It's generally useful to set the optional source operand to be the
7565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest variable of the instruction that actually produces the FakeDef
7575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest.  Otherwise, the original instruction could be dead-code
7585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// eliminated if its dest operand is unused, and therefore the FakeDef
7595bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest wouldn't be properly initialized.
760b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel {
7617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef(const InstFakeDef &) = delete;
7627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef &operator=(const InstFakeDef &) = delete;
7637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
7645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
7655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) {
7665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    return new (Func->allocateInst<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
7675bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
768b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
769198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
770b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7715bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
7725bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
7735bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
7745bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
775b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstFakeDef() override {}
7765bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
7775bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
7785bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// FakeUse instruction.  This creates a fake use of a variable, to
7795bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// keep the instruction that produces that variable from being
7805bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dead-code eliminated.  This is useful in a variety of lowering
7815bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// situations.  The FakeUse instruction has no dest, so it can itself
7825bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// never be dead-code eliminated.
783b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel {
7847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse(const InstFakeUse &) = delete;
7857b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse &operator=(const InstFakeUse &) = delete;
7867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
7875bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
7885bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static InstFakeUse *create(Cfg *Func, Variable *Src) {
7895bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    return new (Func->allocateInst<InstFakeUse>()) InstFakeUse(Func, Src);
7905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
791b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
792198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
793b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7945bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
7955bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
7965bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
7975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeUse(Cfg *Func, Variable *Src);
798b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstFakeUse() override {}
7995bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
80187ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// FakeKill instruction.  This "kills" a set of variables by modeling
80287ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// a trivial live range at this instruction for each (implicit)
80387ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// variable.  The primary use is to indicate that scratch registers
80487ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// are killed after a call, so that the register allocator won't
80587ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// assign a scratch register to a variable whose live range spans a
80687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// call.
8075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth//
8085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// The FakeKill instruction also holds a pointer to the instruction
8095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// that kills the set of variables, so that if that linked instruction
8105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// gets dead-code eliminated, the FakeKill instruction will as well.
811b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel {
8127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill(const InstFakeKill &) = delete;
8137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill &operator=(const InstFakeKill &) = delete;
8147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
81687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
81787ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth    return new (Func->allocateInst<InstFakeKill>()) InstFakeKill(Func, Linked);
8185bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
8195bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *getLinked() const { return Linked; }
820b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
821198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
822b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8235bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
8245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8255bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
82687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  InstFakeKill(Cfg *Func, const Inst *Linked);
827b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstFakeKill() override {}
8285bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8295bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  // This instruction is ignored if Linked->isDeleted() is true.
8305bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *Linked;
8315bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8325bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8335bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// The Target instruction is the base class for all target-specific
8345bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// instructions.
8355bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst {
8360795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget(const InstTarget &) = delete;
8370795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget &operator=(const InstTarget &) = delete;
838b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
8395bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
840b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  uint32_t getEmitInstCount() const override { return 1; }
841b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
8435bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected:
8455bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
8465bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {
8475bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    assert(Kind >= Target);
8485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
849b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  ~InstTarget() override {}
8505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
852f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
853f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
854dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm {
855dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
856607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth// Override the default ilist traits so that Inst's private ctor and
857607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth// deleted dtor aren't invoked.
858607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <>
859dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
860607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *createSentinel() const {
861607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth    return static_cast<Ice::Inst *>(&Sentinel);
862607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  }
863607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void destroySentinel(Ice::Inst *) {}
864607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *provideInitialHead() const { return createSentinel(); }
865607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
866607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void noteHead(Ice::Inst *, Ice::Inst *) {}
867607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  void deleteNode(Ice::Inst *) {}
868607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
869607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate:
870607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  mutable ilist_half_node<Ice::Inst> Sentinel;
871607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth};
872607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
873dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm
874dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
875f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H
876