IceInst.h revision 8cfeb69e17190d3bfe22a8a1cbd7679a114d68cf
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
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the Inst class and its target-independent subclasses.
1292a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth///
1392a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// These represent the high-level Vanilla ICE instructions and map roughly 1:1
1492a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// to LLVM instructions.
159612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
16f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
17f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#ifndef SUBZERO_SRC_ICEINST_H
19f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define SUBZERO_SRC_ICEINST_H
20f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
217e93c62d7e223b7fd9e6e0889e4b70b635589282John Porto#include "IceCfg.h"
22f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceDefs.h"
23f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.def"
243bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung#include "IceIntrinsics.h"
25f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h"
26f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be
286ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull// validated for things like valid operand types, valid branch targets, proper
2957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// ordering of Phi and non-Phi instructions, etc. Most of the validity checking
3057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// will be done in the bitcode reader. We need a list of everything that should
3157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// be validated, and tests for each.
32f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
33f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice {
34f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
356ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
366ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
376ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// low-level (target-specific) ICE instructions inherit from InstTarget.
38607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> {
39c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  Inst() = delete;
407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst(const Inst &) = delete;
417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst &operator=(const Inst &) = delete;
427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
43f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
44f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum InstKind {
45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // Arbitrary (alphabetical) order, except put Unreachable first.
46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Unreachable,
47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Alloca,
48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Arithmetic,
49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Br,
50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Call,
51f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Cast,
5249889239d4c7ab296c7430722d36032d905110b6Matt Wala    ExtractElement,
53f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Fcmp,
54f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Icmp,
553bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    IntrinsicCall,
5649889239d4c7ab296c7430722d36032d905110b6Matt Wala    InsertElement,
57f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Load,
58f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Phi,
59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Ret,
60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Select,
61f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Store,
625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Switch,
63c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth    Assign,       // not part of LLVM/PNaCl bitcode
649f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    BundleLock,   // not part of LLVM/PNaCl bitcode
659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    BundleUnlock, // not part of LLVM/PNaCl bitcode
669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeDef,      // not part of LLVM/PNaCl bitcode
679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeUse,      // not part of LLVM/PNaCl bitcode
689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeKill,     // not part of LLVM/PNaCl bitcode
6987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    JumpTable,    // not part of LLVM/PNaCl bitcode
706ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // Anything >= Target is an InstTarget subclass. Note that the value-spaces
716ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // are shared across targets. To avoid confusion over the definition of
726ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // shared values, an object specific to one target should never be passed
736ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // to a different target.
746ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target,
756ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target_Max = std::numeric_limits<uint8_t>::max(),
76f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
776ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  static_assert(Target <= Target_Max, "Must not be above max.");
78f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstKind getKind() const { return Kind; }
79e37076a176e04eee0f35058ccd2109754c193015Eric Holk  virtual IceString getInstName() const;
80f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
81d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT getNumber() const { return Number; }
82d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void renumber(Cfg *Func);
83e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  enum {
84e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberDeleted = -1,
85e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberSentinel = 0,
86e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberInitial = 2,
87e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberExtended = NumberInitial - 1
88e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  };
89f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
90f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isDeleted() const { return Deleted; }
91f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void setDeleted() { Deleted = true; }
92a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  void setDead(bool Value = true) { Dead = Value; }
93d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void deleteIfDead();
94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasSideEffects() const { return HasSideEffects; }
96f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
97230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool isDestRedefined() const { return IsDestRedefined; }
98230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  void setDestRedefined() { IsDestRedefined = true; }
994775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth
100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *getDest() const { return Dest; }
101f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
102f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getSrcSize() const { return NumSrcs; }
103f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSrc(SizeT I) const {
104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < getSrcSize());
105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Srcs[I];
106f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
108d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool isLastUse(const Operand *Src) const;
1098e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth  void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
110d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
1116ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Returns a list of out-edges corresponding to a terminator instruction,
1126ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// which is the last instruction of the block. The list must not contain
1136ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// duplicates.
114f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual NodeList getTerminatorEdges() const {
1156ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // All valid terminator instructions override this method. For the default
1166ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // implementation, we assert in case some CfgNode is constructed without a
1176ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // terminator instruction at the end.
118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    llvm_unreachable(
119f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        "getTerminatorEdges() called on a non-terminator instruction");
120f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return NodeList();
121f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
122336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool isUnconditionalBranch() const { return false; }
12357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// If the instruction is a branch-type instruction with OldNode as a target,
12457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// repoint it to NewNode and return true, otherwise return false. Repoint all
12557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instances of OldNode as a target.
12687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
127336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)OldNode;
128336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)NewNode;
129336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    return false;
130336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
131f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
13228b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// Returns true if the instruction is equivalent to a simple
13328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// "var_dest=var_src" assignment where the dest and src are both variables.
13428b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  virtual bool isVarAssign() const { return false; }
135ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
1364775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessLightweight(Cfg *Func, LivenessBV &Live);
13757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Calculates liveness for this instruction. Returns true if this instruction
13857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// is (tentatively) still live and should be retained, and false if this
13957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction is (tentatively) dead and should be deleted. The decision is
14057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// tentative until the liveness dataflow algorithm has converged, and then a
14157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// separate pass permanently deletes dead instructions.
142336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
1434775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
1441873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth
1456ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Get the number of native instructions that this instruction ultimately
1466ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// emits. By default, high-level instructions don't result in any native
1476ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instructions, and a target-specific instruction results in a single native
1486ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instruction.
1491873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  virtual uint32_t getEmitInstCount() const { return 0; }
15057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
15157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
15257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
15357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // allow the abstract class Ice::Inst. The method should be declared
15457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
15557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
156dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emit(const Cfg *) const {
157dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth    llvm_unreachable("emit on abstract class");
158dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  }
159dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void dump(const Cfg *Func) const;
161d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  virtual void dumpExtras(const Cfg *Func) const;
162f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDecorated(const Cfg *Func) const;
1635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  void emitSources(const Cfg *Func) const;
164f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpSources(const Cfg *Func) const;
165f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDest(const Cfg *Func) const;
1665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  virtual bool isRedundantAssign() const { return false; }
167f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
16800741a005cf242d2e9108f7cc7c454246e13741cAndrew Scull  ~Inst() = default;
169f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
170f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected:
171f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
172f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addSource(Operand *Src) {
173f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(Src);
174f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(NumSrcs < MaxSrcs);
175f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Srcs[NumSrcs++] = Src;
176f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
177d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void setLastUse(SizeT VarIndex) {
178d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
180d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
181d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void resetLastUses() { LiveRangesEnded = 0; }
18257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// The destroy() method lets the instruction cleanly release any memory that
18357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// was allocated via the Cfg's allocator.
184f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
185f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
186f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const InstKind Kind;
1879612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Number is the instruction number for describing live ranges.
188d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT Number;
1899612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Deleted means irrevocably deleted.
190eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Deleted = false;
19157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Dead means one of two things depending on context: (1) pending deletion
19257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// after liveness analysis converges, or (2) marked for deletion during
19357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// lowering due to a folded bool operation.
194eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Dead = false;
19557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// HasSideEffects means the instruction is something like a function call or
19657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// a volatile load that can't be removed even if its Dest variable is not
19757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// live.
198eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool HasSideEffects = false;
199230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// IsDestRedefined indicates that this instruction is not the first
200230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// definition of Dest in the basic block.  The effect is that liveness
201230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// analysis shouldn't consider this instruction to be the start of Dest's
202230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range; rather, there is some other instruction earlier in the basic
203230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// block with the same Dest.  This is maintained because liveness analysis
204230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// has an invariant (primarily for performance reasons) that any Variable's
205230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range recorded in a basic block has at most one start and at most one
206230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// end.
207230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool IsDestRedefined = false;
208f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
209f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *Dest;
210f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const SizeT MaxSrcs; // only used for assert
211eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  SizeT NumSrcs = 0;
212f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand **Srcs;
213f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
2149612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// LiveRangesEnded marks which Variables' live ranges end in this
21557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. An instruction can have an arbitrary number of source
21657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands (e.g. a call instruction), and each source operand can contain 0
21757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// or 1 Variable (and target-specific operands could contain more than 1
21857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Variable). All the variables in an instruction are conceptually flattened
21957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and each variable is mapped to one bit position of the LiveRangesEnded bit
22057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
2219612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// tracked this way.
2228072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
223d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  LREndedBits LiveRangesEnded;
224f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
225f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
226b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst {
227c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstHighLevel() = delete;
2280795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel(const InstHighLevel &) = delete;
2290795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel &operator=(const InstHighLevel &) = delete;
230b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
231b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected:
232b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
233b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {}
234b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg * /*Func*/) const override {
235b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emit() called on a non-lowered instruction");
236b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
237b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emitIAS(const Cfg * /*Func*/) const override {
238b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emitIAS() called on a non-lowered instruction");
239b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
240b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth};
241b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
24257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the
24357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment
24457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2.
245b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel {
246c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAlloca() = delete;
2477b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca(const InstAlloca &) = delete;
2487b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca &operator=(const InstAlloca &) = delete;
2497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
250f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
2512f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
2522f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr                            uint32_t AlignInBytes) {
25331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAlloca>())
2542f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr        InstAlloca(Func, Dest, ByteCount, AlignInBytes);
255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
256f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint32_t getAlignInBytes() const { return AlignInBytes; }
257f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSizeInBytes() const { return getSrc(0); }
25855f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool getKnownFrameOffset() const { return KnownFrameOffset; }
25955f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  void setKnownFrameOffset() { KnownFrameOffset = true; }
260b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
2618cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
262f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
263f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
2642f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
2652f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr             uint32_t AlignInBytes);
2661bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
267f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const uint32_t AlignInBytes;
26855f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool KnownFrameOffset = false;
269f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
270f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
27157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0)
27257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1).
273b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel {
274c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstArithmetic() = delete;
2757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic(const InstArithmetic &) = delete;
2767b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic &operator=(const InstArithmetic &) = delete;
2777b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
278f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
280f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag,
281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTARITHMETIC_TABLE
282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
2834376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
284f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
2855bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                                Operand *Source1, Operand *Source2) {
28831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstArithmetic>())
289f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstArithmetic(Func, Op, Dest, Source1, Source2);
290f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
291f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getOp() const { return Op; }
292e37076a176e04eee0f35058ccd2109754c193015Eric Holk
293e37076a176e04eee0f35058ccd2109754c193015Eric Holk  virtual IceString getInstName() const override;
294e37076a176e04eee0f35058ccd2109754c193015Eric Holk
295d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf  static const char *getOpName(OpKind Op);
296f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isCommutative() const;
297b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
2988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
2998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Arithmetic;
300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
302f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
304f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                 Operand *Source2);
305f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
306f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind Op;
307f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
308f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
30957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is
31057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the
31157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering,
31257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for
31357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction.
314b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel {
315c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAssign() = delete;
3167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign(const InstAssign &) = delete;
3177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign &operator=(const InstAssign &) = delete;
3187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
32131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
32328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  bool isVarAssign() const override;
324b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
326f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
327f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
329f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
330f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
33157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional
33257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches.
333b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel {
334c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBr() = delete;
3357b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr(const InstBr &) = delete;
3367b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr &operator=(const InstBr &) = delete;
3377b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
338f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
33957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
34057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to an unconditional branch.
341f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                        CfgNode *TargetFalse) {
34331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>())
344f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstBr(Func, Source, TargetTrue, TargetFalse);
345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
3469612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Create an unconditional branch.
347f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, CfgNode *Target) {
34831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>()) InstBr(Func, Target);
349f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
350ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  bool isUnconditional() const { return getTargetTrue() == nullptr; }
351f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const {
352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(!isUnconditional());
353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
354f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
355f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetTrue() const { return TargetTrue; }
356f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetFalse() const { return TargetFalse; }
357f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetUnconditional() const {
358f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(isUnconditional());
359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getTargetFalse();
360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
361b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
362336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool isUnconditionalBranch() const override { return isUnconditional(); }
36387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
364b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3658cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
366f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
367f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
3689612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Conditional branch
369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
3709612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Unconditional branch
371f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, CfgNode *Target);
372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
3739612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetFalse; /// Doubles as unconditional branch target
3749612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetTrue;  /// nullptr if unconditional branch
375f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
37757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is
37857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1).
379b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel {
380c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCall() = delete;
3817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall(const InstCall &) = delete;
3827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall &operator=(const InstCall &) = delete;
3837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
384f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
3865e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          Operand *CallTarget, bool HasTailCall,
3875e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          bool IsTargetHelperCall = false) {
3889612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull    /// Set HasSideEffects to true so that the call instruction can't be
38957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// dead-code eliminated. IntrinsicCalls can override this if the particular
39057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// intrinsic is deletable and has no side-effects.
3915bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr bool HasSideEffects = true;
3925bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr InstKind Kind = Inst::Call;
3935e0a8a71b75ec56981883587612b16f7c1635a03John Porto    return new (Func->allocate<InstCall>())
3945e0a8a71b75ec56981883587612b16f7c1635a03John Porto        InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
3955e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 IsTargetHelperCall, HasSideEffects, Kind);
396f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
397f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArg(Operand *Arg) { addSource(Arg); }
398f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCallTarget() const { return getSrc(0); }
399f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
400f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumArgs() const { return getSrcSize() - 1; }
4018df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool isTailcall() const { return HasTailCall; }
4025e0a8a71b75ec56981883587612b16f7c1635a03John Porto  bool isTargetHelperCall() const { return IsTargetHelperCall; }
4033ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung  void dump(const Cfg *Func) const override;
4048cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
4058df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  Type getReturnType() const;
406f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4073bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected:
4083bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
4095e0a8a71b75ec56981883587612b16f7c1635a03John Porto           bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
4105e0a8a71b75ec56981883587612b16f7c1635a03John Porto           InstKind Kind)
4115e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
4125e0a8a71b75ec56981883587612b16f7c1635a03John Porto        IsTargetHelperCall(IsTargetHelperCall) {
4133bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    HasSideEffects = HasSideEff;
414f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    addSource(CallTarget);
415f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
4163bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
4173bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
4185e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool HasTailCall;
4195e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool IsTargetHelperCall;
420f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
421f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4229612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation).
423b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel {
424c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCast() = delete;
4257b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast(const InstCast &) = delete;
4267b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast &operator=(const InstCast &) = delete;
4277b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
428f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
429f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
430f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
431f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTCAST_TABLE
432f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4334376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
434f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4355bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
436bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf  static const char *getCastName(OpKind Kind);
437bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf
438f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
439f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source) {
44031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCast>())
441f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstCast(Func, CastKind, Dest, Source);
442f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
443f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getCastKind() const { return CastKind; }
444b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4458cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
446f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
447f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
448f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
4491bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
450f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind CastKind;
451f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
452f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4539612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction.
454b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel {
455c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstExtractElement() = delete;
4567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement(const InstExtractElement &) = delete;
4577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement &operator=(const InstExtractElement &) = delete;
4587b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
45949889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
46049889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
46149889239d4c7ab296c7430722d36032d905110b6Matt Wala                                    Operand *Source2) {
46231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstExtractElement>())
46349889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstExtractElement(Func, Dest, Source1, Source2);
46449889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
46549889239d4c7ab296c7430722d36032d905110b6Matt Wala
466b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4678cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
4688cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == ExtractElement;
46949889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
47049889239d4c7ab296c7430722d36032d905110b6Matt Wala
47149889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
47249889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
47349889239d4c7ab296c7430722d36032d905110b6Matt Wala                     Operand *Source2);
47449889239d4c7ab296c7430722d36032d905110b6Matt Wala};
47549889239d4c7ab296c7430722d36032d905110b6Matt Wala
47657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in
47757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
478b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel {
479c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFcmp() = delete;
4807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp(const InstFcmp &) = delete;
4817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp &operator=(const InstFcmp &) = delete;
4827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
484f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum FCond {
485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
486f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTFCMP_TABLE
487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4884376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
491f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
49331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFcmp>())
494f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstFcmp(Func, Condition, Dest, Source1, Source2);
495f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
496f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  FCond getCondition() const { return Condition; }
497b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
499f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
500f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
501f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
502f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5031bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
504f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const FCond Condition;
505f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
506f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
50757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in
50857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
509b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel {
510c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIcmp() = delete;
5117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp(const InstIcmp &) = delete;
5127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp &operator=(const InstIcmp &) = delete;
5137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
515f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum ICond {
516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTICMP_TABLE
518f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5194376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5215bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
52431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIcmp>())
525f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstIcmp(Func, Condition, Dest, Source1, Source2);
526f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
527f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  ICond getCondition() const { return Condition; }
528b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5298cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
530f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
531f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
533f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5341bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
535f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const ICond Condition;
536f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
537f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
5389612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction.
539b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel {
540c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstInsertElement() = delete;
5417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement(const InstInsertElement &) = delete;
5427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement &operator=(const InstInsertElement &) = delete;
5437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
54449889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
54549889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
54649889239d4c7ab296c7430722d36032d905110b6Matt Wala                                   Operand *Source2, Operand *Source3) {
54731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstInsertElement>())
54849889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstInsertElement(Func, Dest, Source1, Source2, Source3);
54949889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
55049889239d4c7ab296c7430722d36032d905110b6Matt Wala
551b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
5538cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == InsertElement;
55449889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
55549889239d4c7ab296c7430722d36032d905110b6Matt Wala
55649889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
55749889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
55849889239d4c7ab296c7430722d36032d905110b6Matt Wala                    Operand *Source2, Operand *Source3);
55949889239d4c7ab296c7430722d36032d905110b6Matt Wala};
56049889239d4c7ab296c7430722d36032d905110b6Matt Wala
56157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and
56257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1).
5633bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall {
564c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIntrinsicCall() = delete;
5657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall(const InstIntrinsicCall &) = delete;
5667b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
5677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
5683bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic:
5693bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
5703bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   Operand *CallTarget,
5713bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   const Intrinsics::IntrinsicInfo &Info) {
57231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIntrinsicCall>())
5733bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
5743bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5758cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
5768cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == IntrinsicCall;
5773bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5783bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5793bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
5803bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5813bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
5823bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
5833bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                    Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
5845e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
5855e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 Info.HasSideEffects, Inst::IntrinsicCall),
5863bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        Info(Info) {}
5871bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
5883bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  const Intrinsics::IntrinsicInfo Info;
5893bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung};
5903bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
59157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0).
592b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel {
593c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstLoad() = delete;
5947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad(const InstLoad &) = delete;
5957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad &operator=(const InstLoad &) = delete;
5967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
597f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
59841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
599c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth                          uint32_t Align = 1) {
60041689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
601c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    (void)Align;
60231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
603f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
604f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSourceAddress() const { return getSrc(0); }
605b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
607f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
608f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
609f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
610f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
611f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
61257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
61357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I).
614b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel {
615c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstPhi() = delete;
6167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi(const InstPhi &) = delete;
6177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi &operator=(const InstPhi &) = delete;
6187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
619f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
620f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
62131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
622f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
623f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArgument(Operand *Source, CfgNode *Label);
6245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  Operand *getOperandForTarget(CfgNode *Target) const;
62598712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
6264775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
627d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth                          Liveness *Liveness);
628144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Inst *lower(Cfg *Func);
629b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6308cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
631f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
632f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
633f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
634b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
635f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
636f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
637f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
638f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
63957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
64057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// but the Phi instruction is created before InEdges[] is available, so it's
64157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// more complicated to share the list.
642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode **Labels;
643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
644f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
64557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is
64657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and
64757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false.
648b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel {
649c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstRet() = delete;
6507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet(const InstRet &) = delete;
6517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet &operator=(const InstRet &) = delete;
6527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
654ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
65531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
657f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasRetValue() const { return getSrcSize(); }
658f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getRetValue() const {
659f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(hasRetValue());
660f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
661f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
662b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
663b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6648cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
665f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
667f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstRet(Cfg *Func, Operand *RetValue);
668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
669f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
6709612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction.  The condition, true, and false operands are captured.
671b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel {
672c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSelect() = delete;
6737b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect(const InstSelect &) = delete;
6747b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect &operator=(const InstSelect &) = delete;
6757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
676f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            Operand *SourceTrue, Operand *SourceFalse) {
67931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSelect>())
680f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
681f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const { return getSrc(0); }
683f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getTrueOperand() const { return getSrc(1); }
684f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getFalseOperand() const { return getSrc(2); }
685b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6868cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
687f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
688f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
689f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
690f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Operand *Source2);
691f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
69357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data
69457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address.
695b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel {
696c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstStore() = delete;
6977b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore(const InstStore &) = delete;
6987b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore &operator=(const InstStore &) = delete;
6997b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
70141689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
702e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth                           uint32_t Align = 1) {
70341689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
704e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth    (void)Align;
70531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
707f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getAddr() const { return getSrc(1); }
708f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getData() const { return getSrc(0); }
709aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  Variable *getRmwBeacon() const;
710e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth  void setRmwBeacon(Variable *Beacon);
711b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7128cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
714f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
71857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0).
719b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel {
720c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSwitch() = delete;
7217b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch(const InstSwitch &) = delete;
7227b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch &operator=(const InstSwitch &) = delete;
7237b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            CfgNode *LabelDefault) {
72731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSwitch>())
728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSwitch(Func, NumCases, Source, LabelDefault);
729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
730f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getComparison() const { return getSrc(0); }
731f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabelDefault() const { return LabelDefault; }
732f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumCases() const { return NumCases; }
733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t getValue(SizeT I) const {
734f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Values[I];
736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
737f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabel(SizeT I) const {
738f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Labels[I];
740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
742b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
74387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
744b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7458cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
746f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
748f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
749b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
750f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<uint64_t>(Values);
751f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
752f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
753f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
754f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *LabelDefault;
7569612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  SizeT NumCases;   /// not including the default case
7579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  uint64_t *Values; /// size is NumCases
7589612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode **Labels; /// size is NumCases
759f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
760f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
76157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands.
762b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel {
763c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstUnreachable() = delete;
7647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable(const InstUnreachable &) = delete;
7657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable &operator=(const InstUnreachable &) = delete;
7667b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
767f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
768f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstUnreachable *create(Cfg *Func) {
76931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
770f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
771b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
772b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7738cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
7748cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Unreachable;
775f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
776f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
777f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
778c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  explicit InstUnreachable(Cfg *Func);
779f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
780f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
78157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction.  There are no operands. Contains an option
7829612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified.
7839f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel {
784c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleLock() = delete;
7859f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(const InstBundleLock &) = delete;
7869f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock &operator=(const InstBundleLock &) = delete;
7879f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
7889f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
78956958cb33d3c1d045f2844408d825442d523f59fJohn Porto  enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
7909f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleLock *create(Cfg *Func, Option BundleOption) {
7919f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleLock>())
7929f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth        InstBundleLock(Func, BundleOption);
7939f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
7949f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
7959f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
7969f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
7979f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option getOption() const { return BundleOption; }
7988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
7998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleLock;
8009f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8019f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8029f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8039f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option BundleOption;
8049f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(Cfg *Func, Option BundleOption);
8059f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8069f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
80757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands.
8089f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel {
809c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleUnlock() = delete;
8109f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock(const InstBundleUnlock &) = delete;
8119f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
8129f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8139f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
8149f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleUnlock *create(Cfg *Func) {
8159f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
8169f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8179f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8189f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
8199f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8208cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8218cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleUnlock;
8229f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8239f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8249f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8259f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  explicit InstBundleUnlock(Cfg *Func);
8269f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8279f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
82857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is
82957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results.
83057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered
83157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags
83257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction.
8339612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
83457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest
83557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest.
83657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its
83757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
83857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized.
839b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel {
840c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeDef() = delete;
8417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef(const InstFakeDef &) = delete;
8427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef &operator=(const InstFakeDef &) = delete;
8437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
845ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstFakeDef *create(Cfg *Func, Variable *Dest,
846ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth                             Variable *Src = nullptr) {
84731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
8485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
849b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
850198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
851b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
8535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
8555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
8565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
85857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the
85957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated.
86057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction
8618ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// has no dest, so it can itself never be dead-code eliminated.  A weight can
8628ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// be provided to provide extra bias to the register allocator - for simplicity
8638ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// of implementation, weight=N is handled by holding N copies of the variable
8648ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// as source operands.
865b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel {
866c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeUse() = delete;
8677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse(const InstFakeUse &) = delete;
8687b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse &operator=(const InstFakeUse &) = delete;
8697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8705bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
8718ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
8728ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth    return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
8735bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
874b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
875198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
876b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8778cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
8785bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8795bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
8808ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
8815bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8825bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
88357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial
88457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use
88557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the
88657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live
88757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call.
8889612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
88957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills
89057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code
89157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well.
892b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel {
893c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeKill() = delete;
8947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill(const InstFakeKill &) = delete;
8957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill &operator=(const InstFakeKill &) = delete;
8967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
89887ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
89931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
9005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *getLinked() const { return Linked; }
902b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
903198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
904b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9058cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
9068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == FakeKill;
9078cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
9085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
91087ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  InstFakeKill(Cfg *Func, const Inst *Linked);
9115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// This instruction is ignored if Linked->isDeleted() is true.
9135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *Linked;
9145bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
91657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in
91757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes
91857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering.
91987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel {
92087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable() = delete;
92187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(const InstJumpTable &) = delete;
92287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable &operator=(const InstJumpTable &) = delete;
92387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
92487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic:
92587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
92687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    return new (Func->allocate<InstJumpTable>())
92787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull        InstJumpTable(Func, NumTargets, Default);
92887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
92987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void addTarget(SizeT TargetIndex, CfgNode *Target) {
93087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    assert(TargetIndex < NumTargets);
93187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Targets[TargetIndex] = Target;
93287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
93387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
93486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getId() const { return Id; }
93586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getNumTargets() const { return NumTargets; }
93686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  CfgNode *getTarget(SizeT I) const {
93786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    assert(I < NumTargets);
93886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return Targets[I];
93986df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
94087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void dump(const Cfg *Func) const override;
9418cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
9428cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == JumpTable;
9438cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
94487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
94586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  static IceString makeName(const IceString &FuncName, SizeT Id) {
94686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return ".L" + FuncName + "$jumptable$__" + std::to_string(Id);
94786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
94886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
94987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate:
95087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
95187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void destroy(Cfg *Func) override {
95287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Func->deallocateArrayOf<CfgNode *>(Targets);
95387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Inst::destroy(Func);
95487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
95587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
95686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  const SizeT Id;
95787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  const SizeT NumTargets;
95887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CfgNode **Targets;
95987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull};
96087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
9619612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific
9629612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions.
9635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst {
964c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstTarget() = delete;
9650795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget(const InstTarget &) = delete;
9660795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget &operator=(const InstTarget &) = delete;
967b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
9685bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
969b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  uint32_t getEmitInstCount() const override { return 1; }
970b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9718cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
9725bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9735bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected:
9745bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
9755bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {
9765bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    assert(Kind >= Target);
9776ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    assert(Kind <= Target_Max);
9785bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
9795bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9805bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
981b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
982b3401d27a236b81393092b4d571df473b5bba64bJan Voung
983f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
984f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
985dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm {
986dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
98757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted
98857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked.
989607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <>
990dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
991607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *createSentinel() const {
992607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth    return static_cast<Ice::Inst *>(&Sentinel);
993607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  }
994607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void destroySentinel(Ice::Inst *) {}
995607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *provideInitialHead() const { return createSentinel(); }
996607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
997607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void noteHead(Ice::Inst *, Ice::Inst *) {}
998607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  void deleteNode(Ice::Inst *) {}
999607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1000607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate:
1001607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  mutable ilist_half_node<Ice::Inst> Sentinel;
1002607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth};
1003607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1004dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm
1005dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
1006f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H
1007