IceInst.h revision 032c315836b8c1ed9ff6bb2be1981b6d4a1a3594
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
106f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getSrcSize() const { return NumSrcs; }
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) {
112032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    assert(Index < NumSrcs);
113032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    assert(!isDeleted());
114032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    assert(LiveRangesEnded == 0);
115032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    //Invalidates liveness info because the use Srcs[Index] is removed.
116032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    Srcs[Index] = Replacement;
117032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee  }
118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
119d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool isLastUse(const Operand *Src) const;
1208e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth  void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
121d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
1226ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Returns a list of out-edges corresponding to a terminator instruction,
1236ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// which is the last instruction of the block. The list must not contain
1246ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// duplicates.
125f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual NodeList getTerminatorEdges() const {
1266ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // All valid terminator instructions override this method. For the default
1276ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // implementation, we assert in case some CfgNode is constructed without a
1286ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // terminator instruction at the end.
129f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    llvm_unreachable(
130f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        "getTerminatorEdges() called on a non-terminator instruction");
131f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return NodeList();
132f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
133336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool isUnconditionalBranch() const { return false; }
13457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// If the instruction is a branch-type instruction with OldNode as a target,
13557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// repoint it to NewNode and return true, otherwise return false. Repoint all
13657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instances of OldNode as a target.
13787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
138336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)OldNode;
139336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)NewNode;
140336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    return false;
141336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
142f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
14328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// Returns true if the instruction is equivalent to a simple
14428b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// "var_dest=var_src" assignment where the dest and src are both variables.
14528b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  virtual bool isVarAssign() const { return false; }
146ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
147f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// Returns true if the instruction has a possible side effect of changing
148f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// memory, in which case a memory load should not be reordered with respect
149f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// to this instruction.  It should really be pure virtual, but we can't
150f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// because of g++ and llvm::ilist<>, so we implement it as
151f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// report_fatal_error().
152f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  virtual bool isMemoryWrite() const;
153f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth
1544775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessLightweight(Cfg *Func, LivenessBV &Live);
15557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Calculates liveness for this instruction. Returns true if this instruction
15657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// is (tentatively) still live and should be retained, and false if this
15757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction is (tentatively) dead and should be deleted. The decision is
15857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// tentative until the liveness dataflow algorithm has converged, and then a
15957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// separate pass permanently deletes dead instructions.
160336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
1614775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
1621873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth
1636ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Get the number of native instructions that this instruction ultimately
1646ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// emits. By default, high-level instructions don't result in any native
1656ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instructions, and a target-specific instruction results in a single native
1666ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instruction.
1671873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  virtual uint32_t getEmitInstCount() const { return 0; }
16857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
16957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
17057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
17157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // allow the abstract class Ice::Inst. The method should be declared
17257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
17357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
174dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emit(const Cfg *) const {
175dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth    llvm_unreachable("emit on abstract class");
176dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  }
177dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
178f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void dump(const Cfg *Func) const;
179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  virtual void dumpExtras(const Cfg *Func) const;
180f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDecorated(const Cfg *Func) const;
1815bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  void emitSources(const Cfg *Func) const;
182f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpSources(const Cfg *Func) const;
183f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDest(const Cfg *Func) const;
1845bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  virtual bool isRedundantAssign() const { return false; }
185f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
186fc707ffe812339bddf4ca28fbe8c01045e2b42d6Sean Klein  virtual ~Inst() = default;
187f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
188f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected:
189f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
190f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addSource(Operand *Src) {
191f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(Src);
192f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(NumSrcs < MaxSrcs);
193f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Srcs[NumSrcs++] = Src;
194f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
195d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void setLastUse(SizeT VarIndex) {
196d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
197d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
198d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
199d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void resetLastUses() { LiveRangesEnded = 0; }
20057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// The destroy() method lets the instruction cleanly release any memory that
20157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// was allocated via the Cfg's allocator.
202f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
203f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
204f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const InstKind Kind;
2059612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Number is the instruction number for describing live ranges.
206d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT Number;
2079612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Deleted means irrevocably deleted.
208eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Deleted = false;
20957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Dead means one of two things depending on context: (1) pending deletion
21057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// after liveness analysis converges, or (2) marked for deletion during
21157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// lowering due to a folded bool operation.
212eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Dead = false;
21357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// HasSideEffects means the instruction is something like a function call or
21457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// a volatile load that can't be removed even if its Dest variable is not
21557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// live.
216eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool HasSideEffects = false;
217230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// IsDestRedefined indicates that this instruction is not the first
218230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// definition of Dest in the basic block.  The effect is that liveness
219230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// analysis shouldn't consider this instruction to be the start of Dest's
220230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range; rather, there is some other instruction earlier in the basic
221230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// block with the same Dest.  This is maintained because liveness analysis
222230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// has an invariant (primarily for performance reasons) that any Variable's
223230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range recorded in a basic block has at most one start and at most one
224230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// end.
225230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool IsDestRedefined = false;
226f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
227f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *Dest;
228f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const SizeT MaxSrcs; // only used for assert
229eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  SizeT NumSrcs = 0;
230f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand **Srcs;
231f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
2329612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// LiveRangesEnded marks which Variables' live ranges end in this
23357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. An instruction can have an arbitrary number of source
23457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands (e.g. a call instruction), and each source operand can contain 0
23557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// or 1 Variable (and target-specific operands could contain more than 1
23657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Variable). All the variables in an instruction are conceptually flattened
23757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and each variable is mapped to one bit position of the LiveRangesEnded bit
23857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
2399612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// tracked this way.
2408072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
241d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  LREndedBits LiveRangesEnded;
242f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
243f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
244b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst {
245c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstHighLevel() = delete;
2460795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel(const InstHighLevel &) = delete;
2470795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel &operator=(const InstHighLevel &) = delete;
248b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
249b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected:
250b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
251b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {}
252b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg * /*Func*/) const override {
253b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emit() called on a non-lowered instruction");
254b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
255b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emitIAS(const Cfg * /*Func*/) const override {
256b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emitIAS() called on a non-lowered instruction");
257b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
258b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth};
259b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
26057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the
26157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment
26257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2.
263b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel {
264c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAlloca() = delete;
2657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca(const InstAlloca &) = delete;
2667b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca &operator=(const InstAlloca &) = delete;
2677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
268f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
2692f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
2702f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr                            uint32_t AlignInBytes) {
27131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAlloca>())
2722f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr        InstAlloca(Func, Dest, ByteCount, AlignInBytes);
273f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint32_t getAlignInBytes() const { return AlignInBytes; }
275f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSizeInBytes() const { return getSrc(0); }
27655f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool getKnownFrameOffset() const { return KnownFrameOffset; }
27755f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  void setKnownFrameOffset() { KnownFrameOffset = true; }
278f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
279b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
2808cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
2832f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
2842f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr             uint32_t AlignInBytes);
2851bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const uint32_t AlignInBytes;
28755f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool KnownFrameOffset = false;
288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
289f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
29057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0)
29157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1).
292b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel {
293c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstArithmetic() = delete;
2947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic(const InstArithmetic &) = delete;
2957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic &operator=(const InstArithmetic &) = delete;
2967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
297f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
298f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
299f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag,
300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTARITHMETIC_TABLE
301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
3024376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
3045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
305f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
306f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                                Operand *Source1, Operand *Source2) {
30731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstArithmetic>())
308f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstArithmetic(Func, Op, Dest, Source1, Source2);
309f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
310f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getOp() const { return Op; }
311e37076a176e04eee0f35058ccd2109754c193015Eric Holk
312467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  virtual const char *getInstName() const override;
313e37076a176e04eee0f35058ccd2109754c193015Eric Holk
314d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf  static const char *getOpName(OpKind Op);
315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isCommutative() const;
316f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
317b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3188cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
3198cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Arithmetic;
320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
323f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
324f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                 Operand *Source2);
325f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
326f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind Op;
327f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
32957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is
33057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the
33157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering,
33257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for
33357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction.
334b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel {
335c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAssign() = delete;
3367b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign(const InstAssign &) = delete;
3377b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign &operator=(const InstAssign &) = delete;
3387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
339f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
340f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
34131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
34328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  bool isVarAssign() const override;
344f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
345b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3468cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
347f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
349f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
350f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
351f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
35257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional
35357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches.
354b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel {
355c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBr() = delete;
3567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr(const InstBr &) = delete;
3577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr &operator=(const InstBr &) = delete;
3587b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
36057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
36157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to an unconditional branch.
362f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
363f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                        CfgNode *TargetFalse) {
36431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>())
365f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstBr(Func, Source, TargetTrue, TargetFalse);
366f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
3679612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Create an unconditional branch.
368f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, CfgNode *Target) {
36931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>()) InstBr(Func, Target);
370f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
371ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  bool isUnconditional() const { return getTargetTrue() == nullptr; }
372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const {
373f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(!isUnconditional());
374f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
375f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetTrue() const { return TargetTrue; }
377f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetFalse() const { return TargetFalse; }
378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetUnconditional() const {
379f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(isUnconditional());
380f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getTargetFalse();
381f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
382b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
383336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool isUnconditionalBranch() const override { return isUnconditional(); }
38487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
385f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
386b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3878cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
388f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
389f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
3909612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Conditional branch
391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
3929612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Unconditional branch
393f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, CfgNode *Target);
394f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
3959612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetFalse; /// Doubles as unconditional branch target
3969612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetTrue;  /// nullptr if unconditional branch
397f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
398f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
39957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is
40057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1).
401b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel {
402c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCall() = delete;
4037b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall(const InstCall &) = delete;
4047b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall &operator=(const InstCall &) = delete;
4057b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
406f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
407f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
4085e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          Operand *CallTarget, bool HasTailCall,
4095e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          bool IsTargetHelperCall = false) {
4109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull    /// Set HasSideEffects to true so that the call instruction can't be
41157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// dead-code eliminated. IntrinsicCalls can override this if the particular
41257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// intrinsic is deletable and has no side-effects.
4135bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr bool HasSideEffects = true;
4145bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr InstKind Kind = Inst::Call;
4155e0a8a71b75ec56981883587612b16f7c1635a03John Porto    return new (Func->allocate<InstCall>())
4165e0a8a71b75ec56981883587612b16f7c1635a03John Porto        InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
4175e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 IsTargetHelperCall, HasSideEffects, Kind);
418f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
419f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArg(Operand *Arg) { addSource(Arg); }
420f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCallTarget() const { return getSrc(0); }
421f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
422f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumArgs() const { return getSrcSize() - 1; }
4238df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool isTailcall() const { return HasTailCall; }
4245e0a8a71b75ec56981883587612b16f7c1635a03John Porto  bool isTargetHelperCall() const { return IsTargetHelperCall; }
425f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return true; }
4263ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung  void dump(const Cfg *Func) const override;
4278cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
4288df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  Type getReturnType() const;
429f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4303bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected:
4313bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
4325e0a8a71b75ec56981883587612b16f7c1635a03John Porto           bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
4335e0a8a71b75ec56981883587612b16f7c1635a03John Porto           InstKind Kind)
4345e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
4355e0a8a71b75ec56981883587612b16f7c1635a03John Porto        IsTargetHelperCall(IsTargetHelperCall) {
4363bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    HasSideEffects = HasSideEff;
437f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    addSource(CallTarget);
438f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
4393bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
4403bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
4415e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool HasTailCall;
4425e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool IsTargetHelperCall;
443f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
444f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation).
446b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel {
447c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCast() = delete;
4487b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast(const InstCast &) = delete;
4497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast &operator=(const InstCast &) = delete;
4507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
451f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
452f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
453f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
454f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTCAST_TABLE
455f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4564376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
457f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
459bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf  static const char *getCastName(OpKind Kind);
460bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf
461f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
462f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source) {
46331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCast>())
464f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstCast(Func, CastKind, Dest, Source);
465f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
466f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getCastKind() const { return CastKind; }
467f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
468b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4698cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
471f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
472f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
4731bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
474f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind CastKind;
475f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4779612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction.
478b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel {
479c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstExtractElement() = delete;
4807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement(const InstExtractElement &) = delete;
4817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement &operator=(const InstExtractElement &) = delete;
4827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
48349889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
48449889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
48549889239d4c7ab296c7430722d36032d905110b6Matt Wala                                    Operand *Source2) {
48631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstExtractElement>())
48749889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstExtractElement(Func, Dest, Source1, Source2);
48849889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
48949889239d4c7ab296c7430722d36032d905110b6Matt Wala
490f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
491b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4928cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
4938cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == ExtractElement;
49449889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
49549889239d4c7ab296c7430722d36032d905110b6Matt Wala
49649889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
49749889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
49849889239d4c7ab296c7430722d36032d905110b6Matt Wala                     Operand *Source2);
49949889239d4c7ab296c7430722d36032d905110b6Matt Wala};
50049889239d4c7ab296c7430722d36032d905110b6Matt Wala
50157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in
50257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
503b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel {
504c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFcmp() = delete;
5057b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp(const InstFcmp &) = delete;
5067b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp &operator=(const InstFcmp &) = delete;
5077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
508f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
509f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum FCond {
510f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
511f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTFCMP_TABLE
512f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5134376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
51831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFcmp>())
519f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstFcmp(Func, Condition, Dest, Source1, Source2);
520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
521f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  FCond getCondition() const { return Condition; }
522f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
523b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5248cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
525f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
526f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
527f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
528f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5291bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
530f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const FCond Condition;
531f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
53357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in
53457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
535b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel {
536c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIcmp() = delete;
5377b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp(const InstIcmp &) = delete;
5387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp &operator=(const InstIcmp &) = delete;
5397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
540f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
541f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum ICond {
542f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
543f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTICMP_TABLE
544f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5454376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
546f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5475bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
548f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
549f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
55031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIcmp>())
551f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstIcmp(Func, Condition, Dest, Source1, Source2);
552f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
553f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  ICond getCondition() const { return Condition; }
554f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
555b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5568cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
557f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
558f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
559f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
560f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5611bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
562f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const ICond Condition;
563f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
564f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
5659612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction.
566b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel {
567c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstInsertElement() = delete;
5687b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement(const InstInsertElement &) = delete;
5697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement &operator=(const InstInsertElement &) = delete;
5707b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
57149889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
57249889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
57349889239d4c7ab296c7430722d36032d905110b6Matt Wala                                   Operand *Source2, Operand *Source3) {
57431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstInsertElement>())
57549889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstInsertElement(Func, Dest, Source1, Source2, Source3);
57649889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
57749889239d4c7ab296c7430722d36032d905110b6Matt Wala
578f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
579b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5808cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
5818cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == InsertElement;
58249889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
58349889239d4c7ab296c7430722d36032d905110b6Matt Wala
58449889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
58549889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
58649889239d4c7ab296c7430722d36032d905110b6Matt Wala                    Operand *Source2, Operand *Source3);
58749889239d4c7ab296c7430722d36032d905110b6Matt Wala};
58849889239d4c7ab296c7430722d36032d905110b6Matt Wala
58957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and
59057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1).
5913bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall {
592c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIntrinsicCall() = delete;
5937b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall(const InstIntrinsicCall &) = delete;
5947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
5957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
5963bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic:
5973bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
5983bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   Operand *CallTarget,
5993bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   const Intrinsics::IntrinsicInfo &Info) {
60031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIntrinsicCall>())
6013bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
6023bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
6038cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
6048cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == IntrinsicCall;
6053bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
6063bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
6073bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
608f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override {
609f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth    return getIntrinsicInfo().IsMemoryWrite;
610f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  }
6113bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
6123bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
6133bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
6143bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                    Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
6155e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
6165e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 Info.HasSideEffects, Inst::IntrinsicCall),
6173bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        Info(Info) {}
6181bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
6193bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  const Intrinsics::IntrinsicInfo Info;
6203bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung};
6213bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
62257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0).
623b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel {
624c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstLoad() = delete;
6257b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad(const InstLoad &) = delete;
6267b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad &operator=(const InstLoad &) = delete;
6277b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
628f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
62941689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
630c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth                          uint32_t Align = 1) {
63141689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
632c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    (void)Align;
63331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
634f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
635f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSourceAddress() const { return getSrc(0); }
636f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
637b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6388cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
639f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
640f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
641f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
64457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
64557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I).
646b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel {
647c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstPhi() = delete;
6487b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi(const InstPhi &) = delete;
6497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi &operator=(const InstPhi &) = delete;
6507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
651f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
652f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
65331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
655f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArgument(Operand *Source, CfgNode *Label);
6565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  Operand *getOperandForTarget(CfgNode *Target) const;
657263ac526cb5d182e5bedb16e90566ae8ba1f36ffDavid Sehr  void clearOperandForTarget(CfgNode *Target);
65898712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
65916f8061ca23653172ea4c1a43659bb0501b5b474Eric Holk  void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
6604775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
661d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth                          Liveness *Liveness);
662144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Inst *lower(Cfg *Func);
663f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
664b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6658cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
667f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
669b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
670f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
671f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
672f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
67457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
67557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// but the Phi instruction is created before InEdges[] is available, so it's
67657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// more complicated to share the list.
677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode **Labels;
678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
679f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
68057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is
68157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and
68257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false.
683b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel {
684c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstRet() = delete;
6857b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet(const InstRet &) = delete;
6867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet &operator=(const InstRet &) = delete;
6877b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
688f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
689ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
69031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
691f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasRetValue() const { return getSrcSize(); }
693f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getRetValue() const {
694f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(hasRetValue());
695f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
696f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
697b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
698f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
699b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7008cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
701f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstRet(Cfg *Func, Operand *RetValue);
704f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
705f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
7069612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction.  The condition, true, and false operands are captured.
707b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel {
708c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSelect() = delete;
7097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect(const InstSelect &) = delete;
7107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect &operator=(const InstSelect &) = delete;
7117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
712f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
714f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            Operand *SourceTrue, Operand *SourceFalse) {
71531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSelect>())
716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const { return getSrc(0); }
719f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getTrueOperand() const { return getSrc(1); }
720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getFalseOperand() const { return getSrc(2); }
721f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
722b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7238cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
727f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Operand *Source2);
728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
73057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data
73157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address.
732b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel {
733c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstStore() = delete;
7347b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore(const InstStore &) = delete;
7357b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore &operator=(const InstStore &) = delete;
7367b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
737f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
73841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
739e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth                           uint32_t Align = 1) {
74041689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
741e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth    (void)Align;
74231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
743f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
744f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getAddr() const { return getSrc(1); }
745f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getData() const { return getSrc(0); }
746aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  Variable *getRmwBeacon() const;
747e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth  void setRmwBeacon(Variable *Beacon);
748f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return true; }
749b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7508cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
751f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
752f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
753f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
754f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
75657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0).
757b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel {
758c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSwitch() = delete;
7597b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch(const InstSwitch &) = delete;
7607b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch &operator=(const InstSwitch &) = delete;
7617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
762f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
763f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
764f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            CfgNode *LabelDefault) {
76531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSwitch>())
766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSwitch(Func, NumCases, Source, LabelDefault);
767f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
768f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getComparison() const { return getSrc(0); }
769f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabelDefault() const { return LabelDefault; }
770f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumCases() const { return NumCases; }
771f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t getValue(SizeT I) const {
772f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
773f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Values[I];
774f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
775f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabel(SizeT I) const {
776f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
777f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Labels[I];
778f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
779f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
780b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
78187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
782f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
783b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7848cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
785f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
786f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
787f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
788b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
789f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<uint64_t>(Values);
790f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
791f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
792f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
793f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
794f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *LabelDefault;
7959612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  SizeT NumCases;   /// not including the default case
7969612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  uint64_t *Values; /// size is NumCases
7979612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode **Labels; /// size is NumCases
798f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
799f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
80057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands.
801b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel {
802c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstUnreachable() = delete;
8037b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable(const InstUnreachable &) = delete;
8047b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable &operator=(const InstUnreachable &) = delete;
8057b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
806f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
807f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstUnreachable *create(Cfg *Func) {
80831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
809f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
810b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
811f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
812b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8138cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8148cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Unreachable;
815f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
816f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
817f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
818c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  explicit InstUnreachable(Cfg *Func);
819f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
820f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
82157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction.  There are no operands. Contains an option
8229612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified.
8239f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel {
824c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleLock() = delete;
8259f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(const InstBundleLock &) = delete;
8269f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock &operator=(const InstBundleLock &) = delete;
8279f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8289f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
82956958cb33d3c1d045f2844408d825442d523f59fJohn Porto  enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
8309f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleLock *create(Cfg *Func, Option BundleOption) {
8319f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleLock>())
8329f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth        InstBundleLock(Func, BundleOption);
8339f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8349f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8359f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
836f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
8379f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8389f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option getOption() const { return BundleOption; }
8398cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8408cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleLock;
8419f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8429f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8439f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8449f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option BundleOption;
8459f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(Cfg *Func, Option BundleOption);
8469f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8479f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
84857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands.
8499f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel {
850c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleUnlock() = delete;
8519f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock(const InstBundleUnlock &) = delete;
8529f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
8539f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8549f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
8559f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleUnlock *create(Cfg *Func) {
8569f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
8579f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8589f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8599f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
860f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
8619f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8628cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8638cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleUnlock;
8649f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  explicit InstBundleUnlock(Cfg *Func);
8689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
87057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is
87157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results.
87257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered
87357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags
87457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction.
8759612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
87657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest
87757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest.
87857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its
87957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
88057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized.
881b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel {
882c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeDef() = delete;
8837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef(const InstFakeDef &) = delete;
8847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef &operator=(const InstFakeDef &) = delete;
8857b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8865bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
887ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstFakeDef *create(Cfg *Func, Variable *Dest,
888ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth                             Variable *Src = nullptr) {
88931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
8905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
891b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
892198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
893f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
894b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8958cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
8965bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
8985bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
8995bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
90157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the
90257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated.
90357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction
9048ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// has no dest, so it can itself never be dead-code eliminated.  A weight can
9058ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// be provided to provide extra bias to the register allocator - for simplicity
9068ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// of implementation, weight=N is handled by holding N copies of the variable
9078ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// as source operands.
908b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel {
909c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeUse() = delete;
9107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse(const InstFakeUse &) = delete;
9117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse &operator=(const InstFakeUse &) = delete;
9127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
9135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
9148ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
9158ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth    return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
9165bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
917b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
918198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
919f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
920b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9218cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
9225bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9235bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
9248ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
9255bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9265bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
92757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial
92857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use
92957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the
93057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live
93157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call.
9329612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
93357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills
93457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code
93557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well.
936b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel {
937c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeKill() = delete;
9387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill(const InstFakeKill &) = delete;
9397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill &operator=(const InstFakeKill &) = delete;
9407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
9415bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
94287ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
94331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
9445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
9455bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *getLinked() const { return Linked; }
946b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
947198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
948f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
949b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9508cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
9518cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == FakeKill;
9528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
9535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
95587ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  InstFakeKill(Cfg *Func, const Inst *Linked);
9565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// This instruction is ignored if Linked->isDeleted() is true.
9585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *Linked;
9595bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9605bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
961a47c11c7f17022050043d69c0802241e0747a056John Porto/// ShuffleVector instruction. This represents a shuffle operation on vector
962a47c11c7f17022050043d69c0802241e0747a056John Porto/// types. This instruction is not part of the PNaCl bitcode: it is generated
963a47c11c7f17022050043d69c0802241e0747a056John Porto/// by Subzero when it matches the pattern used by pnacl-clang when compiling
964a47c11c7f17022050043d69c0802241e0747a056John Porto/// to bitcode.
965a47c11c7f17022050043d69c0802241e0747a056John Portoclass InstShuffleVector : public InstHighLevel {
966a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector() = delete;
967a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector(const InstShuffleVector &) = delete;
968a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector &operator=(const InstShuffleVector &) = delete;
969a47c11c7f17022050043d69c0802241e0747a056John Porto
970a47c11c7f17022050043d69c0802241e0747a056John Portopublic:
971a47c11c7f17022050043d69c0802241e0747a056John Porto  static InstShuffleVector *create(Cfg *Func, Variable *Dest, Variable *Src0,
972a47c11c7f17022050043d69c0802241e0747a056John Porto                                   Variable *Src1) {
973a47c11c7f17022050043d69c0802241e0747a056John Porto    return new (Func->allocate<InstShuffleVector>())
974a47c11c7f17022050043d69c0802241e0747a056John Porto        InstShuffleVector(Func, Dest, Src0, Src1);
975a47c11c7f17022050043d69c0802241e0747a056John Porto  }
976a47c11c7f17022050043d69c0802241e0747a056John Porto
977a47c11c7f17022050043d69c0802241e0747a056John Porto  SizeT getNumIndexes() const { return NumIndexes; }
978a47c11c7f17022050043d69c0802241e0747a056John Porto
979a47c11c7f17022050043d69c0802241e0747a056John Porto  void addIndex(ConstantInteger32 *Index) {
980a47c11c7f17022050043d69c0802241e0747a056John Porto    assert(CurrentIndex < NumIndexes);
981a47c11c7f17022050043d69c0802241e0747a056John Porto    Indexes[CurrentIndex++] = Index;
982a47c11c7f17022050043d69c0802241e0747a056John Porto  }
983a47c11c7f17022050043d69c0802241e0747a056John Porto
984a47c11c7f17022050043d69c0802241e0747a056John Porto  ConstantInteger32 *getIndex(SizeT Pos) const {
985a47c11c7f17022050043d69c0802241e0747a056John Porto    assert(Pos < NumIndexes);
986a47c11c7f17022050043d69c0802241e0747a056John Porto    return Indexes[Pos];
987a47c11c7f17022050043d69c0802241e0747a056John Porto  }
988a47c11c7f17022050043d69c0802241e0747a056John Porto
989cd261e9187a065dc7b917af8f2f8ff435fcf4c15Jim Stichnoth  bool isMemoryWrite() const override { return false; }
990a47c11c7f17022050043d69c0802241e0747a056John Porto  void dump(const Cfg *Func) const override;
991a47c11c7f17022050043d69c0802241e0747a056John Porto  static bool classof(const Inst *Instr) {
992a47c11c7f17022050043d69c0802241e0747a056John Porto    return Instr->getKind() == ShuffleVector;
993a47c11c7f17022050043d69c0802241e0747a056John Porto  }
994a47c11c7f17022050043d69c0802241e0747a056John Porto
995a47c11c7f17022050043d69c0802241e0747a056John Portoprivate:
996a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1);
997a47c11c7f17022050043d69c0802241e0747a056John Porto
998a47c11c7f17022050043d69c0802241e0747a056John Porto  void destroy(Cfg *Func) override {
999a47c11c7f17022050043d69c0802241e0747a056John Porto    Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
1000a47c11c7f17022050043d69c0802241e0747a056John Porto    Inst::destroy(Func);
1001a47c11c7f17022050043d69c0802241e0747a056John Porto  }
1002a47c11c7f17022050043d69c0802241e0747a056John Porto
1003a47c11c7f17022050043d69c0802241e0747a056John Porto  ConstantInteger32 **Indexes;
1004a47c11c7f17022050043d69c0802241e0747a056John Porto  SizeT CurrentIndex = 0;
1005a47c11c7f17022050043d69c0802241e0747a056John Porto  const SizeT NumIndexes;
1006a47c11c7f17022050043d69c0802241e0747a056John Porto};
1007a47c11c7f17022050043d69c0802241e0747a056John Porto
100857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in
100957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes
101057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering.
101187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel {
101287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable() = delete;
101387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(const InstJumpTable &) = delete;
101487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable &operator=(const InstJumpTable &) = delete;
101587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
101687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic:
101787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
101887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    return new (Func->allocate<InstJumpTable>())
101987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull        InstJumpTable(Func, NumTargets, Default);
102087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
102187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void addTarget(SizeT TargetIndex, CfgNode *Target) {
102287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    assert(TargetIndex < NumTargets);
102387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Targets[TargetIndex] = Target;
102487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
102587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
102686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getId() const { return Id; }
102786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getNumTargets() const { return NumTargets; }
102886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  CfgNode *getTarget(SizeT I) const {
102986df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    assert(I < NumTargets);
103086df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return Targets[I];
103186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
1032f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
103387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void dump(const Cfg *Func) const override;
10348cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
10358cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == JumpTable;
10368cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
1037030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // Creates a JumpTableData struct (used for ELF emission) that represents this
1038030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // InstJumpTable.
1039030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  JumpTableData toJumpTableData(Assembler *Asm) const;
104087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
1041030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // InstJumpTable is just a placeholder for the switch targets, and it does not
1042030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // need to emit any code, so we redefine emit and emitIAS to do nothing.
1043030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  void emit(const Cfg *) const override {}
1044030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  void emitIAS(const Cfg * /* Func */) const override {}
1045030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto
1046030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  const std::string getName() const {
1047030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    assert(Name.hasStdString());
1048030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    return Name.toString();
1049030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  }
1050030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto
1051030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  std::string getSectionName() const {
1052030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    return JumpTableData::createSectionName(FuncName);
105386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
105486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
105587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate:
105687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
105787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void destroy(Cfg *Func) override {
105887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Func->deallocateArrayOf<CfgNode *>(Targets);
105987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Inst::destroy(Func);
106087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
106187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
106286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  const SizeT Id;
106387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  const SizeT NumTargets;
106487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CfgNode **Targets;
1065030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString Name; // This JumpTable's name in the output.
1066030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString FuncName;
106787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull};
106887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
106967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction inserts an unconditional breakpoint.
107067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk///
107167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// On x86, this assembles into an INT 3 instruction.
107267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk///
107367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction is primarily meant for debugging the code generator.
107467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkclass InstBreakpoint : public InstHighLevel {
107567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic:
107667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint() = delete;
107767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint(const InstBreakpoint &) = delete;
107867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint &operator=(const InstBreakpoint &) = delete;
107967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
1080f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  explicit InstBreakpoint(Cfg *Func);
1081f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
108267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
108367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic:
108467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  static InstBreakpoint *create(Cfg *Func) {
108567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk    return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
108667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  }
108767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
108867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  static bool classof(const Inst *Instr) {
108967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk    return Instr->getKind() == Breakpoint;
109067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  }
109167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk};
109267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
10939612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific
10949612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions.
10955bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst {
1096c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstTarget() = delete;
10970795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget(const InstTarget &) = delete;
10980795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget &operator=(const InstTarget &) = delete;
1099b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
11005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
1101b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  uint32_t getEmitInstCount() const override { return 1; }
1102f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override {
1103f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth    return true; // conservative answer
1104f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  }
1105b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
11068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
11075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
11085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected:
11095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
11105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {
11115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    assert(Kind >= Target);
11126ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    assert(Kind <= Target_Max);
11135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
11145bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
11155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
1116b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
1117b3401d27a236b81393092b4d571df473b5bba64bJan Voung
1118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
1119f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
1120dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm {
1121dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
112257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted
112357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked.
1124607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <>
1125dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
1126607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *createSentinel() const {
1127607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth    return static_cast<Ice::Inst *>(&Sentinel);
1128607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  }
1129607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void destroySentinel(Ice::Inst *) {}
1130607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *provideInitialHead() const { return createSentinel(); }
1131607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
1132607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void noteHead(Ice::Inst *, Ice::Inst *) {}
1133607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  void deleteNode(Ice::Inst *) {}
1134607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1135607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate:
1136607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  mutable ilist_half_node<Ice::Inst> Sentinel;
1137607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth};
1138607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1139dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm
1140dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
1141f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothnamespace Ice {
1142f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1143f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline InstList::iterator instToIterator(Inst *Instr) {
1144f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#ifdef PNACL_LLVM
1145f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return Instr;
1146a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#else  // !PNACL_LLVM
1147f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return Instr->getIterator();
1148f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#endif // !PNACL_LLVM
1149f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth}
1150f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1151a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnothinline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; }
1152f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1153f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline const Inst *iteratorToInst(InstList::const_iterator Iter) {
1154f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return &*Iter;
1155f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth}
1156f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1157f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} // end of namespace Ice
1158f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1159f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H
1160