IceInst.h revision 1bec8bcd64da0cd4855a357d740d3ad45bbef3b9
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//===----------------------------------------------------------------------===//
9f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
10f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// This file declares the Inst class and its target-independent
11f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// subclasses, which represent the high-level Vanilla ICE instructions
12f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// and map roughly 1:1 to LLVM instructions.
13f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
14f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
15f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
16f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#ifndef SUBZERO_SRC_ICEINST_H
17f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define SUBZERO_SRC_ICEINST_H
18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
19f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceDefs.h"
20f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.def"
213bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung#include "IceIntrinsics.h"
22f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h"
23f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
24f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be
25f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// validated for things like valid operand types, valid branch
26f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// targets, proper ordering of Phi and non-Phi instructions, etc.
27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Most of the validity checking will be done in the bitcode reader.
28f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// We need a list of everything that should be validated, and tests
29f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// for each.
30f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
31f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice {
32f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
33b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// Base instruction class for ICE.  Inst has two subclasses:
34b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// InstHighLevel and InstTarget.  High-level ICE instructions inherit
35b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// from InstHighLevel, and low-level (target-specific) ICE
36b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth// instructions inherit from InstTarget.
37607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> {
38c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  Inst() = delete;
397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst(const Inst &) = delete;
407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  Inst &operator=(const Inst &) = delete;
417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
42f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
43f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum InstKind {
44f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // Arbitrary (alphabetical) order, except put Unreachable first.
45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Unreachable,
46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Alloca,
47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Arithmetic,
48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Br,
49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Call,
50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Cast,
5149889239d4c7ab296c7430722d36032d905110b6Matt Wala    ExtractElement,
52f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Fcmp,
53f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Icmp,
543bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    IntrinsicCall,
5549889239d4c7ab296c7430722d36032d905110b6Matt Wala    InsertElement,
56f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Load,
57f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Phi,
58f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Ret,
59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Select,
60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Store,
615bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Switch,
62c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth    Assign,       // not part of LLVM/PNaCl bitcode
639f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    BundleLock,   // not part of LLVM/PNaCl bitcode
649f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    BundleUnlock, // not part of LLVM/PNaCl bitcode
659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeDef,      // not part of LLVM/PNaCl bitcode
669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeUse,      // not part of LLVM/PNaCl bitcode
679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    FakeKill,     // not part of LLVM/PNaCl bitcode
689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    Target        // target-specific low-level ICE
699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth                  // Anything >= Target is an InstTarget subclass.
70b3401d27a236b81393092b4d571df473b5bba64bJan Voung                  // Note that the value-spaces are shared across targets.
71b3401d27a236b81393092b4d571df473b5bba64bJan Voung                  // To avoid confusion over the definition of shared values,
72b3401d27a236b81393092b4d571df473b5bba64bJan Voung                  // an object specific to one target should never be passed
73b3401d27a236b81393092b4d571df473b5bba64bJan Voung                  // to a different target.
74f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
75f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstKind getKind() const { return Kind; }
76f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
77d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT getNumber() const { return Number; }
78d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void renumber(Cfg *Func);
79e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  enum {
80e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberDeleted = -1,
81e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberSentinel = 0,
82e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberInitial = 2,
83e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    NumberExtended = NumberInitial - 1
84e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  };
85f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
86f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isDeleted() const { return Deleted; }
87f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void setDeleted() { Deleted = true; }
88a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  void setDead(bool Value = true) { Dead = Value; }
89d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void deleteIfDead();
90f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
91f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasSideEffects() const { return HasSideEffects; }
92f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
934775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  bool isDestNonKillable() const { return IsDestNonKillable; }
944775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void setDestNonKillable() { IsDestNonKillable = true; }
954775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth
96f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *getDest() const { return Dest; }
97f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
98f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getSrcSize() const { return NumSrcs; }
99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSrc(SizeT I) const {
100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < getSrcSize());
101f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Srcs[I];
102f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
103f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
104d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  bool isLastUse(const Operand *Src) const;
1058e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth  void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);
106d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Returns a list of out-edges corresponding to a terminator
108f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // instruction, which is the last instruction of the block.
109f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual NodeList getTerminatorEdges() const {
110f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // All valid terminator instructions override this method.  For
111f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // the default implementation, we assert in case some CfgNode
112f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    // is constructed without a terminator instruction at the end.
113f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    llvm_unreachable(
114f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        "getTerminatorEdges() called on a non-terminator instruction");
115f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return NodeList();
116f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
117336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool isUnconditionalBranch() const { return false; }
118336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // If the instruction is a branch-type instruction with OldNode as a
119336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // target, repoint it to NewNode and return true, otherwise return
120336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // false.  Only repoint one instance, even if the instruction has
121336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // multiple instances of OldNode as a target.
122336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
123336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)OldNode;
124336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    (void)NewNode;
125336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    return false;
126336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
127f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
128ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  virtual bool isSimpleAssign() const { return false; }
129ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
1304775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessLightweight(Cfg *Func, LivenessBV &Live);
131336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // Calculates liveness for this instruction.  Returns true if this
132336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // instruction is (tentatively) still live and should be retained,
133336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // and false if this instruction is (tentatively) dead and should be
134336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // deleted.  The decision is tentative until the liveness dataflow
135336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // algorithm has converged, and then a separate pass permanently
136336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  // deletes dead instructions.
137336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
1384775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
1391873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth
1401873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // Get the number of native instructions that this instruction
1411873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // ultimately emits.  By default, high-level instructions don't
1421873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // result in any native instructions, and a target-specific
1431873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  // instruction results in a single native instruction.
1441873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth  virtual uint32_t getEmitInstCount() const { return 0; }
145dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // TODO(stichnot): Change Inst back to abstract once the g++ build
146dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // issue is fixed.  llvm::ilist<Ice::Inst> doesn't work under g++
147dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // because the resize(size_t, Ice::Inst) method is incorrectly
148dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // declared and thus doesn't allow the abstract class Ice::Inst.
149dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // The method should be declared resize(size_t, const Ice::Inst &).
150dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // virtual void emit(const Cfg *Func) const = 0;
151dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  // virtual void emitIAS(const Cfg *Func) const = 0;
152dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emit(const Cfg *) const {
153dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth    llvm_unreachable("emit on abstract class");
154dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  }
155dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
156f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void dump(const Cfg *Func) const;
157d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  virtual void dumpExtras(const Cfg *Func) const;
158f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDecorated(const Cfg *Func) const;
1595bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  void emitSources(const Cfg *Func) const;
160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpSources(const Cfg *Func) const;
161f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void dumpDest(const Cfg *Func) const;
1625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  virtual bool isRedundantAssign() const { return false; }
163f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
1641bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto  // TODO(jpp): Insts should not have non-trivial destructors, but they
1651bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto  // currently do. This dtor is marked final as a multi-step refactor that
1661bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto  // will eventually fix this problem.
167eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  virtual ~Inst() = default;
168f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
169f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected:
170f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
171f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addSource(Operand *Src) {
172f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(Src);
173f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(NumSrcs < MaxSrcs);
174f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Srcs[NumSrcs++] = Src;
175f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
176d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void setLastUse(SizeT VarIndex) {
177d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
178d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
180d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  void resetLastUses() { LiveRangesEnded = 0; }
181f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // The destroy() method lets the instruction cleanly release any
182f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // memory that was allocated via the Cfg's allocator.
183f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); }
184f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
185f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const InstKind Kind;
186f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Number is the instruction number for describing live ranges.
187d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT Number;
188f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Deleted means irrevocably deleted.
189eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Deleted = false;
190a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  // Dead means one of two things depending on context: (1) pending
191a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  // deletion after liveness analysis converges, or (2) marked for
192a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth  // deletion during lowering due to a folded bool operation.
193eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool Dead = false;
194f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // HasSideEffects means the instruction is something like a function
195f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // call or a volatile load that can't be removed even if its Dest
196f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // variable is not live.
197eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool HasSideEffects = false;
1984775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  // IsDestNonKillable means that liveness analysis shouldn't consider
1994775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  // this instruction to kill the Dest variable.  This is used when
2004775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  // lowering produces two assignments to the same variable.
201eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool IsDestNonKillable = false;
202f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
203f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Variable *Dest;
204f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const SizeT MaxSrcs; // only used for assert
205eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  SizeT NumSrcs = 0;
206f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand **Srcs;
207f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
208d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // LiveRangesEnded marks which Variables' live ranges end in this
209d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // instruction.  An instruction can have an arbitrary number of
210d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // source operands (e.g. a call instruction), and each source
211d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // operand can contain 0 or 1 Variable (and target-specific operands
212d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // could contain more than 1 Variable).  All the variables in an
213d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // instruction are conceptually flattened and each variable is
214d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // mapped to one bit position of the LiveRangesEnded bit vector.
215d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // Only the first CHAR_BIT * sizeof(LREndedBits) variables are
216d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // tracked this way.
217d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry
218d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  LREndedBits LiveRangesEnded;
219f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
220f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
221b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst {
222c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstHighLevel() = delete;
2230795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel(const InstHighLevel &) = delete;
2240795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstHighLevel &operator=(const InstHighLevel &) = delete;
225b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
226b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected:
227b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
228b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {}
229b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg * /*Func*/) const override {
230b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emit() called on a non-lowered instruction");
231b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
232b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emitIAS(const Cfg * /*Func*/) const override {
233b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth    llvm_unreachable("emitIAS() called on a non-lowered instruction");
234b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  }
235b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth};
236b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
237f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Alloca instruction.  This captures the size in bytes as getSrc(0),
238f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// and the required alignment in bytes.  The alignment must be either
239f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 0 (no alignment required) or a power of 2.
240b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel {
241c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAlloca() = delete;
2427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca(const InstAlloca &) = delete;
2437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAlloca &operator=(const InstAlloca &) = delete;
2447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
245f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
246f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAlloca *create(Cfg *Func, Operand *ByteCount,
247f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            uint32_t AlignInBytes, Variable *Dest) {
24831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAlloca>())
249f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstAlloca(Func, ByteCount, AlignInBytes, Dest);
250f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
251f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint32_t getAlignInBytes() const { return AlignInBytes; }
252f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSizeInBytes() const { return getSrc(0); }
253b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
254f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; }
255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
256f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
257f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
258f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Variable *Dest);
2591bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
260f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const uint32_t AlignInBytes;
261f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
262f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
263f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Binary arithmetic instruction.  The source operands are captured in
264f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0) and getSrc(1).
265b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel {
266c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstArithmetic() = delete;
2677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic(const InstArithmetic &) = delete;
2687b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstArithmetic &operator=(const InstArithmetic &) = delete;
2697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
270f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
271f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
272f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag,
273f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTARITHMETIC_TABLE
274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
2754376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
276f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
2775bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
278f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                                Operand *Source1, Operand *Source2) {
28031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstArithmetic>())
281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstArithmetic(Func, Op, Dest, Source1, Source2);
282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
283f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getOp() const { return Op; }
284d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf  static const char *getOpName(OpKind Op);
285f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool isCommutative() const;
286b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) {
288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Inst->getKind() == Arithmetic;
289f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
290f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
291f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
292f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
293f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                 Operand *Source2);
294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind Op;
296f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
297f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
298f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Assignment instruction.  The source operand is captured in
299f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0).  This is not part of the LLVM bitcode, but is a useful
300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// abstraction for some of the lowering.  E.g., if Phi instruction
301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// lowering happens before target lowering, or for representing an
302f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Inttoptr instruction, or as an intermediate step for lowering a
303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Load instruction.
304b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel {
305c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstAssign() = delete;
3067b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign(const InstAssign &) = delete;
3077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstAssign &operator=(const InstAssign &) = delete;
3087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
309f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
310f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
31131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
312f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
313b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  bool isSimpleAssign() const override { return true; }
314b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; }
316f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
317f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
318f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Branch instruction.  This represents both conditional and
322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// unconditional branches.
323b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel {
324c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBr() = delete;
3257b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr(const InstBr &) = delete;
3267b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstBr &operator=(const InstBr &) = delete;
3277b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
329f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Create a conditional branch.  If TargetTrue==TargetFalse, it is
330f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // optimized to an unconditional branch.
331f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
332f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                        CfgNode *TargetFalse) {
33331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>())
334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstBr(Func, Source, TargetTrue, TargetFalse);
335f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
336f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Create an unconditional branch.
337f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstBr *create(Cfg *Func, CfgNode *Target) {
33831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstBr>()) InstBr(Func, Target);
339f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
340ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  bool isUnconditional() const { return getTargetTrue() == nullptr; }
341f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const {
342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(!isUnconditional());
343f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
344f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetTrue() const { return TargetTrue; }
346f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetFalse() const { return TargetFalse; }
347f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getTargetUnconditional() const {
348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(isUnconditional());
349f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getTargetFalse();
350f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
351b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
352336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool isUnconditionalBranch() const override { return isUnconditional(); }
353336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
354b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
355f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Br; }
356f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
357f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
358f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Conditional branch
359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Unconditional branch
361f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstBr(Cfg *Func, CfgNode *Target);
362f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
363336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  CfgNode *TargetFalse; // Doubles as unconditional branch target
364ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  CfgNode *TargetTrue;  // nullptr if unconditional branch
365f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
366f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
367f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Call instruction.  The call target is captured as getSrc(0), and
368f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// arg I is captured as getSrc(I+1).
369b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel {
370c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCall() = delete;
3717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall(const InstCall &) = delete;
3727b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCall &operator=(const InstCall &) = delete;
3737b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
374f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
375f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
3768df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf                          Operand *CallTarget, bool HasTailCall) {
3773bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    // Set HasSideEffects to true so that the call instruction can't be
3783bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    // dead-code eliminated. IntrinsicCalls can override this if the
3793bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    // particular intrinsic is deletable and has no side-effects.
3803bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    const bool HasSideEffects = true;
3813bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    const InstKind Kind = Inst::Call;
38231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCall>()) InstCall(
3838df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf        Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
384f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArg(Operand *Arg) { addSource(Arg); }
386f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCallTarget() const { return getSrc(0); }
387f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
388f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumArgs() const { return getSrcSize() - 1; }
3898df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool isTailcall() const { return HasTailCall; }
3903ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung  void dump(const Cfg *Func) const override;
391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
3928df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  Type getReturnType() const;
393f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
3943bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected:
3953bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
3968df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf           bool HasTailCall, bool HasSideEff, InstKind Kind)
397b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
3983bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    HasSideEffects = HasSideEff;
399f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    addSource(CallTarget);
400f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
4013bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
4023bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
4038df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf  bool HasTailCall;
404f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
405f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
406f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Cast instruction (a.k.a. conversion operation).
407b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel {
408c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstCast() = delete;
4097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast(const InstCast &) = delete;
4107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstCast &operator=(const InstCast &) = delete;
4117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
412f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
413f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum OpKind {
414f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
415f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTCAST_TABLE
416f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4174376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
418f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4195bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
420bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf  static const char *getCastName(OpKind Kind);
421bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf
422f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
423f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source) {
42431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstCast>())
425f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstCast(Func, CastKind, Dest, Source);
426f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
427f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  OpKind getCastKind() const { return CastKind; }
428b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
429f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; }
430f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
431f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
432f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
4331bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
434f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const OpKind CastKind;
435f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
436f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
43749889239d4c7ab296c7430722d36032d905110b6Matt Wala// ExtractElement instruction.
438b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel {
439c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstExtractElement() = delete;
4407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement(const InstExtractElement &) = delete;
4417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstExtractElement &operator=(const InstExtractElement &) = delete;
4427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
44349889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
44449889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
44549889239d4c7ab296c7430722d36032d905110b6Matt Wala                                    Operand *Source2) {
44631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstExtractElement>())
44749889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstExtractElement(Func, Dest, Source1, Source2);
44849889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
44949889239d4c7ab296c7430722d36032d905110b6Matt Wala
450b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
45149889239d4c7ab296c7430722d36032d905110b6Matt Wala  static bool classof(const Inst *Inst) {
45249889239d4c7ab296c7430722d36032d905110b6Matt Wala    return Inst->getKind() == ExtractElement;
45349889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
45449889239d4c7ab296c7430722d36032d905110b6Matt Wala
45549889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
45649889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
45749889239d4c7ab296c7430722d36032d905110b6Matt Wala                     Operand *Source2);
45849889239d4c7ab296c7430722d36032d905110b6Matt Wala};
45949889239d4c7ab296c7430722d36032d905110b6Matt Wala
460f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Floating-point comparison instruction.  The source operands are
461f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// captured in getSrc(0) and getSrc(1).
462b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel {
463c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFcmp() = delete;
4647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp(const InstFcmp &) = delete;
4657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFcmp &operator=(const InstFcmp &) = delete;
4667b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
467f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
468f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum FCond {
469f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTFCMP_TABLE
471f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
4724376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
473f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
4745bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
475f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
47731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFcmp>())
478f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstFcmp(Func, Condition, Dest, Source1, Source2);
479f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
480f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  FCond getCondition() const { return Condition; }
481b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
482f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; }
483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
484f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
486f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
4871bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
488f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const FCond Condition;
489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
490f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
491f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Integer comparison instruction.  The source operands are captured
492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// in getSrc(0) and getSrc(1).
493b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel {
494c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIcmp() = delete;
4957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp(const InstIcmp &) = delete;
4967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIcmp &operator=(const InstIcmp &) = delete;
4977b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
498f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
499f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  enum ICond {
500f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag,
501f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    ICEINSTICMP_TABLE
502f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X
5034376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth        _num
504f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  };
5055bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
506f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
507f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                          Operand *Source1, Operand *Source2) {
50831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIcmp>())
509f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstIcmp(Func, Condition, Dest, Source1, Source2);
510f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
511f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  ICond getCondition() const { return Condition; }
512b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
513f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; }
514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
515f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth           Operand *Source2);
5181bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
519f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  const ICond Condition;
520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
521f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
52249889239d4c7ab296c7430722d36032d905110b6Matt Wala// InsertElement instruction.
523b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel {
524c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstInsertElement() = delete;
5257b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement(const InstInsertElement &) = delete;
5267b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstInsertElement &operator=(const InstInsertElement &) = delete;
5277b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
52849889239d4c7ab296c7430722d36032d905110b6Matt Walapublic:
52949889239d4c7ab296c7430722d36032d905110b6Matt Wala  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
53049889239d4c7ab296c7430722d36032d905110b6Matt Wala                                   Operand *Source2, Operand *Source3) {
53131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstInsertElement>())
53249889239d4c7ab296c7430722d36032d905110b6Matt Wala        InstInsertElement(Func, Dest, Source1, Source2, Source3);
53349889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
53449889239d4c7ab296c7430722d36032d905110b6Matt Wala
535b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
53649889239d4c7ab296c7430722d36032d905110b6Matt Wala  static bool classof(const Inst *Inst) {
53749889239d4c7ab296c7430722d36032d905110b6Matt Wala    return Inst->getKind() == InsertElement;
53849889239d4c7ab296c7430722d36032d905110b6Matt Wala  }
53949889239d4c7ab296c7430722d36032d905110b6Matt Wala
54049889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate:
54149889239d4c7ab296c7430722d36032d905110b6Matt Wala  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
54249889239d4c7ab296c7430722d36032d905110b6Matt Wala                    Operand *Source2, Operand *Source3);
54349889239d4c7ab296c7430722d36032d905110b6Matt Wala};
54449889239d4c7ab296c7430722d36032d905110b6Matt Wala
5453bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung// Call to an intrinsic function.  The call target is captured as getSrc(0),
5463bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung// and arg I is captured as getSrc(I+1).
5473bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall {
548c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstIntrinsicCall() = delete;
5497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall(const InstIntrinsicCall &) = delete;
5507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
5517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
5523bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic:
5533bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
5543bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   Operand *CallTarget,
5553bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                                   const Intrinsics::IntrinsicInfo &Info) {
55631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstIntrinsicCall>())
5573bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
5583bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5593bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  static bool classof(const Inst *Inst) {
5603bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung    return Inst->getKind() == IntrinsicCall;
5613bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  }
5623bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5633bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
5643bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
5653bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate:
5663bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
5673bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                    Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
5688df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf      : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
5693bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung                 Inst::IntrinsicCall),
5703bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung        Info(Info) {}
5711bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto
5723bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung  const Intrinsics::IntrinsicInfo Info;
5733bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung};
5743bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung
575f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Load instruction.  The source address is captured in getSrc(0).
576b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel {
577c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstLoad() = delete;
5787b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad(const InstLoad &) = delete;
5797b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstLoad &operator=(const InstLoad &) = delete;
5807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
581f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
58241689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
583c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth                          uint32_t Align = 1) {
58441689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
585c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    (void)Align;
58631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
587f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
588f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getSourceAddress() const { return getSrc(0); }
589b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
590f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Load; }
591f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
592f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
593f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
594f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
595f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
596f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Phi instruction.  For incoming edge I, the node is Labels[I] and
597f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// the Phi source operand is getSrc(I).
598b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel {
599c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstPhi() = delete;
6007b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi(const InstPhi &) = delete;
6017b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstPhi &operator=(const InstPhi &) = delete;
6027b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
603f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
604f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
60531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
606f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
607f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addArgument(Operand *Source, CfgNode *Label);
6085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  Operand *getOperandForTarget(CfgNode *Target) const;
60998712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
6104775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
611d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth                          Liveness *Liveness);
612144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Inst *lower(Cfg *Func);
613b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
614f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
615f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
616f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
617f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
618b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
619f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
620f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
621f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
622f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
623f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // Labels[] duplicates the InEdges[] information in the enclosing
624f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // CfgNode, but the Phi instruction is created before InEdges[]
625f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  // is available, so it's more complicated to share the list.
626f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode **Labels;
627f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
628f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
629f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Ret instruction.  The return value is captured in getSrc(0), but if
630f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// there is no return value (void-type function), then
631f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrcSize()==0 and hasRetValue()==false.
632b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel {
633c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstRet() = delete;
6347b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet(const InstRet &) = delete;
6357b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstRet &operator=(const InstRet &) = delete;
6367b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
637f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
638ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
63931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
640f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
641f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  bool hasRetValue() const { return getSrcSize(); }
642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getRetValue() const {
643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(hasRetValue());
644f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return getSrc(0);
645f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
646b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
647b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; }
649f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
650f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
651f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstRet(Cfg *Func, Operand *RetValue);
652f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Select instruction.  The condition, true, and false operands are captured.
655b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel {
656c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSelect() = delete;
6577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect(const InstSelect &) = delete;
6587b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSelect &operator=(const InstSelect &) = delete;
6597b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
660f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
661f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
662f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            Operand *SourceTrue, Operand *SourceFalse) {
66331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSelect>())
664f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
665f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getCondition() const { return getSrc(0); }
667f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getTrueOperand() const { return getSrc(1); }
668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getFalseOperand() const { return getSrc(2); }
669b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
670f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Select; }
671f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
672f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
674f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth             Operand *Source2);
675f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
676f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Store instruction.  The address operand is captured, along with the
678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// data operand to be stored into the address.
679b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel {
680c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstStore() = delete;
6817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore(const InstStore &) = delete;
6827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstStore &operator=(const InstStore &) = delete;
6837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
684f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
68541689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
686e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth                           uint32_t Align = 1) {
68741689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf    // TODO(kschimpf) Stop ignoring alignment specification.
688e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth    (void)Align;
68931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
690f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
691f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getAddr() const { return getSrc(1); }
692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getData() const { return getSrc(0); }
693e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth  Variable *getRmwBeacon() const { return llvm::dyn_cast<Variable>(getSrc(2)); }
694e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth  void setRmwBeacon(Variable *Beacon);
695b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
696f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Store; }
697f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
698f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
701f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Switch instruction.  The single source operand is captured as
703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0).
704b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel {
705c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstSwitch() = delete;
7067b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch(const InstSwitch &) = delete;
7077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstSwitch &operator=(const InstSwitch &) = delete;
7087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
709f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
710f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
711f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth                            CfgNode *LabelDefault) {
71231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstSwitch>())
713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth        InstSwitch(Func, NumCases, Source, LabelDefault);
714f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  Operand *getComparison() const { return getSrc(0); }
716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabelDefault() const { return LabelDefault; }
717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT getNumCases() const { return NumCases; }
718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t getValue(SizeT I) const {
719f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Values[I];
721f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
722f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *getLabel(SizeT I) const {
723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    assert(I < NumCases);
724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Labels[I];
725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
727b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override;
728336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
729b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
730f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; }
731f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
732f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
734b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void destroy(Cfg *Func) override {
735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<uint64_t>(Values);
736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Func->deallocateArrayOf<CfgNode *>(Labels);
737f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    Inst::destroy(Func);
738f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode *LabelDefault;
741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  SizeT NumCases;   // not including the default case
742f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  uint64_t *Values; // size is NumCases
743f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  CfgNode **Labels; // size is NumCases
744f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
745f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
746f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Unreachable instruction.  This is a terminator instruction with no
747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// operands.
748b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel {
749c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstUnreachable() = delete;
7507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable(const InstUnreachable &) = delete;
7517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstUnreachable &operator=(const InstUnreachable &) = delete;
7527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
753f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic:
754f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static InstUnreachable *create(Cfg *Func) {
75531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
756f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
757b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  NodeList getTerminatorEdges() const override { return NodeList(); }
758b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
759f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  static bool classof(const Inst *Inst) {
760f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth    return Inst->getKind() == Unreachable;
761f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth  }
762f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
763f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate:
764c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  explicit InstUnreachable(Cfg *Func);
765f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth};
766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
7679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth// BundleLock instruction.  There are no operands.  Contains an option
7689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth// indicating whether align_to_end is specified.
7699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel {
770c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleLock() = delete;
7719f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(const InstBundleLock &) = delete;
7729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock &operator=(const InstBundleLock &) = delete;
7739f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
7749f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
7759f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  enum Option { Opt_None, Opt_AlignToEnd };
7769f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleLock *create(Cfg *Func, Option BundleOption) {
7779f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleLock>())
7789f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth        InstBundleLock(Func, BundleOption);
7799f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
7809f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
7819f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
7829f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
7839f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option getOption() const { return BundleOption; }
7849f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static bool classof(const Inst *Inst) {
7859f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return Inst->getKind() == BundleLock;
7869f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
7879f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
7889f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
7899f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  Option BundleOption;
7909f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleLock(Cfg *Func, Option BundleOption);
7919f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
7929f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
7939f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth// BundleUnlock instruction.  There are no operands.
7949f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel {
795c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstBundleUnlock() = delete;
7969f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock(const InstBundleUnlock &) = delete;
7979f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
7989f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
7999f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic:
8009f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static InstBundleUnlock *create(Cfg *Func) {
8019f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
8029f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8039f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emit(const Cfg *Func) const override;
8049f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void emitIAS(const Cfg * /* Func */) const override {}
8059f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  void dump(const Cfg *Func) const override;
8069f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  static bool classof(const Inst *Inst) {
8079f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth    return Inst->getKind() == BundleUnlock;
8089f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  }
8099f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8109f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate:
8119f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth  explicit InstBundleUnlock(Cfg *Func);
8129f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth};
8139f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth
8145bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// FakeDef instruction.  This creates a fake definition of a variable,
8155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// which is how we represent the case when an instruction produces
8165bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// multiple results.  This doesn't happen with high-level ICE
8175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// instructions, but might with lowered instructions.  For example,
8185bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// this would be a way to represent condition flags being modified by
8195bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// an instruction.
8205bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth//
8215bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// It's generally useful to set the optional source operand to be the
8225bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest variable of the instruction that actually produces the FakeDef
8235bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest.  Otherwise, the original instruction could be dead-code
8245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// eliminated if its dest operand is unused, and therefore the FakeDef
8255bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest wouldn't be properly initialized.
826b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel {
827c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeDef() = delete;
8287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef(const InstFakeDef &) = delete;
8297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeDef &operator=(const InstFakeDef &) = delete;
8307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8315bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
832ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  static InstFakeDef *create(Cfg *Func, Variable *Dest,
833ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth                             Variable *Src = nullptr) {
83431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
8355bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
836b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
837198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
838b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8395bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; }
8405bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8415bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
8425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
8435bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8455bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// FakeUse instruction.  This creates a fake use of a variable, to
8465bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// keep the instruction that produces that variable from being
8475bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dead-code eliminated.  This is useful in a variety of lowering
8485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// situations.  The FakeUse instruction has no dest, so it can itself
8495bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// never be dead-code eliminated.
850b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel {
851c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeUse() = delete;
8527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse(const InstFakeUse &) = delete;
8537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeUse &operator=(const InstFakeUse &) = delete;
8547b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
8565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static InstFakeUse *create(Cfg *Func, Variable *Src) {
85731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src);
8585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
859b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
860198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
861b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; }
8635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
8655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstFakeUse(Cfg *Func, Variable *Src);
8665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8675bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
86887ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// FakeKill instruction.  This "kills" a set of variables by modeling
86987ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// a trivial live range at this instruction for each (implicit)
87087ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// variable.  The primary use is to indicate that scratch registers
87187ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// are killed after a call, so that the register allocator won't
87287ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// assign a scratch register to a variable whose live range spans a
87387ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// call.
8745bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth//
8755bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// The FakeKill instruction also holds a pointer to the instruction
8765bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// that kills the set of variables, so that if that linked instruction
8775bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// gets dead-code eliminated, the FakeKill instruction will as well.
878b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel {
879c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstFakeKill() = delete;
8807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill(const InstFakeKill &) = delete;
8817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth  InstFakeKill &operator=(const InstFakeKill &) = delete;
8827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth
8835bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
88487ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
88531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
8865bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
8875bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *getLinked() const { return Linked; }
888b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void emit(const Cfg *Func) const override;
889198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung  void emitIAS(const Cfg * /* Func */) const override {}
890b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
8915bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; }
8925bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8935bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate:
89487ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth  InstFakeKill(Cfg *Func, const Inst *Linked);
8955bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
8965bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  // This instruction is ignored if Linked->isDeleted() is true.
8975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  const Inst *Linked;
8985bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
8995bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// The Target instruction is the base class for all target-specific
9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// instructions.
9025bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst {
903c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  InstTarget() = delete;
9040795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget(const InstTarget &) = delete;
9050795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth  InstTarget &operator=(const InstTarget &) = delete;
906b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth
9075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic:
908b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  uint32_t getEmitInstCount() const override { return 1; }
909b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth  void dump(const Cfg *Func) const override;
9105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; }
9115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
9125bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected:
9135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
9145bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      : Inst(Func, Kind, MaxSrcs, Dest) {
9155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    assert(Kind >= Target);
9165bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
9175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth};
9185bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
919b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
920b3401d27a236b81393092b4d571df473b5bba64bJan Voung
921f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
922f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
923dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm {
924dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
925607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth// Override the default ilist traits so that Inst's private ctor and
926607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth// deleted dtor aren't invoked.
927607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <>
928dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
929607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *createSentinel() const {
930607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth    return static_cast<Ice::Inst *>(&Sentinel);
931607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  }
932607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void destroySentinel(Ice::Inst *) {}
933607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *provideInitialHead() const { return createSentinel(); }
934607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
935607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  static void noteHead(Ice::Inst *, Ice::Inst *) {}
936607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  void deleteNode(Ice::Inst *) {}
937607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
938607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate:
939607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth  mutable ilist_half_node<Ice::Inst> Sentinel;
940607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth};
941607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth
942dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm
943dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth
944f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H
945