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"
25a47c11c7f17022050043d69c0802241e0747a056John Porto#include "IceOperand.h"
26030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto#include "IceSwitchLowering.h"
27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h"
28f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
29f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be
306ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull// validated for things like valid operand types, valid branch targets, proper
3157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// ordering of Phi and non-Phi instructions, etc. Most of the validity checking
3257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// will be done in the bitcode reader. We need a list of everything that should
3357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// be validated, and tests for each.
34f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
35f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice {
36f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
376ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
386ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
396ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// low-level (target-specific) ICE instructions inherit from InstTarget.
40607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> {
41c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  Inst() = delete;
427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst(const Inst &) = delete;
437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst &operator=(const Inst &) = delete;
447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum InstKind {
47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // Arbitrary (alphabetical) order, except put Unreachable first.
48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Unreachable,
49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Alloca,
50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Arithmetic,
51f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Br,
52f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Call,
53f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Cast,
5449889239d4c7ab296c7430722d36032d905110b6Matt Wala    ExtractElement,
55f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Fcmp,
56f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Icmp,
573bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    IntrinsicCall,
5849889239d4c7ab296c7430722d36032d905110b6Matt Wala    InsertElement,
59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Load,
60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Phi,
61f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Ret,
62f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Select,
63f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Store,
645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Switch,
65a47c11c7f17022050043d69c0802241e0747a056John Porto    Assign,        // not part of LLVM/PNaCl bitcode
66a47c11c7f17022050043d69c0802241e0747a056John Porto    Breakpoint,    // not part of LLVM/PNaCl bitcode
67a47c11c7f17022050043d69c0802241e0747a056John Porto    BundleLock,    // not part of LLVM/PNaCl bitcode
68a47c11c7f17022050043d69c0802241e0747a056John Porto    BundleUnlock,  // not part of LLVM/PNaCl bitcode
69a47c11c7f17022050043d69c0802241e0747a056John Porto    FakeDef,       // not part of LLVM/PNaCl bitcode
70a47c11c7f17022050043d69c0802241e0747a056John Porto    FakeUse,       // not part of LLVM/PNaCl bitcode
71a47c11c7f17022050043d69c0802241e0747a056John Porto    FakeKill,      // not part of LLVM/PNaCl bitcode
72a47c11c7f17022050043d69c0802241e0747a056John Porto    JumpTable,     // not part of LLVM/PNaCl bitcode
73a47c11c7f17022050043d69c0802241e0747a056John Porto    ShuffleVector, // not part of LLVM/PNaCl bitcode
746ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // Anything >= Target is an InstTarget subclass. Note that the value-spaces
756ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // are shared across targets. To avoid confusion over the definition of
766ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // shared values, an object specific to one target should never be passed
776ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // to a different target.
786ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target,
796ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target_Max = std::numeric_limits<uint8_t>::max(),
80f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
816ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  static_assert(Target <= Target_Max, "Must not be above max.");
82f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstKind getKind() const { return Kind; }
83467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  virtual const char *getInstName() const;
84f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
85d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT getNumber() const { return Number; }
86d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void renumber(Cfg *Func);
87e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  enum {
88e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberDeleted = -1,
89e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberSentinel = 0,
90e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberInitial = 2,
91e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberExtended = NumberInitial - 1
92e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  };
93f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isDeleted() const { return Deleted; }
95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void setDeleted() { Deleted = true; }
96a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  void setDead(bool Value = true) { Dead = Value; }
97d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void deleteIfDead();
98f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasSideEffects() const { return HasSideEffects; }
100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
101230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool isDestRedefined() const { return IsDestRedefined; }
102230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  void setDestRedefined() { IsDestRedefined = true; }
1034775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth
104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *getDest() const { return Dest; }
105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
10645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  SizeT getSrcSize() const { return Srcs.size(); }
107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSrc(SizeT I) const {
108f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < getSrcSize());
109f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Srcs[I];
110f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
111032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee  void replaceSource(SizeT Index, Operand *Replacement) {
11245f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee    assert(Index < getSrcSize());
113032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    assert(!isDeleted());
114032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    Srcs[Index] = Replacement;
115032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee  }
116f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
117d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool isLastUse(const Operand *Src) const;
1188e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth  void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
119d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
1206ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Returns a list of out-edges corresponding to a terminator instruction,
1216ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// which is the last instruction of the block. The list must not contain
1226ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// duplicates.
123f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual NodeList getTerminatorEdges() const {
1246ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // All valid terminator instructions override this method. For the default
1256ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // implementation, we assert in case some CfgNode is constructed without a
1266ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // terminator instruction at the end.
127f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    llvm_unreachable(
128f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        "getTerminatorEdges() called on a non-terminator instruction");
129f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return NodeList();
130f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
131336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool isUnconditionalBranch() const { return false; }
13257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// If the instruction is a branch-type instruction with OldNode as a target,
13357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// repoint it to NewNode and return true, otherwise return false. Repoint all
13457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instances of OldNode as a target.
13587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
136336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)OldNode;
137336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)NewNode;
138336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    return false;
139336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
140f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
14128b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// Returns true if the instruction is equivalent to a simple
14228b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// "var_dest=var_src" assignment where the dest and src are both variables.
14328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  virtual bool isVarAssign() const { return false; }
144ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
145f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// Returns true if the instruction has a possible side effect of changing
146f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// memory, in which case a memory load should not be reordered with respect
147f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// to this instruction.  It should really be pure virtual, but we can't
148f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// because of g++ and llvm::ilist<>, so we implement it as
149f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// report_fatal_error().
150f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  virtual bool isMemoryWrite() const;
151f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth
152b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// Returns true if the (target-specific) instruction represents an
153b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// intra-block label, i.e. branch target.  This is meant primarily for
154b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// Cfg::splitLocalVars().
155b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  virtual bool isLabel() const { return false; }
156b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// If the (target-specific) instruction represents an intra-block branch to
157b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// some Label instruction, return that Label branch target instruction;
158b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// otherwise return nullptr.
159b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; }
160b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth
1614775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessLightweight(Cfg *Func, LivenessBV &Live);
16257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Calculates liveness for this instruction. Returns true if this instruction
16357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// is (tentatively) still live and should be retained, and false if this
16457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction is (tentatively) dead and should be deleted. The decision is
16557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// tentative until the liveness dataflow algorithm has converged, and then a
16657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// separate pass permanently deletes dead instructions.
167336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
1684775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
1691873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth
1706ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Get the number of native instructions that this instruction ultimately
1716ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// emits. By default, high-level instructions don't result in any native
1726ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instructions, and a target-specific instruction results in a single native
1736ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instruction.
1741873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  virtual uint32_t getEmitInstCount() const { return 0; }
17557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
17657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
17757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
17857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // allow the abstract class Ice::Inst. The method should be declared
17957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
18057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
181dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emit(const Cfg *) const {
182dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth    llvm_unreachable("emit on abstract class");
183dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  }
184dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
185f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void dump(const Cfg *Func) const;
186d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  virtual void dumpExtras(const Cfg *Func) const;
187f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDecorated(const Cfg *Func) const;
1885bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  void emitSources(const Cfg *Func) const;
189f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpSources(const Cfg *Func) const;
190f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDest(const Cfg *Func) const;
1915bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  virtual bool isRedundantAssign() const { return false; }
192f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
193fc707ffe812339bddf4ca28fbe8c01045e2b42d6Sean Klein  virtual ~Inst() = default;
1947cd926d6d4f401dd3595e0682f48ede3e04ac7f7Manasij Mukherjee  void replaceDest(Variable *Var) { Dest = Var; }
195f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
196038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens  void operator delete(void *Ptr, std::size_t Size) {
197038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens    assert(CfgAllocatorTraits::current() != nullptr);
198038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens    CfgAllocatorTraits::current()->Deallocate(Ptr, Size);
199038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens    llvm::report_fatal_error("Inst unexpectedly deleted");
200038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens  }
201038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens
202f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected:
203f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
204f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addSource(Operand *Src) {
205f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(Src);
20645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee    Srcs.push_back(Src);
207f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
208d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void setLastUse(SizeT VarIndex) {
209d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
210d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
211d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
212d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void resetLastUses() { LiveRangesEnded = 0; }
21357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// The destroy() method lets the instruction cleanly release any memory that
21457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// was allocated via the Cfg's allocator.
21545f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  virtual void destroy(Cfg *) {}
216f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
217f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const InstKind Kind;
2189612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Number is the instruction number for describing live ranges.
219d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT Number;
2209612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Deleted means irrevocably deleted.
221eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Deleted = false;
22257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Dead means one of two things depending on context: (1) pending deletion
22357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// after liveness analysis converges, or (2) marked for deletion during
22457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// lowering due to a folded bool operation.
225eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Dead = false;
22657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// HasSideEffects means the instruction is something like a function call or
22757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// a volatile load that can't be removed even if its Dest variable is not
22857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// live.
229eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool HasSideEffects = false;
230230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// IsDestRedefined indicates that this instruction is not the first
231230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// definition of Dest in the basic block.  The effect is that liveness
232230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// analysis shouldn't consider this instruction to be the start of Dest's
233230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range; rather, there is some other instruction earlier in the basic
234230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// block with the same Dest.  This is maintained because liveness analysis
235230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// has an invariant (primarily for performance reasons) that any Variable's
236230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range recorded in a basic block has at most one start and at most one
237230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// end.
238230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool IsDestRedefined = false;
239f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
240f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *Dest;
241f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const SizeT MaxSrcs; // only used for assert
24245f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee
24345f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  CfgVector<Operand *> Srcs;
244f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
2459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// LiveRangesEnded marks which Variables' live ranges end in this
24657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. An instruction can have an arbitrary number of source
24757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands (e.g. a call instruction), and each source operand can contain 0
24857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// or 1 Variable (and target-specific operands could contain more than 1
24957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Variable). All the variables in an instruction are conceptually flattened
25057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and each variable is mapped to one bit position of the LiveRangesEnded bit
25157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
2529612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// tracked this way.
2538072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
254d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  LREndedBits LiveRangesEnded;
255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
256f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
257b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst {
258c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstHighLevel() = delete;
2590795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel(const InstHighLevel &) = delete;
2600795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel &operator=(const InstHighLevel &) = delete;
261b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
262b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected:
263b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
264b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {}
265b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg * /*Func*/) const override {
266b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emit() called on a non-lowered instruction");
267b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
268b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emitIAS(const Cfg * /*Func*/) const override {
269b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emitIAS() called on a non-lowered instruction");
270b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
271b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth};
272b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
27357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the
27457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment
27557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2.
276b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel {
277c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAlloca() = delete;
2787b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca(const InstAlloca &) = delete;
2797b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca &operator=(const InstAlloca &) = delete;
2807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
2822f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
2832f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr                            uint32_t AlignInBytes) {
28431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAlloca>())
2852f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr        InstAlloca(Func, Dest, ByteCount, AlignInBytes);
286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint32_t getAlignInBytes() const { return AlignInBytes; }
288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSizeInBytes() const { return getSrc(0); }
28955f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool getKnownFrameOffset() const { return KnownFrameOffset; }
29055f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  void setKnownFrameOffset() { KnownFrameOffset = true; }
291f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
292b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
2938cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
2962f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
2972f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr             uint32_t AlignInBytes);
2981bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
299f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const uint32_t AlignInBytes;
30055f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool KnownFrameOffset = false;
301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
302f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
30357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0)
30457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1).
305b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel {
306c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstArithmetic() = delete;
3077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic(const InstArithmetic &) = delete;
3087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic &operator=(const InstArithmetic &) = delete;
3097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
310f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
311f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
312f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag,
313f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTARITHMETIC_TABLE
314f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
3154376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
316f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
3175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
318f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                                Operand *Source1, Operand *Source2) {
32031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstArithmetic>())
321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstArithmetic(Func, Op, Dest, Source1, Source2);
322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
323f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getOp() const { return Op; }
324e37076a176e04eee0f35058ccd2109754c193015Eric Holk
325467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  virtual const char *getInstName() const override;
326e37076a176e04eee0f35058ccd2109754c193015Eric Holk
327d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf  static const char *getOpName(OpKind Op);
328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isCommutative() const;
329f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
330b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3318cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
3328cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Arithmetic;
333f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
335f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
336f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
337f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                 Operand *Source2);
338f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
339f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind Op;
340f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
341f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
34257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is
34357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the
34457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering,
34557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for
34657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction.
347b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel {
348c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAssign() = delete;
3497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign(const InstAssign &) = delete;
3507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign &operator=(const InstAssign &) = delete;
3517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
35431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
355f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
35628b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  bool isVarAssign() const override;
357f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
358b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3598cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
361f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
362f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
363f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
364f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
36557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional
36657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches.
367b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel {
368c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBr() = delete;
3697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr(const InstBr &) = delete;
3707b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr &operator=(const InstBr &) = delete;
3717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
37357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
37457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to an unconditional branch.
375f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                        CfgNode *TargetFalse) {
37731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>())
378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstBr(Func, Source, TargetTrue, TargetFalse);
379f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
3809612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Create an unconditional branch.
381f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, CfgNode *Target) {
38231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>()) InstBr(Func, Target);
383f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
384ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  bool isUnconditional() const { return getTargetTrue() == nullptr; }
385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const {
386f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(!isUnconditional());
387f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
388f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
389f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetTrue() const { return TargetTrue; }
390f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetFalse() const { return TargetFalse; }
391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetUnconditional() const {
392f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(isUnconditional());
393f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getTargetFalse();
394f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
395b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
396336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool isUnconditionalBranch() const override { return isUnconditional(); }
39787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
398f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
399b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4008cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
401f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
402f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
4039612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Conditional branch
404f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
4059612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Unconditional branch
406f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, CfgNode *Target);
407f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4089612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetFalse; /// Doubles as unconditional branch target
4099612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetTrue;  /// nullptr if unconditional branch
410f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
411f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
41257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is
41357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1).
414b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel {
415c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCall() = delete;
4167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall(const InstCall &) = delete;
4177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall &operator=(const InstCall &) = delete;
4187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
419f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
420f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
4215e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          Operand *CallTarget, bool HasTailCall,
4225e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          bool IsTargetHelperCall = false) {
4239612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull    /// Set HasSideEffects to true so that the call instruction can't be
42457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// dead-code eliminated. IntrinsicCalls can override this if the particular
42557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// intrinsic is deletable and has no side-effects.
4265bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr bool HasSideEffects = true;
4275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr InstKind Kind = Inst::Call;
4285e0a8a71b75ec56981883587612b16f7c1635a03John Porto    return new (Func->allocate<InstCall>())
4295e0a8a71b75ec56981883587612b16f7c1635a03John Porto        InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
4305e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 IsTargetHelperCall, HasSideEffects, Kind);
431f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
432f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArg(Operand *Arg) { addSource(Arg); }
433f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCallTarget() const { return getSrc(0); }
434f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
435f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumArgs() const { return getSrcSize() - 1; }
4368df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool isTailcall() const { return HasTailCall; }
4375e0a8a71b75ec56981883587612b16f7c1635a03John Porto  bool isTargetHelperCall() const { return IsTargetHelperCall; }
438f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return true; }
4393ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung  void dump(const Cfg *Func) const override;
4408cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
4418df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  Type getReturnType() const;
442f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4433bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected:
4443bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
4455e0a8a71b75ec56981883587612b16f7c1635a03John Porto           bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
4465e0a8a71b75ec56981883587612b16f7c1635a03John Porto           InstKind Kind)
4475e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
4485e0a8a71b75ec56981883587612b16f7c1635a03John Porto        IsTargetHelperCall(IsTargetHelperCall) {
4493bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    HasSideEffects = HasSideEff;
450f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    addSource(CallTarget);
451f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
4523bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
4533bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
4545e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool HasTailCall;
4555e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool IsTargetHelperCall;
456f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
457f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4589612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation).
459b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel {
460c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCast() = delete;
4617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast(const InstCast &) = delete;
4627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast &operator=(const InstCast &) = delete;
4637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
464f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
465f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
466f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
467f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTCAST_TABLE
468f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4694376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4715bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
472bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf  static const char *getCastName(OpKind Kind);
473bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf
474f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
475f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source) {
47631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCast>())
477f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstCast(Func, CastKind, Dest, Source);
478f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
479f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getCastKind() const { return CastKind; }
480f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
481b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4828cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
484f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
4861bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind CastKind;
488f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4909612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction.
491b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel {
492c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstExtractElement() = delete;
4937b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement(const InstExtractElement &) = delete;
4947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement &operator=(const InstExtractElement &) = delete;
4957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
49649889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
49749889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
49849889239d4c7ab296c7430722d36032d905110b6Matt Wala                                    Operand *Source2) {
49931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstExtractElement>())
50049889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstExtractElement(Func, Dest, Source1, Source2);
50149889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
50249889239d4c7ab296c7430722d36032d905110b6Matt Wala
503f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
504b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5058cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
5068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == ExtractElement;
50749889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
50849889239d4c7ab296c7430722d36032d905110b6Matt Wala
50949889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
51049889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
51149889239d4c7ab296c7430722d36032d905110b6Matt Wala                     Operand *Source2);
51249889239d4c7ab296c7430722d36032d905110b6Matt Wala};
51349889239d4c7ab296c7430722d36032d905110b6Matt Wala
51457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in
51557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
516b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel {
517c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFcmp() = delete;
5187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp(const InstFcmp &) = delete;
5197b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp &operator=(const InstFcmp &) = delete;
5207b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
521f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum FCond {
523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
524f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTFCMP_TABLE
525f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5264376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
527f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5285bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
529f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
530f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
53131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFcmp>())
532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstFcmp(Func, Condition, Dest, Source1, Source2);
533f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
534f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  FCond getCondition() const { return Condition; }
535f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
536b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5378cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
538f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
539f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
540f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
541f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5421bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
543f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const FCond Condition;
544f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
545f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
54657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in
54757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
548b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel {
549c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIcmp() = delete;
5507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp(const InstIcmp &) = delete;
5517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp &operator=(const InstIcmp &) = delete;
5527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
553f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
554f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum ICond {
5550c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee#define X(tag, inverse, str) tag,
556f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTICMP_TABLE
557f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5584376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
559f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5605bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
561f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
562f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
56331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIcmp>())
564f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstIcmp(Func, Condition, Dest, Source1, Source2);
565f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
566f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  ICond getCondition() const { return Condition; }
5670c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee  void reverseConditionAndOperands();
568f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
569b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5708cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
571f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
572f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
573f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
574f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5751bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
5760c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee  ICond Condition;
577f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
578f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
5799612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction.
580b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel {
581c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstInsertElement() = delete;
5827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement(const InstInsertElement &) = delete;
5837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement &operator=(const InstInsertElement &) = delete;
5847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
58549889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
58649889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
58749889239d4c7ab296c7430722d36032d905110b6Matt Wala                                   Operand *Source2, Operand *Source3) {
58831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstInsertElement>())
58949889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstInsertElement(Func, Dest, Source1, Source2, Source3);
59049889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
59149889239d4c7ab296c7430722d36032d905110b6Matt Wala
592f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
593b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5948cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
5958cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == InsertElement;
59649889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
59749889239d4c7ab296c7430722d36032d905110b6Matt Wala
59849889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
59949889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
60049889239d4c7ab296c7430722d36032d905110b6Matt Wala                    Operand *Source2, Operand *Source3);
60149889239d4c7ab296c7430722d36032d905110b6Matt Wala};
60249889239d4c7ab296c7430722d36032d905110b6Matt Wala
60357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and
60457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1).
6053bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall {
606c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIntrinsicCall() = delete;
6077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall(const InstIntrinsicCall &) = delete;
6087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
6097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
6103bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic:
6113bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
6123bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   Operand *CallTarget,
6133bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   const Intrinsics::IntrinsicInfo &Info) {
61431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIntrinsicCall>())
6153bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
6163bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
6178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
6188cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == IntrinsicCall;
6193bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
6203bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
6213bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
622f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override {
623f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth    return getIntrinsicInfo().IsMemoryWrite;
624f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  }
6253bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
6263bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
6273bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
6283bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                    Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
6295e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
6305e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 Info.HasSideEffects, Inst::IntrinsicCall),
6313bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        Info(Info) {}
6321bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
6333bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  const Intrinsics::IntrinsicInfo Info;
6343bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung};
6353bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
63657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0).
637b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel {
638c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstLoad() = delete;
6397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad(const InstLoad &) = delete;
6407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad &operator=(const InstLoad &) = delete;
6417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
64341689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
644c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth                          uint32_t Align = 1) {
64541689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
646c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    (void)Align;
64731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
649f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSourceAddress() const { return getSrc(0); }
650f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
651b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
655f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
657f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
65857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
65957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I).
660b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel {
661c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstPhi() = delete;
6627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi(const InstPhi &) = delete;
6637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi &operator=(const InstPhi &) = delete;
6647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
665f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
66731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
669f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArgument(Operand *Source, CfgNode *Label);
6705bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  Operand *getOperandForTarget(CfgNode *Target) const;
671263ac526cb5d182e5bedb16e90566ae8ba1f36ffDavid Sehr  void clearOperandForTarget(CfgNode *Target);
67298712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
67316f8061ca23653172ea4c1a43659bb0501b5b474Eric Holk  void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
6744775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
675d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth                          Liveness *Liveness);
676144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Inst *lower(Cfg *Func);
677f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
678b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6798cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
680f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
681f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
68345f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  void destroy(Cfg *Func) override { Inst::destroy(Func); }
684f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
68557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
68657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// but the Phi instruction is created before InEdges[] is available, so it's
68757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// more complicated to share the list.
68845f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  CfgVector<CfgNode *> Labels;
689f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
690f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
69157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is
69257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and
69357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false.
694b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel {
695c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstRet() = delete;
6967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet(const InstRet &) = delete;
6977b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet &operator=(const InstRet &) = delete;
6987b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
700ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
70131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasRetValue() const { return getSrcSize(); }
704f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getRetValue() const {
705f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(hasRetValue());
706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
707f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
708b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
709f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
710b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7118cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
712f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
714f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstRet(Cfg *Func, Operand *RetValue);
715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
7179612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction.  The condition, true, and false operands are captured.
718b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel {
719c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSelect() = delete;
7207b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect(const InstSelect &) = delete;
7217b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect &operator=(const InstSelect &) = delete;
7227b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            Operand *SourceTrue, Operand *SourceFalse) {
72631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSelect>())
727f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const { return getSrc(0); }
730f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getTrueOperand() const { return getSrc(1); }
731f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getFalseOperand() const { return getSrc(2); }
732f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
733b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7348cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
737f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
738f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Operand *Source2);
739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
74157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data
74257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address.
743b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel {
744c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstStore() = delete;
7457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore(const InstStore &) = delete;
7467b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore &operator=(const InstStore &) = delete;
7477b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
748f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
74941689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
750e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth                           uint32_t Align = 1) {
75141689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
752e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth    (void)Align;
75331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
754f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getAddr() const { return getSrc(1); }
756f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getData() const { return getSrc(0); }
757aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  Variable *getRmwBeacon() const;
758e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth  void setRmwBeacon(Variable *Beacon);
759f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return true; }
760b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7618cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
762f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
763f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
764f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
765f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
76757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0).
768b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel {
769c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSwitch() = delete;
7707b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch(const InstSwitch &) = delete;
7717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch &operator=(const InstSwitch &) = delete;
7727b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
773f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
774f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
775f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            CfgNode *LabelDefault) {
77631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSwitch>())
777f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSwitch(Func, NumCases, Source, LabelDefault);
778f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
779f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getComparison() const { return getSrc(0); }
780f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabelDefault() const { return LabelDefault; }
781f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumCases() const { return NumCases; }
782f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t getValue(SizeT I) const {
783f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
784f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Values[I];
785f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
786f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabel(SizeT I) const {
787f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
788f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Labels[I];
789f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
790f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
791b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
79287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
793f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
794b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7958cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
796f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
797f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
798f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
799b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
800f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<uint64_t>(Values);
801f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
802f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
803f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
804f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
805f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *LabelDefault;
8069612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  SizeT NumCases;   /// not including the default case
8079612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  uint64_t *Values; /// size is NumCases
8089612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode **Labels; /// size is NumCases
809f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
810f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
81157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands.
812b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel {
813c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstUnreachable() = delete;
8147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable(const InstUnreachable &) = delete;
8157b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable &operator=(const InstUnreachable &) = delete;
8167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
817f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
818f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstUnreachable *create(Cfg *Func) {
81931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
820f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
821b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
822f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
823b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8248cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Unreachable;
826f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
827f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
828f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
829c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  explicit InstUnreachable(Cfg *Func);
830f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
831f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
83257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction.  There are no operands. Contains an option
8339612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified.
8349f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel {
835c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleLock() = delete;
8369f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(const InstBundleLock &) = delete;
8379f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock &operator=(const InstBundleLock &) = delete;
8389f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8399f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
84056958cb33d3c1d045f2844408d825442d523f59fJohn Porto  enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
8419f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleLock *create(Cfg *Func, Option BundleOption) {
8429f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleLock>())
8439f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth        InstBundleLock(Func, BundleOption);
8449f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8459f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8469f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
847f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
8489f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8499f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option getOption() const { return BundleOption; }
8508cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8518cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleLock;
8529f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8539f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8549f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8559f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option BundleOption;
8569f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(Cfg *Func, Option BundleOption);
8579f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8589f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
85957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands.
8609f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel {
861c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleUnlock() = delete;
8629f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock(const InstBundleUnlock &) = delete;
8639f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
8649f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
8669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleUnlock *create(Cfg *Func) {
8679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
8689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8709f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
871f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
8729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8738cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8748cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleUnlock;
8759f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8769f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8779f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8789f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  explicit InstBundleUnlock(Cfg *Func);
8799f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8809f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
88157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is
88257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results.
88357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered
88457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags
88557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction.
8869612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
88757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest
88857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest.
88957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its
89057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
89157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized.
892b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel {
893c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeDef() = delete;
8947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef(const InstFakeDef &) = delete;
8957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef &operator=(const InstFakeDef &) = delete;
8967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
898ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstFakeDef *create(Cfg *Func, Variable *Dest,
899ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth                             Variable *Src = nullptr) {
90031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
902b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
903198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
904f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
905b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
9075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
9095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
9105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
91257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the
91357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated.
91457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction
9158ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// has no dest, so it can itself never be dead-code eliminated.  A weight can
9168ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// be provided to provide extra bias to the register allocator - for simplicity
9178ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// of implementation, weight=N is handled by holding N copies of the variable
9188ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// as source operands.
919b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel {
920c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeUse() = delete;
9217b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse(const InstFakeUse &) = delete;
9227b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse &operator=(const InstFakeUse &) = delete;
9237b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
9245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
9258ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
9268ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth    return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
9275bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
928b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
929198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
930f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
931b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9328cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
9335bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9345bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
9358ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
9365bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9375bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
93857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial
93957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use
94057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the
94157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live
94257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call.
9439612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
94457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills
94557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code
94657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well.
947b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel {
948c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeKill() = delete;
9497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill(const InstFakeKill &) = delete;
9507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill &operator=(const InstFakeKill &) = delete;
9517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
9525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
95387ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
95431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
9555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
9565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *getLinked() const { return Linked; }
957b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
958198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
959f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
960b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9618cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
9628cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == FakeKill;
9638cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
9645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
96687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  InstFakeKill(Cfg *Func, const Inst *Linked);
9675bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9689612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// This instruction is ignored if Linked->isDeleted() is true.
9695bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *Linked;
9705bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9715bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
972a47c11c7f17022050043d69c0802241e0747a056John Porto/// ShuffleVector instruction. This represents a shuffle operation on vector
973a47c11c7f17022050043d69c0802241e0747a056John Porto/// types. This instruction is not part of the PNaCl bitcode: it is generated
974a47c11c7f17022050043d69c0802241e0747a056John Porto/// by Subzero when it matches the pattern used by pnacl-clang when compiling
975a47c11c7f17022050043d69c0802241e0747a056John Porto/// to bitcode.
976a47c11c7f17022050043d69c0802241e0747a056John Portoclass InstShuffleVector : public InstHighLevel {
977a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector() = delete;
978a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector(const InstShuffleVector &) = delete;
979a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector &operator=(const InstShuffleVector &) = delete;
980a47c11c7f17022050043d69c0802241e0747a056John Porto
981a47c11c7f17022050043d69c0802241e0747a056John Portopublic:
982579b1b3a84da15d233c9ab4e3d3dc35cff4edf86Nicolas Capens  static InstShuffleVector *create(Cfg *Func, Variable *Dest, Operand *Src0,
983579b1b3a84da15d233c9ab4e3d3dc35cff4edf86Nicolas Capens                                   Operand *Src1) {
984a47c11c7f17022050043d69c0802241e0747a056John Porto    return new (Func->allocate<InstShuffleVector>())
985a47c11c7f17022050043d69c0802241e0747a056John Porto        InstShuffleVector(Func, Dest, Src0, Src1);
986a47c11c7f17022050043d69c0802241e0747a056John Porto  }
987a47c11c7f17022050043d69c0802241e0747a056John Porto
988a47c11c7f17022050043d69c0802241e0747a056John Porto  SizeT getNumIndexes() const { return NumIndexes; }
989a47c11c7f17022050043d69c0802241e0747a056John Porto
990a47c11c7f17022050043d69c0802241e0747a056John Porto  void addIndex(ConstantInteger32 *Index) {
991a47c11c7f17022050043d69c0802241e0747a056John Porto    assert(CurrentIndex < NumIndexes);
992a47c11c7f17022050043d69c0802241e0747a056John Porto    Indexes[CurrentIndex++] = Index;
993a47c11c7f17022050043d69c0802241e0747a056John Porto  }
994a47c11c7f17022050043d69c0802241e0747a056John Porto
995a47c11c7f17022050043d69c0802241e0747a056John Porto  ConstantInteger32 *getIndex(SizeT Pos) const {
996a47c11c7f17022050043d69c0802241e0747a056John Porto    assert(Pos < NumIndexes);
997a47c11c7f17022050043d69c0802241e0747a056John Porto    return Indexes[Pos];
998a47c11c7f17022050043d69c0802241e0747a056John Porto  }
999a47c11c7f17022050043d69c0802241e0747a056John Porto
10001448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens  inline bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3,
10011448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens                         int32_t i4, int32_t i5, int32_t i6, int32_t i7) const {
10021448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    static constexpr SizeT ExpectedNumElements = 8;
10031448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    assert(ExpectedNumElements == getNumIndexes());
10041448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    (void)ExpectedNumElements;
10051448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens
10061448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    return getIndex(0)->getValue() == i0 && getIndex(1)->getValue() == i1 &&
10071448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(2)->getValue() == i2 && getIndex(3)->getValue() == i3 &&
10081448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(4)->getValue() == i4 && getIndex(5)->getValue() == i5 &&
10091448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(6)->getValue() == i6 && getIndex(7)->getValue() == i7;
10101448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens  }
10111448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens
10121448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens  inline bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3,
10131448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens                         int32_t i4, int32_t i5, int32_t i6, int32_t i7,
10141448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens                         int32_t i8, int32_t i9, int32_t i10, int32_t i11,
10151448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens                         int32_t i12, int32_t i13, int32_t i14,
10161448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens                         int32_t i15) const {
10171448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    static constexpr SizeT ExpectedNumElements = 16;
10181448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    assert(ExpectedNumElements == getNumIndexes());
10191448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    (void)ExpectedNumElements;
10201448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens
10211448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens    return getIndex(0)->getValue() == i0 && getIndex(1)->getValue() == i1 &&
10221448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(2)->getValue() == i2 && getIndex(3)->getValue() == i3 &&
10231448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(4)->getValue() == i4 && getIndex(5)->getValue() == i5 &&
10241448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(6)->getValue() == i6 && getIndex(7)->getValue() == i7 &&
10251448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(8)->getValue() == i8 && getIndex(9)->getValue() == i9 &&
10261448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(10)->getValue() == i10 && getIndex(11)->getValue() == i11 &&
10271448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(12)->getValue() == i12 && getIndex(13)->getValue() == i13 &&
10281448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens           getIndex(14)->getValue() == i14 && getIndex(15)->getValue() == i15;
10291448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens  }
10301448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens
1031cd261e9187a065dc7b917af8f2f8ff435fcf4c15Jim Stichnoth  bool isMemoryWrite() const override { return false; }
1032a47c11c7f17022050043d69c0802241e0747a056John Porto  void dump(const Cfg *Func) const override;
1033a47c11c7f17022050043d69c0802241e0747a056John Porto  static bool classof(const Inst *Instr) {
1034a47c11c7f17022050043d69c0802241e0747a056John Porto    return Instr->getKind() == ShuffleVector;
1035a47c11c7f17022050043d69c0802241e0747a056John Porto  }
1036a47c11c7f17022050043d69c0802241e0747a056John Porto
1037a47c11c7f17022050043d69c0802241e0747a056John Portoprivate:
1038579b1b3a84da15d233c9ab4e3d3dc35cff4edf86Nicolas Capens  InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1);
1039a47c11c7f17022050043d69c0802241e0747a056John Porto
1040a47c11c7f17022050043d69c0802241e0747a056John Porto  void destroy(Cfg *Func) override {
1041a47c11c7f17022050043d69c0802241e0747a056John Porto    Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
1042a47c11c7f17022050043d69c0802241e0747a056John Porto    Inst::destroy(Func);
1043a47c11c7f17022050043d69c0802241e0747a056John Porto  }
1044a47c11c7f17022050043d69c0802241e0747a056John Porto
1045a47c11c7f17022050043d69c0802241e0747a056John Porto  ConstantInteger32 **Indexes;
1046a47c11c7f17022050043d69c0802241e0747a056John Porto  SizeT CurrentIndex = 0;
1047a47c11c7f17022050043d69c0802241e0747a056John Porto  const SizeT NumIndexes;
1048a47c11c7f17022050043d69c0802241e0747a056John Porto};
1049a47c11c7f17022050043d69c0802241e0747a056John Porto
105057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in
105157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes
105257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering.
105387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel {
105487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable() = delete;
105587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(const InstJumpTable &) = delete;
105687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable &operator=(const InstJumpTable &) = delete;
105787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
105887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic:
105987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
106087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    return new (Func->allocate<InstJumpTable>())
106187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull        InstJumpTable(Func, NumTargets, Default);
106287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
106387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void addTarget(SizeT TargetIndex, CfgNode *Target) {
106487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    assert(TargetIndex < NumTargets);
106587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Targets[TargetIndex] = Target;
106687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
106787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
106886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getId() const { return Id; }
106986df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getNumTargets() const { return NumTargets; }
107086df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  CfgNode *getTarget(SizeT I) const {
107186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    assert(I < NumTargets);
107286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return Targets[I];
107386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
1074f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
107587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void dump(const Cfg *Func) const override;
10768cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
10778cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == JumpTable;
10788cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
1079030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // Creates a JumpTableData struct (used for ELF emission) that represents this
1080030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // InstJumpTable.
1081030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  JumpTableData toJumpTableData(Assembler *Asm) const;
108287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
1083030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // InstJumpTable is just a placeholder for the switch targets, and it does not
1084030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // need to emit any code, so we redefine emit and emitIAS to do nothing.
1085030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  void emit(const Cfg *) const override {}
1086030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  void emitIAS(const Cfg * /* Func */) const override {}
1087030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto
1088030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  const std::string getName() const {
1089030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    assert(Name.hasStdString());
1090030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    return Name.toString();
1091030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  }
1092030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto
1093030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  std::string getSectionName() const {
1094030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    return JumpTableData::createSectionName(FuncName);
109586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
109686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
109787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate:
109887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
109987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void destroy(Cfg *Func) override {
110087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Func->deallocateArrayOf<CfgNode *>(Targets);
110187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Inst::destroy(Func);
110287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
110387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
110486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  const SizeT Id;
110587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  const SizeT NumTargets;
110687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CfgNode **Targets;
1107030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString Name; // This JumpTable's name in the output.
1108030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString FuncName;
110987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull};
111087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
111167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction inserts an unconditional breakpoint.
111267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk///
111367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// On x86, this assembles into an INT 3 instruction.
111467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk///
111567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction is primarily meant for debugging the code generator.
111667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkclass InstBreakpoint : public InstHighLevel {
111767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic:
111867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint() = delete;
111967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint(const InstBreakpoint &) = delete;
112067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint &operator=(const InstBreakpoint &) = delete;
112167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
1122f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  explicit InstBreakpoint(Cfg *Func);
1123f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
112467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
112567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic:
112667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  static InstBreakpoint *create(Cfg *Func) {
112767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk    return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
112867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  }
112967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
113067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  static bool classof(const Inst *Instr) {
113167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk    return Instr->getKind() == Breakpoint;
113267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  }
113367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk};
113467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
11359612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific
11369612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions.
11375bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst {
1138c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstTarget() = delete;
11390795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget(const InstTarget &) = delete;
11400795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget &operator=(const InstTarget &) = delete;
1141b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
11425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
1143b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  uint32_t getEmitInstCount() const override { return 1; }
1144f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override {
1145f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth    return true; // conservative answer
1146f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  }
1147b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
11488cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
11495bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
11505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected:
11515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
11525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {
11535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    assert(Kind >= Target);
11546ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    assert(Kind <= Target_Max);
11555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
11565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
11575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
1158b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
1159b3401d27a236b81393092b4d571df473b5bba64bJan Voung
1160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
1161f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
11628b21cc589f0cc01344a6a772c97c1f24a40718ccJim Stichnoth#ifdef PNACL_LLVM
1163dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm {
1164dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
116557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted
116657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked.
1167607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <>
1168dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
1169607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *createSentinel() const {
1170607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth    return static_cast<Ice::Inst *>(&Sentinel);
1171607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  }
1172607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void destroySentinel(Ice::Inst *) {}
1173607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *provideInitialHead() const { return createSentinel(); }
1174607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
1175607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void noteHead(Ice::Inst *, Ice::Inst *) {}
1176607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  void deleteNode(Ice::Inst *) {}
1177607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1178607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate:
1179607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  mutable ilist_half_node<Ice::Inst> Sentinel;
1180607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth};
1181607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1182dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm
11838b21cc589f0cc01344a6a772c97c1f24a40718ccJim Stichnoth#endif // PNACL_LLVM
1184dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
1185f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothnamespace Ice {
1186f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1187f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline InstList::iterator instToIterator(Inst *Instr) {
1188f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#ifdef PNACL_LLVM
1189f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return Instr;
1190a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#else  // !PNACL_LLVM
1191f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return Instr->getIterator();
1192f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#endif // !PNACL_LLVM
1193f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth}
1194f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1195a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnothinline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; }
1196f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1197f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline const Inst *iteratorToInst(InstList::const_iterator Iter) {
1198f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return &*Iter;
1199f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth}
1200f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
12017c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnothinline InstList::iterator
12027c9728faead1368150bcaa8313bc460df29ea1b7Jim StichnothreverseToForwardIterator(InstList::reverse_iterator RI) {
12037c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth#ifdef PNACL_LLVM
12047c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth  return RI.base();
12057c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth#else  // !PNACL_LLVM
12067c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth  return ++RI.getReverse();
12077c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth#endif // !PNACL_LLVM
12087c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth}
12097c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth
1210f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} // end of namespace Ice
1211f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1212f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H
1213