IceInst.h revision 230d4101fb3c591d044406eef27d0ce43ffab53e
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//===----------------------------------------------------------------------===//
99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file
119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// This file declares the Inst class and its target-independent
129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// subclasses, which represent the high-level Vanilla ICE instructions
139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// and map roughly 1:1 to LLVM instructions.
149612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
15f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
16f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
17f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#ifndef SUBZERO_SRC_ICEINST_H
18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define SUBZERO_SRC_ICEINST_H
19f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
207e93c62d7e223b7fd9e6e0889e4b70b635589282John Porto#include "IceCfg.h"
21f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceDefs.h"
22f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.def"
233bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung#include "IceIntrinsics.h"
24f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h"
25f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
26f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be
276ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull// validated for things like valid operand types, valid branch targets, proper
2857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// ordering of Phi and non-Phi instructions, etc. Most of the validity checking
2957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// will be done in the bitcode reader. We need a list of everything that should
3057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// be validated, and tests for each.
31f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
32f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice {
33f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
346ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
356ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
366ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// low-level (target-specific) ICE instructions inherit from InstTarget.
37607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> {
38c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  Inst() = delete;
397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst(const Inst &) = delete;
407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst &operator=(const Inst &) = delete;
417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
42f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
43f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum InstKind {
44f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // Arbitrary (alphabetical) order, except put Unreachable first.
45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Unreachable,
46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Alloca,
47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Arithmetic,
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,
62c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth    Assign,       // not part of LLVM/PNaCl bitcode
639f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    BundleLock,   // not part of LLVM/PNaCl bitcode
649f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    BundleUnlock, // not part of LLVM/PNaCl bitcode
659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeDef,      // not part of LLVM/PNaCl bitcode
669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeUse,      // not part of LLVM/PNaCl bitcode
679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeKill,     // not part of LLVM/PNaCl bitcode
6887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    JumpTable,    // not part of LLVM/PNaCl bitcode
696ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // Anything >= Target is an InstTarget subclass. Note that the value-spaces
706ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // are shared across targets. To avoid confusion over the definition of
716ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // shared values, an object specific to one target should never be passed
726ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // to a different target.
736ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target,
746ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target_Max = std::numeric_limits<uint8_t>::max(),
75f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
766ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  static_assert(Target <= Target_Max, "Must not be above max.");
77f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstKind getKind() const { return Kind; }
78f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
79d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT getNumber() const { return Number; }
80d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void renumber(Cfg *Func);
81e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  enum {
82e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberDeleted = -1,
83e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberSentinel = 0,
84e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberInitial = 2,
85e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberExtended = NumberInitial - 1
86e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  };
87f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
88f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isDeleted() const { return Deleted; }
89f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void setDeleted() { Deleted = true; }
90a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  void setDead(bool Value = true) { Dead = Value; }
91d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void deleteIfDead();
92f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
93f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasSideEffects() const { return HasSideEffects; }
94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
95230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool isDestRedefined() const { return IsDestRedefined; }
96230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  void setDestRedefined() { IsDestRedefined = true; }
974775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth
98f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *getDest() const { return Dest; }
99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getSrcSize() const { return NumSrcs; }
101f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSrc(SizeT I) const {
102f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < getSrcSize());
103f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Srcs[I];
104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
106d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool isLastUse(const Operand *Src) const;
1078e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth  void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
108d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
1096ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Returns a list of out-edges corresponding to a terminator instruction,
1106ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// which is the last instruction of the block. The list must not contain
1116ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// duplicates.
112f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual NodeList getTerminatorEdges() const {
1136ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // All valid terminator instructions override this method. For the default
1146ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // implementation, we assert in case some CfgNode is constructed without a
1156ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // terminator instruction at the end.
116f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    llvm_unreachable(
117f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        "getTerminatorEdges() called on a non-terminator instruction");
118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return NodeList();
119f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
120336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool isUnconditionalBranch() const { return false; }
12157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// If the instruction is a branch-type instruction with OldNode as a target,
12257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// repoint it to NewNode and return true, otherwise return false. Repoint all
12357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instances of OldNode as a target.
12487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
125336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)OldNode;
126336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)NewNode;
127336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    return false;
128336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
129f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
130ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  virtual bool isSimpleAssign() const { return false; }
131ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
1324775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessLightweight(Cfg *Func, LivenessBV &Live);
13357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Calculates liveness for this instruction. Returns true if this instruction
13457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// is (tentatively) still live and should be retained, and false if this
13557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction is (tentatively) dead and should be deleted. The decision is
13657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// tentative until the liveness dataflow algorithm has converged, and then a
13757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// separate pass permanently deletes dead instructions.
138336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
1394775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
1401873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth
1416ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Get the number of native instructions that this instruction ultimately
1426ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// emits. By default, high-level instructions don't result in any native
1436ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instructions, and a target-specific instruction results in a single native
1446ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instruction.
1451873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  virtual uint32_t getEmitInstCount() const { return 0; }
14657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
14757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
14857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
14957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // allow the abstract class Ice::Inst. The method should be declared
15057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
15157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
152dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emit(const Cfg *) const {
153dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth    llvm_unreachable("emit on abstract class");
154dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  }
155dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
156f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void dump(const Cfg *Func) const;
157d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  virtual void dumpExtras(const Cfg *Func) const;
158f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDecorated(const Cfg *Func) const;
1595bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  void emitSources(const Cfg *Func) const;
160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpSources(const Cfg *Func) const;
161f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDest(const Cfg *Func) const;
1625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  virtual bool isRedundantAssign() const { return false; }
163f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
16400741a005cf242d2e9108f7cc7c454246e13741cAndrew Scull  ~Inst() = default;
165f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
166f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected:
167f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
168f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addSource(Operand *Src) {
169f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(Src);
170f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(NumSrcs < MaxSrcs);
171f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Srcs[NumSrcs++] = Src;
172f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
173d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void setLastUse(SizeT VarIndex) {
174d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
175d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
176d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
177d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void resetLastUses() { LiveRangesEnded = 0; }
17857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// The destroy() method lets the instruction cleanly release any memory that
17957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// was allocated via the Cfg's allocator.
180f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
181f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
182f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const InstKind Kind;
1839612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Number is the instruction number for describing live ranges.
184d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT Number;
1859612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Deleted means irrevocably deleted.
186eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Deleted = false;
18757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Dead means one of two things depending on context: (1) pending deletion
18857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// after liveness analysis converges, or (2) marked for deletion during
18957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// lowering due to a folded bool operation.
190eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Dead = false;
19157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// HasSideEffects means the instruction is something like a function call or
19257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// a volatile load that can't be removed even if its Dest variable is not
19357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// live.
194eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool HasSideEffects = false;
195230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// IsDestRedefined indicates that this instruction is not the first
196230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// definition of Dest in the basic block.  The effect is that liveness
197230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// analysis shouldn't consider this instruction to be the start of Dest's
198230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range; rather, there is some other instruction earlier in the basic
199230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// block with the same Dest.  This is maintained because liveness analysis
200230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// has an invariant (primarily for performance reasons) that any Variable's
201230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range recorded in a basic block has at most one start and at most one
202230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// end.
203230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool IsDestRedefined = false;
204f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
205f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *Dest;
206f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const SizeT MaxSrcs; // only used for assert
207eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  SizeT NumSrcs = 0;
208f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand **Srcs;
209f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
2109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// LiveRangesEnded marks which Variables' live ranges end in this
21157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. An instruction can have an arbitrary number of source
21257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands (e.g. a call instruction), and each source operand can contain 0
21357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// or 1 Variable (and target-specific operands could contain more than 1
21457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Variable). All the variables in an instruction are conceptually flattened
21557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and each variable is mapped to one bit position of the LiveRangesEnded bit
21657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
2179612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// tracked this way.
2188072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
219d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  LREndedBits LiveRangesEnded;
220f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
221f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
222b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst {
223c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstHighLevel() = delete;
2240795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel(const InstHighLevel &) = delete;
2250795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel &operator=(const InstHighLevel &) = delete;
226b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
227b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected:
228b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
229b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {}
230b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg * /*Func*/) const override {
231b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emit() called on a non-lowered instruction");
232b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
233b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emitIAS(const Cfg * /*Func*/) const override {
234b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emitIAS() called on a non-lowered instruction");
235b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
236b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth};
237b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
23857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the
23957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment
24057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2.
241b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel {
242c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAlloca() = delete;
2437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca(const InstAlloca &) = delete;
2447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca &operator=(const InstAlloca &) = delete;
2457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
246f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
247f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAlloca *create(Cfg *Func, Operand *ByteCount,
248f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            uint32_t AlignInBytes, Variable *Dest) {
24931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAlloca>())
250f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstAlloca(Func, ByteCount, AlignInBytes, Dest);
251f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
252f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint32_t getAlignInBytes() const { return AlignInBytes; }
253f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSizeInBytes() const { return getSrc(0); }
25455f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool getKnownFrameOffset() const { return KnownFrameOffset; }
25555f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  void setKnownFrameOffset() { KnownFrameOffset = true; }
256b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
257f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
258f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
259f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
260f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
261f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Variable *Dest);
2621bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
263f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const uint32_t AlignInBytes;
26455f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool KnownFrameOffset = false;
265f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
266f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
26757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0)
26857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1).
269b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel {
270c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstArithmetic() = delete;
2717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic(const InstArithmetic &) = delete;
2727b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic &operator=(const InstArithmetic &) = delete;
2737b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
275f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
276f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag,
277f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTARITHMETIC_TABLE
278f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
2794376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
280f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
2815bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
283f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                                Operand *Source1, Operand *Source2) {
28431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstArithmetic>())
285f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstArithmetic(Func, Op, Dest, Source1, Source2);
286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getOp() const { return Op; }
288d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf  static const char *getOpName(OpKind Op);
289f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isCommutative() const;
290b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
291f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) {
292f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Inst->getKind() == Arithmetic;
293f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
296f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
297f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                 Operand *Source2);
298f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
299f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind Op;
300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
30257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is
30357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the
30457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering,
30557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for
30657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction.
307b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel {
308c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAssign() = delete;
3097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign(const InstAssign &) = delete;
3107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign &operator=(const InstAssign &) = delete;
3117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
312f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
313f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
31431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
316b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  bool isSimpleAssign() const override { return true; }
317b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
318f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
323f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
32457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional
32557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches.
326b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel {
327c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBr() = delete;
3287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr(const InstBr &) = delete;
3297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr &operator=(const InstBr &) = delete;
3307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
331f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
33257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
33357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to an unconditional branch.
334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
335f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                        CfgNode *TargetFalse) {
33631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>())
337f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstBr(Func, Source, TargetTrue, TargetFalse);
338f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
3399612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Create an unconditional branch.
340f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, CfgNode *Target) {
34131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>()) InstBr(Func, Target);
342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
343ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  bool isUnconditional() const { return getTargetTrue() == nullptr; }
344f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const {
345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(!isUnconditional());
346f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
347f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetTrue() const { return TargetTrue; }
349f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetFalse() const { return TargetFalse; }
350f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetUnconditional() const {
351f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(isUnconditional());
352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getTargetFalse();
353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
354b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
355336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool isUnconditionalBranch() const override { return isUnconditional(); }
35687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
357b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
358f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
3619612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Conditional branch
362f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
3639612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Unconditional branch
364f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, CfgNode *Target);
365f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
3669612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetFalse; /// Doubles as unconditional branch target
3679612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetTrue;  /// nullptr if unconditional branch
368f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
37057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is
37157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1).
372b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel {
373c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCall() = delete;
3747b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall(const InstCall &) = delete;
3757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall &operator=(const InstCall &) = delete;
3767b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
377f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
3798df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf                          Operand *CallTarget, bool HasTailCall) {
3809612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull    /// Set HasSideEffects to true so that the call instruction can't be
38157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// dead-code eliminated. IntrinsicCalls can override this if the particular
38257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// intrinsic is deletable and has no side-effects.
3833bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    const bool HasSideEffects = true;
3843bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    const InstKind Kind = Inst::Call;
38531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCall>()) InstCall(
3868df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf        Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
387f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
388f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArg(Operand *Arg) { addSource(Arg); }
389f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCallTarget() const { return getSrc(0); }
390f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumArgs() const { return getSrcSize() - 1; }
3928df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool isTailcall() const { return HasTailCall; }
3933ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung  void dump(const Cfg *Func) const override;
394f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
3958df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  Type getReturnType() const;
396f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
3973bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected:
3983bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
3998df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf           bool HasTailCall, bool HasSideEff, InstKind Kind)
400b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
4013bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    HasSideEffects = HasSideEff;
402f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    addSource(CallTarget);
403f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
4043bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
4053bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
4068df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool HasTailCall;
407f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
408f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4099612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation).
410b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel {
411c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCast() = delete;
4127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast(const InstCast &) = delete;
4137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast &operator=(const InstCast &) = delete;
4147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
415f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
416f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
417f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
418f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTCAST_TABLE
419f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4204376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
421f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4225bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
423bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf  static const char *getCastName(OpKind Kind);
424bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf
425f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
426f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source) {
42731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCast>())
428f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstCast(Func, CastKind, Dest, Source);
429f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
430f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getCastKind() const { return CastKind; }
431b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
432f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
433f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
434f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
435f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
4361bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
437f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind CastKind;
438f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
439f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4409612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction.
441b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel {
442c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstExtractElement() = delete;
4437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement(const InstExtractElement &) = delete;
4447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement &operator=(const InstExtractElement &) = delete;
4457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
44649889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
44749889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
44849889239d4c7ab296c7430722d36032d905110b6Matt Wala                                    Operand *Source2) {
44931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstExtractElement>())
45049889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstExtractElement(Func, Dest, Source1, Source2);
45149889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
45249889239d4c7ab296c7430722d36032d905110b6Matt Wala
453b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
45449889239d4c7ab296c7430722d36032d905110b6Matt Wala  static bool classof(const Inst *Inst) {
45549889239d4c7ab296c7430722d36032d905110b6Matt Wala    return Inst->getKind() == ExtractElement;
45649889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
45749889239d4c7ab296c7430722d36032d905110b6Matt Wala
45849889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
45949889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
46049889239d4c7ab296c7430722d36032d905110b6Matt Wala                     Operand *Source2);
46149889239d4c7ab296c7430722d36032d905110b6Matt Wala};
46249889239d4c7ab296c7430722d36032d905110b6Matt Wala
46357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in
46457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
465b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel {
466c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFcmp() = delete;
4677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp(const InstFcmp &) = delete;
4687b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp &operator=(const InstFcmp &) = delete;
4697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
471f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum FCond {
472f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
473f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTFCMP_TABLE
474f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4754376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4775bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
478f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
479f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
48031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFcmp>())
481f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstFcmp(Func, Condition, Dest, Source1, Source2);
482f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  FCond getCondition() const { return Condition; }
484b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
486f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
488f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
4901bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
491f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const FCond Condition;
492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
493f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
49457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in
49557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
496b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel {
497c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIcmp() = delete;
4987b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp(const InstIcmp &) = delete;
4997b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp &operator=(const InstIcmp &) = delete;
5007b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
501f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
502f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum ICond {
503f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
504f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTICMP_TABLE
505f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5064376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
507f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
509f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
510f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
51131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIcmp>())
512f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstIcmp(Func, Condition, Dest, Source1, Source2);
513f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  ICond getCondition() const { return Condition; }
515b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
518f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
519f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5211bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const ICond Condition;
523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
524f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
5259612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction.
526b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel {
527c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstInsertElement() = delete;
5287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement(const InstInsertElement &) = delete;
5297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement &operator=(const InstInsertElement &) = delete;
5307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
53149889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
53249889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
53349889239d4c7ab296c7430722d36032d905110b6Matt Wala                                   Operand *Source2, Operand *Source3) {
53431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstInsertElement>())
53549889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstInsertElement(Func, Dest, Source1, Source2, Source3);
53649889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
53749889239d4c7ab296c7430722d36032d905110b6Matt Wala
538b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
53949889239d4c7ab296c7430722d36032d905110b6Matt Wala  static bool classof(const Inst *Inst) {
54049889239d4c7ab296c7430722d36032d905110b6Matt Wala    return Inst->getKind() == InsertElement;
54149889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
54249889239d4c7ab296c7430722d36032d905110b6Matt Wala
54349889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
54449889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
54549889239d4c7ab296c7430722d36032d905110b6Matt Wala                    Operand *Source2, Operand *Source3);
54649889239d4c7ab296c7430722d36032d905110b6Matt Wala};
54749889239d4c7ab296c7430722d36032d905110b6Matt Wala
54857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and
54957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1).
5503bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall {
551c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIntrinsicCall() = delete;
5527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall(const InstIntrinsicCall &) = delete;
5537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
5547b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
5553bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic:
5563bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
5573bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   Operand *CallTarget,
5583bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   const Intrinsics::IntrinsicInfo &Info) {
55931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIntrinsicCall>())
5603bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
5613bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5623bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static bool classof(const Inst *Inst) {
5633bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    return Inst->getKind() == IntrinsicCall;
5643bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5653bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5663bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
5673bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5683bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
5693bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
5703bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                    Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
5718df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf      : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
5723bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                 Inst::IntrinsicCall),
5733bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        Info(Info) {}
5741bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
5753bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  const Intrinsics::IntrinsicInfo Info;
5763bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung};
5773bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
57857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0).
579b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel {
580c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstLoad() = delete;
5817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad(const InstLoad &) = delete;
5827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad &operator=(const InstLoad &) = delete;
5837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
584f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
58541689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
586c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth                          uint32_t Align = 1) {
58741689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
588c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    (void)Align;
58931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
590f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
591f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSourceAddress() const { return getSrc(0); }
592b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
593f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
594f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
595f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
596f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
597f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
598f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
59957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
60057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I).
601b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel {
602c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstPhi() = delete;
6037b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi(const InstPhi &) = delete;
6047b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi &operator=(const InstPhi &) = delete;
6057b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
606f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
607f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
60831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
609f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
610f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArgument(Operand *Source, CfgNode *Label);
6115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  Operand *getOperandForTarget(CfgNode *Target) const;
61298712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
6134775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
614d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth                          Liveness *Liveness);
615144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Inst *lower(Cfg *Func);
616b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
617f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
618f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
619f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
620f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
621b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
622f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
623f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
624f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
625f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
62657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
62757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// but the Phi instruction is created before InEdges[] is available, so it's
62857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// more complicated to share the list.
629f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode **Labels;
630f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
631f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
63257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is
63357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and
63457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false.
635b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel {
636c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstRet() = delete;
6377b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet(const InstRet &) = delete;
6387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet &operator=(const InstRet &) = delete;
6397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
640f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
641ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
64231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
644f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasRetValue() const { return getSrcSize(); }
645f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getRetValue() const {
646f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(hasRetValue());
647f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
649b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
650b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
651f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
652f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstRet(Cfg *Func, Operand *RetValue);
655f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
6579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction.  The condition, true, and false operands are captured.
658b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel {
659c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSelect() = delete;
6607b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect(const InstSelect &) = delete;
6617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect &operator=(const InstSelect &) = delete;
6627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
663f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
664f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
665f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            Operand *SourceTrue, Operand *SourceFalse) {
66631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSelect>())
667f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
669f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const { return getSrc(0); }
670f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getTrueOperand() const { return getSrc(1); }
671f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getFalseOperand() const { return getSrc(2); }
672b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
674f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
675f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
676f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Operand *Source2);
678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
679f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
68057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data
68157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address.
682b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel {
683c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstStore() = delete;
6847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore(const InstStore &) = delete;
6857b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore &operator=(const InstStore &) = delete;
6867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
687f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
68841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
689e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth                           uint32_t Align = 1) {
69041689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
691e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth    (void)Align;
69231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
693f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
694f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getAddr() const { return getSrc(1); }
695f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getData() const { return getSrc(0); }
696aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  Variable *getRmwBeacon() const;
697e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth  void setRmwBeacon(Variable *Beacon);
698b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
701f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
704f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
70557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0).
706b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel {
707c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSwitch() = delete;
7087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch(const InstSwitch &) = delete;
7097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch &operator=(const InstSwitch &) = delete;
7107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
711f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
712f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            CfgNode *LabelDefault) {
71431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSwitch>())
715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSwitch(Func, NumCases, Source, LabelDefault);
716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getComparison() const { return getSrc(0); }
718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabelDefault() const { return LabelDefault; }
719f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumCases() const { return NumCases; }
720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t getValue(SizeT I) const {
721f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
722f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Values[I];
723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabel(SizeT I) const {
725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Labels[I];
727f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
729b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
73087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
731b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
732f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
734f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
736b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
737f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<uint64_t>(Values);
738f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
742f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *LabelDefault;
7439612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  SizeT NumCases;   /// not including the default case
7449612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  uint64_t *Values; /// size is NumCases
7459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode **Labels; /// size is NumCases
746f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
74857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands.
749b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel {
750c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstUnreachable() = delete;
7517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable(const InstUnreachable &) = delete;
7527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable &operator=(const InstUnreachable &) = delete;
7537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
754f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstUnreachable *create(Cfg *Func) {
75631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
757f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
758b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
759b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
760f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) {
761f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Inst->getKind() == Unreachable;
762f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
763f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
764f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
765c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  explicit InstUnreachable(Cfg *Func);
766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
767f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
76857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction.  There are no operands. Contains an option
7699612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified.
7709f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel {
771c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleLock() = delete;
7729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(const InstBundleLock &) = delete;
7739f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock &operator=(const InstBundleLock &) = delete;
7749f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
7759f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
7769f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  enum Option { Opt_None, Opt_AlignToEnd };
7779f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleLock *create(Cfg *Func, Option BundleOption) {
7789f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleLock>())
7799f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth        InstBundleLock(Func, BundleOption);
7809f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
7819f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
7829f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
7839f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
7849f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option getOption() const { return BundleOption; }
7859f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static bool classof(const Inst *Inst) {
7869f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return Inst->getKind() == BundleLock;
7879f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
7889f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
7899f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
7909f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option BundleOption;
7919f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(Cfg *Func, Option BundleOption);
7929f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
7939f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
79457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands.
7959f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel {
796c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleUnlock() = delete;
7979f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock(const InstBundleUnlock &) = delete;
7989f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
7999f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8009f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
8019f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleUnlock *create(Cfg *Func) {
8029f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
8039f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8049f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8059f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
8069f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8079f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static bool classof(const Inst *Inst) {
8089f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return Inst->getKind() == BundleUnlock;
8099f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8109f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8119f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8129f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  explicit InstBundleUnlock(Cfg *Func);
8139f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8149f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
81557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is
81657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results.
81757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered
81857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags
81957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction.
8209612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
82157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest
82257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest.
82357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its
82457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
82557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized.
826b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel {
827c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeDef() = delete;
8287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef(const InstFakeDef &) = delete;
8297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef &operator=(const InstFakeDef &) = delete;
8307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8315bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
832ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstFakeDef *create(Cfg *Func, Variable *Dest,
833ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth                             Variable *Src = nullptr) {
83431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
8355bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
836b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
837198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
838b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8395bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
8405bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8415bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
8425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
8435bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
84557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the
84657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated.
84757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction
84857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// has no dest, so it can itself never be dead-code eliminated.
849b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel {
850c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeUse() = delete;
8517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse(const InstFakeUse &) = delete;
8527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse &operator=(const InstFakeUse &) = delete;
8537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
8555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static InstFakeUse *create(Cfg *Func, Variable *Src) {
85631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
8575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
858b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
859198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
860b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8615bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
8625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
8645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeUse(Cfg *Func, Variable *Src);
8655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
86757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial
86857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use
86957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the
87057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live
87157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call.
8729612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
87357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills
87457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code
87557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well.
876b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel {
877c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeKill() = delete;
8787b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill(const InstFakeKill &) = delete;
8797b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill &operator=(const InstFakeKill &) = delete;
8807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8815bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
88287ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
88331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
8845bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
8855bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *getLinked() const { return Linked; }
886b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
887198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
888b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8895bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
8905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8915bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
89287ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  InstFakeKill(Cfg *Func, const Inst *Linked);
8935bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8949612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// This instruction is ignored if Linked->isDeleted() is true.
8955bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *Linked;
8965bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
89857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in
89957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes
90057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering.
90187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel {
90287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable() = delete;
90387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(const InstJumpTable &) = delete;
90487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable &operator=(const InstJumpTable &) = delete;
90587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
90687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic:
90787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
90887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    return new (Func->allocate<InstJumpTable>())
90987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull        InstJumpTable(Func, NumTargets, Default);
91087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
91187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void addTarget(SizeT TargetIndex, CfgNode *Target) {
91287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    assert(TargetIndex < NumTargets);
91387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Targets[TargetIndex] = Target;
91487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
91587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
91686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getId() const { return Id; }
91786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getNumTargets() const { return NumTargets; }
91886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  CfgNode *getTarget(SizeT I) const {
91986df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    assert(I < NumTargets);
92086df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return Targets[I];
92186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
92287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void dump(const Cfg *Func) const override;
92387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  static bool classof(const Inst *Inst) { return Inst->getKind() == JumpTable; }
92487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
92586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  static IceString makeName(const IceString &FuncName, SizeT Id) {
92686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return ".L" + FuncName + "$jumptable$__" + std::to_string(Id);
92786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
92886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
92987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate:
93087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
93187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void destroy(Cfg *Func) override {
93287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Func->deallocateArrayOf<CfgNode *>(Targets);
93387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Inst::destroy(Func);
93487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
93587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
93686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  const SizeT Id;
93787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  const SizeT NumTargets;
93887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CfgNode **Targets;
93987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull};
94087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
9419612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific
9429612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions.
9435bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst {
944c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstTarget() = delete;
9450795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget(const InstTarget &) = delete;
9460795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget &operator=(const InstTarget &) = delete;
947b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
9485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
949b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  uint32_t getEmitInstCount() const override { return 1; }
950b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
9525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected:
9545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
9555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {
9565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    assert(Kind >= Target);
9576ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    assert(Kind <= Target_Max);
9585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
9595bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9605bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
961b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
962b3401d27a236b81393092b4d571df473b5bba64bJan Voung
963f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
964f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
965dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm {
966dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
96757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted
96857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked.
969607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <>
970dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
971607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *createSentinel() const {
972607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth    return static_cast<Ice::Inst *>(&Sentinel);
973607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  }
974607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void destroySentinel(Ice::Inst *) {}
975607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *provideInitialHead() const { return createSentinel(); }
976607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
977607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void noteHead(Ice::Inst *, Ice::Inst *) {}
978607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  void deleteNode(Ice::Inst *) {}
979607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
980607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate:
981607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  mutable ilist_half_node<Ice::Inst> Sentinel;
982607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth};
983607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
984dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm
985dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
986f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H
987