IceInst.h revision b9a847280e4486e566dabdd5b0d571309b4ad628
1f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===//
2f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
3f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//                        The Subzero Code Generator
4f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
5f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// This file is distributed under the University of Illinois Open Source
6f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// License. See LICENSE.TXT for details.
7f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
8f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the Inst class and its target-independent subclasses.
1292a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth///
1392a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// These represent the high-level Vanilla ICE instructions and map roughly 1:1
1492a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// to LLVM instructions.
159612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
16f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
17f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#ifndef SUBZERO_SRC_ICEINST_H
19f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define SUBZERO_SRC_ICEINST_H
20f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
217e93c62d7e223b7fd9e6e0889e4b70b635589282John Porto#include "IceCfg.h"
22f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceDefs.h"
23f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.def"
243bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung#include "IceIntrinsics.h"
25a47c11c7f17022050043d69c0802241e0747a056John Porto#include "IceOperand.h"
26030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto#include "IceSwitchLowering.h"
27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h"
28f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
29f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be
306ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull// validated for things like valid operand types, valid branch targets, proper
3157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// ordering of Phi and non-Phi instructions, etc. Most of the validity checking
3257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// will be done in the bitcode reader. We need a list of everything that should
3357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// be validated, and tests for each.
34f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
35f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice {
36f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
376ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
386ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
396ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// low-level (target-specific) ICE instructions inherit from InstTarget.
40607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> {
41c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  Inst() = delete;
427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst(const Inst &) = delete;
437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst &operator=(const Inst &) = delete;
447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum InstKind {
47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // Arbitrary (alphabetical) order, except put Unreachable first.
48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Unreachable,
49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Alloca,
50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Arithmetic,
51f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Br,
52f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Call,
53f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Cast,
5449889239d4c7ab296c7430722d36032d905110b6Matt Wala    ExtractElement,
55f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Fcmp,
56f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Icmp,
573bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    IntrinsicCall,
5849889239d4c7ab296c7430722d36032d905110b6Matt Wala    InsertElement,
59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Load,
60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Phi,
61f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Ret,
62f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Select,
63f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Store,
645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Switch,
65a47c11c7f17022050043d69c0802241e0747a056John Porto    Assign,        // not part of LLVM/PNaCl bitcode
66a47c11c7f17022050043d69c0802241e0747a056John Porto    Breakpoint,    // not part of LLVM/PNaCl bitcode
67a47c11c7f17022050043d69c0802241e0747a056John Porto    BundleLock,    // not part of LLVM/PNaCl bitcode
68a47c11c7f17022050043d69c0802241e0747a056John Porto    BundleUnlock,  // not part of LLVM/PNaCl bitcode
69a47c11c7f17022050043d69c0802241e0747a056John Porto    FakeDef,       // not part of LLVM/PNaCl bitcode
70a47c11c7f17022050043d69c0802241e0747a056John Porto    FakeUse,       // not part of LLVM/PNaCl bitcode
71a47c11c7f17022050043d69c0802241e0747a056John Porto    FakeKill,      // not part of LLVM/PNaCl bitcode
72a47c11c7f17022050043d69c0802241e0747a056John Porto    JumpTable,     // not part of LLVM/PNaCl bitcode
73a47c11c7f17022050043d69c0802241e0747a056John Porto    ShuffleVector, // not part of LLVM/PNaCl bitcode
746ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // Anything >= Target is an InstTarget subclass. Note that the value-spaces
756ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // are shared across targets. To avoid confusion over the definition of
766ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // shared values, an object specific to one target should never be passed
776ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // to a different target.
786ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target,
796ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    Target_Max = std::numeric_limits<uint8_t>::max(),
80f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
816ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  static_assert(Target <= Target_Max, "Must not be above max.");
82f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstKind getKind() const { return Kind; }
83467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  virtual const char *getInstName() const;
84f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
85d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT getNumber() const { return Number; }
86d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void renumber(Cfg *Func);
87e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  enum {
88e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberDeleted = -1,
89e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberSentinel = 0,
90e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberInitial = 2,
91e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberExtended = NumberInitial - 1
92e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  };
93f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isDeleted() const { return Deleted; }
95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void setDeleted() { Deleted = true; }
96a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  void setDead(bool Value = true) { Dead = Value; }
97d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void deleteIfDead();
98f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasSideEffects() const { return HasSideEffects; }
100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
101230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool isDestRedefined() const { return IsDestRedefined; }
102230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  void setDestRedefined() { IsDestRedefined = true; }
1034775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth
104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *getDest() const { return Dest; }
105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
10645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  SizeT getSrcSize() const { return Srcs.size(); }
107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSrc(SizeT I) const {
108f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < getSrcSize());
109f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Srcs[I];
110f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
111032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee  void replaceSource(SizeT Index, Operand *Replacement) {
11245f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee    assert(Index < getSrcSize());
113032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    assert(!isDeleted());
114032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee    Srcs[Index] = Replacement;
115032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee  }
116f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
117d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool isLastUse(const Operand *Src) const;
1188e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth  void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
119d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
1206ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Returns a list of out-edges corresponding to a terminator instruction,
1216ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// which is the last instruction of the block. The list must not contain
1226ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// duplicates.
123f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual NodeList getTerminatorEdges() const {
1246ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // All valid terminator instructions override this method. For the default
1256ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // implementation, we assert in case some CfgNode is constructed without a
1266ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    // terminator instruction at the end.
127f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    llvm_unreachable(
128f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        "getTerminatorEdges() called on a non-terminator instruction");
129f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return NodeList();
130f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
131336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool isUnconditionalBranch() const { return false; }
13257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// If the instruction is a branch-type instruction with OldNode as a target,
13357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// repoint it to NewNode and return true, otherwise return false. Repoint all
13457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instances of OldNode as a target.
13587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
136336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)OldNode;
137336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)NewNode;
138336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    return false;
139336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
140f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
14128b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// Returns true if the instruction is equivalent to a simple
14228b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  /// "var_dest=var_src" assignment where the dest and src are both variables.
14328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  virtual bool isVarAssign() const { return false; }
144ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
145f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// Returns true if the instruction has a possible side effect of changing
146f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// memory, in which case a memory load should not be reordered with respect
147f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// to this instruction.  It should really be pure virtual, but we can't
148f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// because of g++ and llvm::ilist<>, so we implement it as
149f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  /// report_fatal_error().
150f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  virtual bool isMemoryWrite() const;
151f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth
152b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// Returns true if the (target-specific) instruction represents an
153b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// intra-block label, i.e. branch target.  This is meant primarily for
154b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// Cfg::splitLocalVars().
155b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  virtual bool isLabel() const { return false; }
156b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// If the (target-specific) instruction represents an intra-block branch to
157b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// some Label instruction, return that Label branch target instruction;
158b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  /// otherwise return nullptr.
159b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth  virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; }
160b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth
1614775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessLightweight(Cfg *Func, LivenessBV &Live);
16257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Calculates liveness for this instruction. Returns true if this instruction
16357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// is (tentatively) still live and should be retained, and false if this
16457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction is (tentatively) dead and should be deleted. The decision is
16557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// tentative until the liveness dataflow algorithm has converged, and then a
16657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// separate pass permanently deletes dead instructions.
167336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
1684775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
1691873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth
1706ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// Get the number of native instructions that this instruction ultimately
1716ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// emits. By default, high-level instructions don't result in any native
1726ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instructions, and a target-specific instruction results in a single native
1736ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull  /// instruction.
1741873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  virtual uint32_t getEmitInstCount() const { return 0; }
17557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
17657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
17757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
17857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // allow the abstract class Ice::Inst. The method should be declared
17957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
18057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
181dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emit(const Cfg *) const {
182dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth    llvm_unreachable("emit on abstract class");
183dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  }
184dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
185f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void dump(const Cfg *Func) const;
186d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  virtual void dumpExtras(const Cfg *Func) const;
187f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDecorated(const Cfg *Func) const;
1885bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  void emitSources(const Cfg *Func) const;
189f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpSources(const Cfg *Func) const;
190f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDest(const Cfg *Func) const;
1915bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  virtual bool isRedundantAssign() const { return false; }
192f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
193fc707ffe812339bddf4ca28fbe8c01045e2b42d6Sean Klein  virtual ~Inst() = default;
194f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
195f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected:
196f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
197f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addSource(Operand *Src) {
198f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(Src);
19945f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee    Srcs.push_back(Src);
200f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
201d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void setLastUse(SizeT VarIndex) {
202d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
203d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
204d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
205d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void resetLastUses() { LiveRangesEnded = 0; }
20657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// The destroy() method lets the instruction cleanly release any memory that
20757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// was allocated via the Cfg's allocator.
20845f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  virtual void destroy(Cfg *) {}
209f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
210f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const InstKind Kind;
2119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Number is the instruction number for describing live ranges.
212d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT Number;
2139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Deleted means irrevocably deleted.
214eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Deleted = false;
21557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Dead means one of two things depending on context: (1) pending deletion
21657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// after liveness analysis converges, or (2) marked for deletion during
21757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// lowering due to a folded bool operation.
218eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Dead = false;
21957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// HasSideEffects means the instruction is something like a function call or
22057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// a volatile load that can't be removed even if its Dest variable is not
22157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// live.
222eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool HasSideEffects = false;
223230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// IsDestRedefined indicates that this instruction is not the first
224230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// definition of Dest in the basic block.  The effect is that liveness
225230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// analysis shouldn't consider this instruction to be the start of Dest's
226230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range; rather, there is some other instruction earlier in the basic
227230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// block with the same Dest.  This is maintained because liveness analysis
228230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// has an invariant (primarily for performance reasons) that any Variable's
229230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// live range recorded in a basic block has at most one start and at most one
230230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  /// end.
231230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth  bool IsDestRedefined = false;
232f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
233f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *Dest;
234f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const SizeT MaxSrcs; // only used for assert
23545f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee
23645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  CfgVector<Operand *> Srcs;
237f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
2389612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// LiveRangesEnded marks which Variables' live ranges end in this
23957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. An instruction can have an arbitrary number of source
24057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands (e.g. a call instruction), and each source operand can contain 0
24157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// or 1 Variable (and target-specific operands could contain more than 1
24257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Variable). All the variables in an instruction are conceptually flattened
24357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and each variable is mapped to one bit position of the LiveRangesEnded bit
24457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
2459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// tracked this way.
2468072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
247d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  LREndedBits LiveRangesEnded;
248f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
249f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
250b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst {
251c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstHighLevel() = delete;
2520795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel(const InstHighLevel &) = delete;
2530795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel &operator=(const InstHighLevel &) = delete;
254b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
255b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected:
256b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
257b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {}
258b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg * /*Func*/) const override {
259b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emit() called on a non-lowered instruction");
260b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
261b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emitIAS(const Cfg * /*Func*/) const override {
262b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emitIAS() called on a non-lowered instruction");
263b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
264b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth};
265b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
26657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the
26757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment
26857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2.
269b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel {
270c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAlloca() = delete;
2717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca(const InstAlloca &) = delete;
2727b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca &operator=(const InstAlloca &) = delete;
2737b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
2752f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
2762f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr                            uint32_t AlignInBytes) {
27731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAlloca>())
2782f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr        InstAlloca(Func, Dest, ByteCount, AlignInBytes);
279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
280f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint32_t getAlignInBytes() const { return AlignInBytes; }
281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSizeInBytes() const { return getSrc(0); }
28255f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool getKnownFrameOffset() const { return KnownFrameOffset; }
28355f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  void setKnownFrameOffset() { KnownFrameOffset = true; }
284f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
285b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
2868cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
2892f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr  InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
2902f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr             uint32_t AlignInBytes);
2911bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
292f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const uint32_t AlignInBytes;
29355f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth  bool KnownFrameOffset = false;
294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
29657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0)
29757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1).
298b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel {
299c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstArithmetic() = delete;
3007b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic(const InstArithmetic &) = delete;
3017b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic &operator=(const InstArithmetic &) = delete;
3027b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
304f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
305f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag,
306f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTARITHMETIC_TABLE
307f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
3084376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
309f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
3105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
311f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
312f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                                Operand *Source1, Operand *Source2) {
31331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstArithmetic>())
314f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstArithmetic(Func, Op, Dest, Source1, Source2);
315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
316f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getOp() const { return Op; }
317e37076a176e04eee0f35058ccd2109754c193015Eric Holk
318467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  virtual const char *getInstName() const override;
319e37076a176e04eee0f35058ccd2109754c193015Eric Holk
320d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf  static const char *getOpName(OpKind Op);
321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isCommutative() const;
322f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
323b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3248cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
3258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Arithmetic;
326f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
327f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
329f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
330f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                 Operand *Source2);
331f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
332f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind Op;
333f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
33557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is
33657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the
33757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering,
33857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for
33957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction.
340b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel {
341c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAssign() = delete;
3427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign(const InstAssign &) = delete;
3437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign &operator=(const InstAssign &) = delete;
3447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
346f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
34731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
34928b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth  bool isVarAssign() const override;
350f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
351b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
354f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
355f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
356f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
357f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
35857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional
35957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches.
360b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel {
361c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBr() = delete;
3627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr(const InstBr &) = delete;
3637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr &operator=(const InstBr &) = delete;
3647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
365f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
36657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
36757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to an unconditional branch.
368f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                        CfgNode *TargetFalse) {
37031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>())
371f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstBr(Func, Source, TargetTrue, TargetFalse);
372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
3739612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Create an unconditional branch.
374f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, CfgNode *Target) {
37531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>()) InstBr(Func, Target);
376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
377ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  bool isUnconditional() const { return getTargetTrue() == nullptr; }
378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const {
379f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(!isUnconditional());
380f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
381f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
382f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetTrue() const { return TargetTrue; }
383f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetFalse() const { return TargetFalse; }
384f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetUnconditional() const {
385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(isUnconditional());
386f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getTargetFalse();
387f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
388b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
389336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool isUnconditionalBranch() const override { return isUnconditional(); }
39087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
391f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
392b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
3938cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
394f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
395f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
3969612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Conditional branch
397f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
3989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Unconditional branch
399f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, CfgNode *Target);
400f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetFalse; /// Doubles as unconditional branch target
4029612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode *TargetTrue;  /// nullptr if unconditional branch
403f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
404f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
40557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is
40657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1).
407b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel {
408c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCall() = delete;
4097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall(const InstCall &) = delete;
4107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall &operator=(const InstCall &) = delete;
4117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
412f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
413f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
4145e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          Operand *CallTarget, bool HasTailCall,
4155e0a8a71b75ec56981883587612b16f7c1635a03John Porto                          bool IsTargetHelperCall = false) {
4169612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull    /// Set HasSideEffects to true so that the call instruction can't be
41757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// dead-code eliminated. IntrinsicCalls can override this if the particular
41857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    /// intrinsic is deletable and has no side-effects.
4195bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr bool HasSideEffects = true;
4205bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    constexpr InstKind Kind = Inst::Call;
4215e0a8a71b75ec56981883587612b16f7c1635a03John Porto    return new (Func->allocate<InstCall>())
4225e0a8a71b75ec56981883587612b16f7c1635a03John Porto        InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
4235e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 IsTargetHelperCall, HasSideEffects, Kind);
424f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
425f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArg(Operand *Arg) { addSource(Arg); }
426f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCallTarget() const { return getSrc(0); }
427f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
428f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumArgs() const { return getSrcSize() - 1; }
4298df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool isTailcall() const { return HasTailCall; }
4305e0a8a71b75ec56981883587612b16f7c1635a03John Porto  bool isTargetHelperCall() const { return IsTargetHelperCall; }
431f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return true; }
4323ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung  void dump(const Cfg *Func) const override;
4338cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
4348df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  Type getReturnType() const;
435f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4363bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected:
4373bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
4385e0a8a71b75ec56981883587612b16f7c1635a03John Porto           bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
4395e0a8a71b75ec56981883587612b16f7c1635a03John Porto           InstKind Kind)
4405e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
4415e0a8a71b75ec56981883587612b16f7c1635a03John Porto        IsTargetHelperCall(IsTargetHelperCall) {
4423bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    HasSideEffects = HasSideEff;
443f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    addSource(CallTarget);
444f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
4453bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
4463bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
4475e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool HasTailCall;
4485e0a8a71b75ec56981883587612b16f7c1635a03John Porto  const bool IsTargetHelperCall;
449f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
450f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4519612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation).
452b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel {
453c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCast() = delete;
4547b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast(const InstCast &) = delete;
4557b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast &operator=(const InstCast &) = delete;
4567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
457f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
458f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
459f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
460f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTCAST_TABLE
461f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4624376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
463f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
465bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf  static const char *getCastName(OpKind Kind);
466bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf
467f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
468f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source) {
46931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCast>())
470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstCast(Func, CastKind, Dest, Source);
471f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
472f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getCastKind() const { return CastKind; }
473f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
474b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4758cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
477f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
478f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
4791bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
480f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind CastKind;
481f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
482f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4839612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction.
484b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel {
485c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstExtractElement() = delete;
4867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement(const InstExtractElement &) = delete;
4877b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement &operator=(const InstExtractElement &) = delete;
4887b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
48949889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
49049889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
49149889239d4c7ab296c7430722d36032d905110b6Matt Wala                                    Operand *Source2) {
49231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstExtractElement>())
49349889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstExtractElement(Func, Dest, Source1, Source2);
49449889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
49549889239d4c7ab296c7430722d36032d905110b6Matt Wala
496f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
497b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
4988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
4998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == ExtractElement;
50049889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
50149889239d4c7ab296c7430722d36032d905110b6Matt Wala
50249889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
50349889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
50449889239d4c7ab296c7430722d36032d905110b6Matt Wala                     Operand *Source2);
50549889239d4c7ab296c7430722d36032d905110b6Matt Wala};
50649889239d4c7ab296c7430722d36032d905110b6Matt Wala
50757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in
50857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
509b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel {
510c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFcmp() = delete;
5117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp(const InstFcmp &) = delete;
5127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp &operator=(const InstFcmp &) = delete;
5137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
515f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum FCond {
516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTFCMP_TABLE
518f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5194376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5215bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
52431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFcmp>())
525f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstFcmp(Func, Condition, Dest, Source1, Source2);
526f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
527f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  FCond getCondition() const { return Condition; }
528f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
529b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5308cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
531f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
533f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
534f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5351bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
536f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const FCond Condition;
537f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
538f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
53957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in
54057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1).
541b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel {
542c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIcmp() = delete;
5437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp(const InstIcmp &) = delete;
5447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp &operator=(const InstIcmp &) = delete;
5457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
546f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
547f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum ICond {
5480c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee#define X(tag, inverse, str) tag,
549f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTICMP_TABLE
550f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5514376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
552f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
554f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
555f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
55631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIcmp>())
557f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstIcmp(Func, Condition, Dest, Source1, Source2);
558f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
559f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  ICond getCondition() const { return Condition; }
5600c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee  void reverseConditionAndOperands();
561f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
562b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5638cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
564f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
565f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
566f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
567f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5681bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
5690c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee  ICond Condition;
570f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
571f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
5729612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction.
573b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel {
574c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstInsertElement() = delete;
5757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement(const InstInsertElement &) = delete;
5767b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement &operator=(const InstInsertElement &) = delete;
5777b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
57849889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
57949889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
58049889239d4c7ab296c7430722d36032d905110b6Matt Wala                                   Operand *Source2, Operand *Source3) {
58131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstInsertElement>())
58249889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstInsertElement(Func, Dest, Source1, Source2, Source3);
58349889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
58449889239d4c7ab296c7430722d36032d905110b6Matt Wala
585f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
586b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
5878cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
5888cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == InsertElement;
58949889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
59049889239d4c7ab296c7430722d36032d905110b6Matt Wala
59149889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
59249889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
59349889239d4c7ab296c7430722d36032d905110b6Matt Wala                    Operand *Source2, Operand *Source3);
59449889239d4c7ab296c7430722d36032d905110b6Matt Wala};
59549889239d4c7ab296c7430722d36032d905110b6Matt Wala
59657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and
59757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1).
5983bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall {
599c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIntrinsicCall() = delete;
6007b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall(const InstIntrinsicCall &) = delete;
6017b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
6027b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
6033bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic:
6043bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
6053bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   Operand *CallTarget,
6063bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   const Intrinsics::IntrinsicInfo &Info) {
60731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIntrinsicCall>())
6083bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
6093bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
6108cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
6118cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == IntrinsicCall;
6123bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
6133bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
6143bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
615f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override {
616f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth    return getIntrinsicInfo().IsMemoryWrite;
617f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  }
6183bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
6193bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
6203bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
6213bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                    Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
6225e0a8a71b75ec56981883587612b16f7c1635a03John Porto      : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
6235e0a8a71b75ec56981883587612b16f7c1635a03John Porto                 Info.HasSideEffects, Inst::IntrinsicCall),
6243bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        Info(Info) {}
6251bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
6263bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  const Intrinsics::IntrinsicInfo Info;
6273bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung};
6283bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
62957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0).
630b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel {
631c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstLoad() = delete;
6327b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad(const InstLoad &) = delete;
6337b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad &operator=(const InstLoad &) = delete;
6347b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
635f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
63641689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
637c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth                          uint32_t Align = 1) {
63841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
639c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    (void)Align;
64031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
641f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSourceAddress() const { return getSrc(0); }
643f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
644b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6458cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
646f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
647f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
649f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
650f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
65157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
65257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I).
653b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel {
654c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstPhi() = delete;
6557b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi(const InstPhi &) = delete;
6567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi &operator=(const InstPhi &) = delete;
6577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
658f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
659f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
66031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
661f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
662f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArgument(Operand *Source, CfgNode *Label);
6635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  Operand *getOperandForTarget(CfgNode *Target) const;
664263ac526cb5d182e5bedb16e90566ae8ba1f36ffDavid Sehr  void clearOperandForTarget(CfgNode *Target);
66598712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
66616f8061ca23653172ea4c1a43659bb0501b5b474Eric Holk  void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
6674775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
668d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth                          Liveness *Liveness);
669144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Inst *lower(Cfg *Func);
670f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
671b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
6728cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
674f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
675f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
67645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  void destroy(Cfg *Func) override { Inst::destroy(Func); }
677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
67857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
67957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// but the Phi instruction is created before InEdges[] is available, so it's
68057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// more complicated to share the list.
68145f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee  CfgVector<CfgNode *> Labels;
682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
683f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
68457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is
68557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and
68657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false.
687b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel {
688c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstRet() = delete;
6897b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet(const InstRet &) = delete;
6907b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet &operator=(const InstRet &) = delete;
6917b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
693ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
69431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
695f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
696f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasRetValue() const { return getSrcSize(); }
697f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getRetValue() const {
698f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(hasRetValue());
699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
701b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
702f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
703b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7048cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
705f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
707f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstRet(Cfg *Func, Operand *RetValue);
708f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
709f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
7109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction.  The condition, true, and false operands are captured.
711b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel {
712c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSelect() = delete;
7137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect(const InstSelect &) = delete;
7147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect &operator=(const InstSelect &) = delete;
7157b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            Operand *SourceTrue, Operand *SourceFalse) {
71931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSelect>())
720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
721f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
722f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const { return getSrc(0); }
723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getTrueOperand() const { return getSrc(1); }
724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getFalseOperand() const { return getSrc(2); }
725f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
726b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7278cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
730f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
731f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Operand *Source2);
732f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
73457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data
73557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address.
736b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel {
737c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstStore() = delete;
7387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore(const InstStore &) = delete;
7397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore &operator=(const InstStore &) = delete;
7407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
74241689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
743e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth                           uint32_t Align = 1) {
74441689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
745e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth    (void)Align;
74631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
748f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getAddr() const { return getSrc(1); }
749f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getData() const { return getSrc(0); }
750aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  Variable *getRmwBeacon() const;
751e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth  void setRmwBeacon(Variable *Beacon);
752f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return true; }
753b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7548cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
756f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
757f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
758f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
759f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
76057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0).
761b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel {
762c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSwitch() = delete;
7637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch(const InstSwitch &) = delete;
7647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch &operator=(const InstSwitch &) = delete;
7657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
767f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
768f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            CfgNode *LabelDefault) {
76931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSwitch>())
770f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSwitch(Func, NumCases, Source, LabelDefault);
771f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
772f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getComparison() const { return getSrc(0); }
773f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabelDefault() const { return LabelDefault; }
774f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumCases() const { return NumCases; }
775f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t getValue(SizeT I) const {
776f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
777f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Values[I];
778f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
779f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabel(SizeT I) const {
780f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
781f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Labels[I];
782f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
783f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
784b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
78587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
786f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
787b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
7888cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
789f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
790f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
791f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
792b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
793f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<uint64_t>(Values);
794f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
795f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
796f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
797f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
798f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *LabelDefault;
7999612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  SizeT NumCases;   /// not including the default case
8009612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  uint64_t *Values; /// size is NumCases
8019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  CfgNode **Labels; /// size is NumCases
802f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
803f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
80457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands.
805b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel {
806c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstUnreachable() = delete;
8077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable(const InstUnreachable &) = delete;
8087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable &operator=(const InstUnreachable &) = delete;
8097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
810f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
811f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstUnreachable *create(Cfg *Func) {
81231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
813f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
814b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
815f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
816b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8188cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == Unreachable;
819f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
820f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
821f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
822c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  explicit InstUnreachable(Cfg *Func);
823f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
824f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
82557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction.  There are no operands. Contains an option
8269612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified.
8279f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel {
828c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleLock() = delete;
8299f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(const InstBundleLock &) = delete;
8309f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock &operator=(const InstBundleLock &) = delete;
8319f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8329f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
83356958cb33d3c1d045f2844408d825442d523f59fJohn Porto  enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
8349f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleLock *create(Cfg *Func, Option BundleOption) {
8359f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleLock>())
8369f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth        InstBundleLock(Func, BundleOption);
8379f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8389f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8399f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
840f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
8419f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8429f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option getOption() const { return BundleOption; }
8438cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8448cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleLock;
8459f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8469f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8479f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8489f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option BundleOption;
8499f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(Cfg *Func, Option BundleOption);
8509f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8519f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
85257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands.
8539f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel {
854c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleUnlock() = delete;
8559f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock(const InstBundleUnlock &) = delete;
8569f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
8579f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8589f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
8599f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleUnlock *create(Cfg *Func) {
8609f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
8619f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8629f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8639f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
864f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
8659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8668cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
8678cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == BundleUnlock;
8689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8709f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8719f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  explicit InstBundleUnlock(Cfg *Func);
8729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8739f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
87457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is
87557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results.
87657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered
87757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags
87857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction.
8799612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
88057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest
88157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest.
88257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its
88357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
88457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized.
885b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel {
886c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeDef() = delete;
8877b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef(const InstFakeDef &) = delete;
8887b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef &operator=(const InstFakeDef &) = delete;
8897b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
891ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstFakeDef *create(Cfg *Func, Variable *Dest,
892ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth                             Variable *Src = nullptr) {
89331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
8945bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
895b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
896198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
897f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
898b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
9005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
9025bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
9035bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
90557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the
90657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated.
90757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction
9088ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// has no dest, so it can itself never be dead-code eliminated.  A weight can
9098ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// be provided to provide extra bias to the register allocator - for simplicity
9108ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// of implementation, weight=N is handled by holding N copies of the variable
9118ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// as source operands.
912b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel {
913c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeUse() = delete;
9147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse(const InstFakeUse &) = delete;
9157b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse &operator=(const InstFakeUse &) = delete;
9167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
9175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
9188ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
9198ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth    return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
9205bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
921b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
922198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
923f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
924b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
9265bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9275bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
9288ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
9295bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9305bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
93157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial
93257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use
93357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the
93457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live
93557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call.
9369612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
93757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills
93857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code
93957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well.
940b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel {
941c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeKill() = delete;
9427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill(const InstFakeKill &) = delete;
9437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill &operator=(const InstFakeKill &) = delete;
9447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
9455bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
94687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
94731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
9485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
9495bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *getLinked() const { return Linked; }
950b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
951198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
952f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
953b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9548cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
9558cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == FakeKill;
9568cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
9575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
95987ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  InstFakeKill(Cfg *Func, const Inst *Linked);
9605bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9619612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// This instruction is ignored if Linked->isDeleted() is true.
9625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *Linked;
9635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
965a47c11c7f17022050043d69c0802241e0747a056John Porto/// ShuffleVector instruction. This represents a shuffle operation on vector
966a47c11c7f17022050043d69c0802241e0747a056John Porto/// types. This instruction is not part of the PNaCl bitcode: it is generated
967a47c11c7f17022050043d69c0802241e0747a056John Porto/// by Subzero when it matches the pattern used by pnacl-clang when compiling
968a47c11c7f17022050043d69c0802241e0747a056John Porto/// to bitcode.
969a47c11c7f17022050043d69c0802241e0747a056John Portoclass InstShuffleVector : public InstHighLevel {
970a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector() = delete;
971a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector(const InstShuffleVector &) = delete;
972a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector &operator=(const InstShuffleVector &) = delete;
973a47c11c7f17022050043d69c0802241e0747a056John Porto
974a47c11c7f17022050043d69c0802241e0747a056John Portopublic:
975a47c11c7f17022050043d69c0802241e0747a056John Porto  static InstShuffleVector *create(Cfg *Func, Variable *Dest, Variable *Src0,
976a47c11c7f17022050043d69c0802241e0747a056John Porto                                   Variable *Src1) {
977a47c11c7f17022050043d69c0802241e0747a056John Porto    return new (Func->allocate<InstShuffleVector>())
978a47c11c7f17022050043d69c0802241e0747a056John Porto        InstShuffleVector(Func, Dest, Src0, Src1);
979a47c11c7f17022050043d69c0802241e0747a056John Porto  }
980a47c11c7f17022050043d69c0802241e0747a056John Porto
981a47c11c7f17022050043d69c0802241e0747a056John Porto  SizeT getNumIndexes() const { return NumIndexes; }
982a47c11c7f17022050043d69c0802241e0747a056John Porto
983a47c11c7f17022050043d69c0802241e0747a056John Porto  void addIndex(ConstantInteger32 *Index) {
984a47c11c7f17022050043d69c0802241e0747a056John Porto    assert(CurrentIndex < NumIndexes);
985a47c11c7f17022050043d69c0802241e0747a056John Porto    Indexes[CurrentIndex++] = Index;
986a47c11c7f17022050043d69c0802241e0747a056John Porto  }
987a47c11c7f17022050043d69c0802241e0747a056John Porto
988a47c11c7f17022050043d69c0802241e0747a056John Porto  ConstantInteger32 *getIndex(SizeT Pos) const {
989a47c11c7f17022050043d69c0802241e0747a056John Porto    assert(Pos < NumIndexes);
990a47c11c7f17022050043d69c0802241e0747a056John Porto    return Indexes[Pos];
991a47c11c7f17022050043d69c0802241e0747a056John Porto  }
992a47c11c7f17022050043d69c0802241e0747a056John Porto
993cd261e9187a065dc7b917af8f2f8ff435fcf4c15Jim Stichnoth  bool isMemoryWrite() const override { return false; }
994a47c11c7f17022050043d69c0802241e0747a056John Porto  void dump(const Cfg *Func) const override;
995a47c11c7f17022050043d69c0802241e0747a056John Porto  static bool classof(const Inst *Instr) {
996a47c11c7f17022050043d69c0802241e0747a056John Porto    return Instr->getKind() == ShuffleVector;
997a47c11c7f17022050043d69c0802241e0747a056John Porto  }
998a47c11c7f17022050043d69c0802241e0747a056John Porto
999a47c11c7f17022050043d69c0802241e0747a056John Portoprivate:
1000a47c11c7f17022050043d69c0802241e0747a056John Porto  InstShuffleVector(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1);
1001a47c11c7f17022050043d69c0802241e0747a056John Porto
1002a47c11c7f17022050043d69c0802241e0747a056John Porto  void destroy(Cfg *Func) override {
1003a47c11c7f17022050043d69c0802241e0747a056John Porto    Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
1004a47c11c7f17022050043d69c0802241e0747a056John Porto    Inst::destroy(Func);
1005a47c11c7f17022050043d69c0802241e0747a056John Porto  }
1006a47c11c7f17022050043d69c0802241e0747a056John Porto
1007a47c11c7f17022050043d69c0802241e0747a056John Porto  ConstantInteger32 **Indexes;
1008a47c11c7f17022050043d69c0802241e0747a056John Porto  SizeT CurrentIndex = 0;
1009a47c11c7f17022050043d69c0802241e0747a056John Porto  const SizeT NumIndexes;
1010a47c11c7f17022050043d69c0802241e0747a056John Porto};
1011a47c11c7f17022050043d69c0802241e0747a056John Porto
101257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in
101357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes
101457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering.
101587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel {
101687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable() = delete;
101787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(const InstJumpTable &) = delete;
101887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable &operator=(const InstJumpTable &) = delete;
101987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
102087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic:
102187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
102287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    return new (Func->allocate<InstJumpTable>())
102387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull        InstJumpTable(Func, NumTargets, Default);
102487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
102587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void addTarget(SizeT TargetIndex, CfgNode *Target) {
102687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    assert(TargetIndex < NumTargets);
102787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Targets[TargetIndex] = Target;
102887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
102987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
103086df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getId() const { return Id; }
103186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getNumTargets() const { return NumTargets; }
103286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  CfgNode *getTarget(SizeT I) const {
103386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    assert(I < NumTargets);
103486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return Targets[I];
103586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
1036f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
103787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void dump(const Cfg *Func) const override;
10388cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) {
10398cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth    return Instr->getKind() == JumpTable;
10408cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  }
1041030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // Creates a JumpTableData struct (used for ELF emission) that represents this
1042030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // InstJumpTable.
1043030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  JumpTableData toJumpTableData(Assembler *Asm) const;
104487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
1045030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // InstJumpTable is just a placeholder for the switch targets, and it does not
1046030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  // need to emit any code, so we redefine emit and emitIAS to do nothing.
1047030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  void emit(const Cfg *) const override {}
1048030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  void emitIAS(const Cfg * /* Func */) const override {}
1049030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto
1050030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  const std::string getName() const {
1051030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    assert(Name.hasStdString());
1052030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    return Name.toString();
1053030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  }
1054030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto
1055030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  std::string getSectionName() const {
1056030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    return JumpTableData::createSectionName(FuncName);
105786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  }
105886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
105987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate:
106087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
106187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  void destroy(Cfg *Func) override {
106287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Func->deallocateArrayOf<CfgNode *>(Targets);
106387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Inst::destroy(Func);
106487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
106587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
106686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  const SizeT Id;
106787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  const SizeT NumTargets;
106887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CfgNode **Targets;
1069030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString Name; // This JumpTable's name in the output.
1070030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString FuncName;
107187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull};
107287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
107367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction inserts an unconditional breakpoint.
107467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk///
107567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// On x86, this assembles into an INT 3 instruction.
107667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk///
107767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction is primarily meant for debugging the code generator.
107867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkclass InstBreakpoint : public InstHighLevel {
107967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic:
108067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint() = delete;
108167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint(const InstBreakpoint &) = delete;
108267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  InstBreakpoint &operator=(const InstBreakpoint &) = delete;
108367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
1084f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  explicit InstBreakpoint(Cfg *Func);
1085f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override { return false; }
108667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
108767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic:
108867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  static InstBreakpoint *create(Cfg *Func) {
108967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk    return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
109067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  }
109167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
109267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  static bool classof(const Inst *Instr) {
109367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk    return Instr->getKind() == Breakpoint;
109467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk  }
109567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk};
109667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk
10979612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific
10989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions.
10995bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst {
1100c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstTarget() = delete;
11010795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget(const InstTarget &) = delete;
11020795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget &operator=(const InstTarget &) = delete;
1103b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
11045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
1105b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  uint32_t getEmitInstCount() const override { return 1; }
1106f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  bool isMemoryWrite() const override {
1107f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth    return true; // conservative answer
1108f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth  }
1109b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
11108cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
11115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
11125bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected:
11135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
11145bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {
11155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    assert(Kind >= Target);
11166ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull    assert(Kind <= Target_Max);
11175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
11185bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
11195bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
1120b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
1121b3401d27a236b81393092b4d571df473b5bba64bJan Voung
1122f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
1123f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
1124dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm {
1125dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
112657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted
112757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked.
1128607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <>
1129dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
1130607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *createSentinel() const {
1131607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth    return static_cast<Ice::Inst *>(&Sentinel);
1132607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  }
1133607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void destroySentinel(Ice::Inst *) {}
1134607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *provideInitialHead() const { return createSentinel(); }
1135607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
1136607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void noteHead(Ice::Inst *, Ice::Inst *) {}
1137607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  void deleteNode(Ice::Inst *) {}
1138607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1139607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate:
1140607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  mutable ilist_half_node<Ice::Inst> Sentinel;
1141607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth};
1142607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
1143dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm
1144dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
1145f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothnamespace Ice {
1146f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1147f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline InstList::iterator instToIterator(Inst *Instr) {
1148f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#ifdef PNACL_LLVM
1149f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return Instr;
1150a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#else  // !PNACL_LLVM
1151f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return Instr->getIterator();
1152f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#endif // !PNACL_LLVM
1153f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth}
1154f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1155a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnothinline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; }
1156f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1157f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline const Inst *iteratorToInst(InstList::const_iterator Iter) {
1158f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return &*Iter;
1159f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth}
1160f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1161f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} // end of namespace Ice
1162f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth
1163f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H
1164