IceInst.h revision bf170370805150026104a9e42e07fb17b0971ad7
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> { 387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst(const Inst &) = delete; 397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst &operator=(const Inst &) = delete; 407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 41f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 42f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum InstKind { 43f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Arbitrary (alphabetical) order, except put Unreachable first. 44f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Unreachable, 45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Alloca, 46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Arithmetic, 47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Assign, // not part of LLVM/PNaCl bitcode 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, 625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth FakeDef, // not part of LLVM/PNaCl bitcode 635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth FakeUse, // not part of LLVM/PNaCl bitcode 645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth FakeKill, // not part of LLVM/PNaCl bitcode 655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Target // target-specific low-level ICE 665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth // Anything >= Target is an InstTarget subclass. 67f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 68f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstKind getKind() const { return Kind; } 69f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 70d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT getNumber() const { return Number; } 71d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void renumber(Cfg *Func); 72e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth enum { 73e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberDeleted = -1, 74e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberSentinel = 0, 75e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberInitial = 2, 76e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberExtended = NumberInitial - 1 77e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth }; 78f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 79f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isDeleted() const { return Deleted; } 80f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void setDeleted() { Deleted = true; } 81d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void deleteIfDead(); 82f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 83f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasSideEffects() const { return HasSideEffects; } 84f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 854775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth bool isDestNonKillable() const { return IsDestNonKillable; } 864775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void setDestNonKillable() { IsDestNonKillable = true; } 874775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth 88f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *getDest() const { return Dest; } 89f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 90f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getSrcSize() const { return NumSrcs; } 91f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSrc(SizeT I) const { 92f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < getSrcSize()); 93f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Srcs[I]; 94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 96d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth bool isLastUse(const Operand *Src) const; 97d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth 98f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Returns a list of out-edges corresponding to a terminator 99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // instruction, which is the last instruction of the block. 100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual NodeList getTerminatorEdges() const { 101f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // All valid terminator instructions override this method. For 102f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // the default implementation, we assert in case some CfgNode 103f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // is constructed without a terminator instruction at the end. 104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth llvm_unreachable( 105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth "getTerminatorEdges() called on a non-terminator instruction"); 106f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return NodeList(); 107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 108336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth virtual bool isUnconditionalBranch() const { return false; } 109336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // If the instruction is a branch-type instruction with OldNode as a 110336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // target, repoint it to NewNode and return true, otherwise return 111336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // false. Only repoint one instance, even if the instruction has 112336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // multiple instances of OldNode as a target. 113336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth virtual bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) { 114336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)OldNode; 115336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)NewNode; 116336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth return false; 117336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth } 118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 119ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth virtual bool isSimpleAssign() const { return false; } 120ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth 1214775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessLightweight(Cfg *Func, LivenessBV &Live); 122336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // Calculates liveness for this instruction. Returns true if this 123336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // instruction is (tentatively) still live and should be retained, 124336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // and false if this instruction is (tentatively) dead and should be 125336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // deleted. The decision is tentative until the liveness dataflow 126336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // algorithm has converged, and then a separate pass permanently 127336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth // deletes dead instructions. 128336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 1294775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 1301873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth 1311873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth // Get the number of native instructions that this instruction 1321873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth // ultimately emits. By default, high-level instructions don't 1331873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth // result in any native instructions, and a target-specific 1341873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth // instruction results in a single native instruction. 1351873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth virtual uint32_t getEmitInstCount() const { return 0; } 136dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // TODO(stichnot): Change Inst back to abstract once the g++ build 137dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ 138dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // because the resize(size_t, Ice::Inst) method is incorrectly 139dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // declared and thus doesn't allow the abstract class Ice::Inst. 140dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // The method should be declared resize(size_t, const Ice::Inst &). 141dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // virtual void emit(const Cfg *Func) const = 0; 142dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // virtual void emitIAS(const Cfg *Func) const = 0; 143dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emit(const Cfg *) const { 144dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth llvm_unreachable("emit on abstract class"); 145dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth } 146dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emitIAS(const Cfg *Func) const { emit(Func); } 147f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual void dump(const Cfg *Func) const; 148d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth virtual void dumpExtras(const Cfg *Func) const; 149f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDecorated(const Cfg *Func) const; 1505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth void emitSources(const Cfg *Func) const; 151f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpSources(const Cfg *Func) const; 152f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDest(const Cfg *Func) const; 1535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth virtual bool isRedundantAssign() const { return false; } 154f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 155f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual ~Inst() {} 156f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 157f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected: 158f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); 159f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addSource(Operand *Src) { 160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(Src); 161f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(NumSrcs < MaxSrcs); 162f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Srcs[NumSrcs++] = Src; 163f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 164d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void setLastUse(SizeT VarIndex) { 165d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 166d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 167d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth } 168d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void resetLastUses() { LiveRangesEnded = 0; } 169f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // The destroy() method lets the instruction cleanly release any 170f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // memory that was allocated via the Cfg's allocator. 171f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); } 172f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 173f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const InstKind Kind; 174f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Number is the instruction number for describing live ranges. 175d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT Number; 176f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Deleted means irrevocably deleted. 177f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool Deleted; 178d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // Dead means pending deletion after liveness analysis converges. 179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth bool Dead; 180f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // HasSideEffects means the instruction is something like a function 181f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // call or a volatile load that can't be removed even if its Dest 182f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // variable is not live. 183f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool HasSideEffects; 1844775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth // IsDestNonKillable means that liveness analysis shouldn't consider 1854775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth // this instruction to kill the Dest variable. This is used when 1864775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth // lowering produces two assignments to the same variable. 1874775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth bool IsDestNonKillable; 188f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 189f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *Dest; 190f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const SizeT MaxSrcs; // only used for assert 191f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT NumSrcs; 192f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand **Srcs; 193f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 194d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // LiveRangesEnded marks which Variables' live ranges end in this 195d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // instruction. An instruction can have an arbitrary number of 196d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // source operands (e.g. a call instruction), and each source 197d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // operand can contain 0 or 1 Variable (and target-specific operands 198d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // could contain more than 1 Variable). All the variables in an 199d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // instruction are conceptually flattened and each variable is 200d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // mapped to one bit position of the LiveRangesEnded bit vector. 201d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // Only the first CHAR_BIT * sizeof(LREndedBits) variables are 202d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth // tracked this way. 203d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry 204d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LREndedBits LiveRangesEnded; 205f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 206f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 207b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst { 2080795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel(const InstHighLevel &) = delete; 2090795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel &operator=(const InstHighLevel &) = delete; 210b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 211b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected: 212b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 213b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) {} 214b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg * /*Func*/) const override { 215b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emit() called on a non-lowered instruction"); 216b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 217b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emitIAS(const Cfg * /*Func*/) const override { 218b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emitIAS() called on a non-lowered instruction"); 219b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 220b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstHighLevel() override {} 221b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth}; 222b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 223f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Alloca instruction. This captures the size in bytes as getSrc(0), 224f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// and the required alignment in bytes. The alignment must be either 225f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 0 (no alignment required) or a power of 2. 226b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel { 2277b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca(const InstAlloca &) = delete; 2287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca &operator=(const InstAlloca &) = delete; 2297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 230f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 231f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstAlloca *create(Cfg *Func, Operand *ByteCount, 232f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint32_t AlignInBytes, Variable *Dest) { 233f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstAlloca>()) 234f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAlloca(Func, ByteCount, AlignInBytes, Dest); 235f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 236f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint32_t getAlignInBytes() const { return AlignInBytes; } 237f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSizeInBytes() const { return getSrc(0); } 238b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 239f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } 240f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 241f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 242f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, 243f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *Dest); 244b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstAlloca() override {} 245f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const uint32_t AlignInBytes; 246f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 247f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 248f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Binary arithmetic instruction. The source operands are captured in 249f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0) and getSrc(1). 250b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel { 2517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic(const InstArithmetic &) = delete; 2527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic &operator=(const InstArithmetic &) = delete; 2537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 254f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 256f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag, 257f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTARITHMETIC_TABLE 258f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 2594376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 260f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 2615bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 262f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, 263f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 264f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstArithmetic>()) 265f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Func, Op, Dest, Source1, Source2); 266f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 267f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getOp() const { return Op; } 268d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf static const char *getOpName(OpKind Op); 269f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isCommutative() const; 270b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 271f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { 272f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Inst->getKind() == Arithmetic; 273f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 275f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 276f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 277f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 278b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstArithmetic() override {} 279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 280f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind Op; 281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 283f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Assignment instruction. The source operand is captured in 284f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0). This is not part of the LLVM bitcode, but is a useful 285f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// abstraction for some of the lowering. E.g., if Phi instruction 286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// lowering happens before target lowering, or for representing an 287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Inttoptr instruction, or as an intermediate step for lowering a 288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Load instruction. 289b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel { 2907b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign(const InstAssign &) = delete; 2917b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign &operator=(const InstAssign &) = delete; 2927b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 293f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstAssign>()) 296f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAssign(Func, Dest, Source); 297f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 298b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth bool isSimpleAssign() const override { return true; } 299b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } 301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 302f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 304b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstAssign() override {} 305f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 306f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 307f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Branch instruction. This represents both conditional and 308f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// unconditional branches. 309b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel { 3107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr(const InstBr &) = delete; 3117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr &operator=(const InstBr &) = delete; 3127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 313f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 314f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Create a conditional branch. If TargetTrue==TargetFalse, it is 315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // optimized to an unconditional branch. 316f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 317f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *TargetFalse) { 318f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstBr>()) 319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Func, Source, TargetTrue, TargetFalse); 320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Create an unconditional branch. 322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, CfgNode *Target) { 323f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstBr>()) InstBr(Func, Target); 324f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 325f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isUnconditional() const { return getTargetTrue() == NULL; } 326f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { 327f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(!isUnconditional()); 328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 329f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 330f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetTrue() const { return TargetTrue; } 331f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetFalse() const { return TargetFalse; } 332f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetUnconditional() const { 333f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(isUnconditional()); 334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getTargetFalse(); 335f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 336b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 337336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool isUnconditionalBranch() const override { return isUnconditional(); } 338336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; 339b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 340f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } 341f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 343f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Conditional branch 344f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Unconditional branch 346f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, CfgNode *Target); 347b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstBr() override {} 348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 349336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth CfgNode *TargetFalse; // Doubles as unconditional branch target 350336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth CfgNode *TargetTrue; // NULL if unconditional branch 351f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Call instruction. The call target is captured as getSrc(0), and 354f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// arg I is captured as getSrc(I+1). 355b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel { 3567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall(const InstCall &) = delete; 3577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall &operator=(const InstCall &) = delete; 3587b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 3618df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Operand *CallTarget, bool HasTailCall) { 3623bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung // Set HasSideEffects to true so that the call instruction can't be 3633bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung // dead-code eliminated. IntrinsicCalls can override this if the 3643bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung // particular intrinsic is deletable and has no side-effects. 3653bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const bool HasSideEffects = true; 3663bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const InstKind Kind = Inst::Call; 3678df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf return new (Func->allocateInst<InstCall>()) InstCall( 3688df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); 369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 370f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArg(Operand *Arg) { addSource(Arg); } 371f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCallTarget() const { return getSrc(0); } 372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getArg(SizeT I) const { return getSrc(I + 1); } 373f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumArgs() const { return getSrcSize() - 1; } 3748df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool isTailcall() const { return HasTailCall; } 375b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const; 376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } 3778df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Type getReturnType() const; 378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 3793bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected: 3803bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 3818df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool HasTailCall, bool HasSideEff, InstKind Kind) 382b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) { 3833bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung HasSideEffects = HasSideEff; 384f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth addSource(CallTarget); 385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 386b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstCall() override {} 3873bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 3883bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 3898df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool HasTailCall; 390f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 392f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Cast instruction (a.k.a. conversion operation). 393b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel { 3947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast(const InstCast &) = delete; 3957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast &operator=(const InstCast &) = delete; 3967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 397f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 398f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 399f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 400f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTCAST_TABLE 401f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4024376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 403f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 405bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf static const char *getCastName(OpKind Kind); 406bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf 407f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 408f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source) { 409f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstCast>()) 410f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Func, CastKind, Dest, Source); 411f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 412f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getCastKind() const { return CastKind; } 413b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 414f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } 415f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 416f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 417f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 418b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstCast() override {} 419f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind CastKind; 420f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 421f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 42249889239d4c7ab296c7430722d36032d905110b6Matt Wala// ExtractElement instruction. 423b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel { 4247b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement(const InstExtractElement &) = delete; 4257b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement &operator=(const InstExtractElement &) = delete; 4267b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 42749889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 42849889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 42949889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2) { 43049889239d4c7ab296c7430722d36032d905110b6Matt Wala return new (Func->allocateInst<InstExtractElement>()) 43149889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Func, Dest, Source1, Source2); 43249889239d4c7ab296c7430722d36032d905110b6Matt Wala } 43349889239d4c7ab296c7430722d36032d905110b6Matt Wala 434b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 43549889239d4c7ab296c7430722d36032d905110b6Matt Wala static bool classof(const Inst *Inst) { 43649889239d4c7ab296c7430722d36032d905110b6Matt Wala return Inst->getKind() == ExtractElement; 43749889239d4c7ab296c7430722d36032d905110b6Matt Wala } 43849889239d4c7ab296c7430722d36032d905110b6Matt Wala 43949889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 44049889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 44149889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2); 442b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstExtractElement() override {} 44349889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 44449889239d4c7ab296c7430722d36032d905110b6Matt Wala 445f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Floating-point comparison instruction. The source operands are 446f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// captured in getSrc(0) and getSrc(1). 447b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel { 4487b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp(const InstFcmp &) = delete; 4497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp &operator=(const InstFcmp &) = delete; 4507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 451f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 452f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum FCond { 453f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 454f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTFCMP_TABLE 455f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4564376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 457f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 459f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 460f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 461f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstFcmp>()) 462f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Func, Condition, Dest, Source1, Source2); 463f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 464f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth FCond getCondition() const { return Condition; } 465b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 466f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } 467f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 468f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 469f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 471b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstFcmp() override {} 472f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const FCond Condition; 473f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 474f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 475f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Integer comparison instruction. The source operands are captured 476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// in getSrc(0) and getSrc(1). 477b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel { 4787b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp(const InstIcmp &) = delete; 4797b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp &operator=(const InstIcmp &) = delete; 4807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 481f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 482f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum ICond { 483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 484f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTICMP_TABLE 485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4864376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4885bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 490f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 491f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstIcmp>()) 492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Func, Condition, Dest, Source1, Source2); 493f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 494f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICond getCondition() const { return Condition; } 495b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 496f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } 497f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 498f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 499f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 500f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 501b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstIcmp() override {} 502f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const ICond Condition; 503f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 504f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 50549889239d4c7ab296c7430722d36032d905110b6Matt Wala// InsertElement instruction. 506b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel { 5077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement(const InstInsertElement &) = delete; 5087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement &operator=(const InstInsertElement &) = delete; 5097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 51049889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 51149889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 51249889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3) { 51349889239d4c7ab296c7430722d36032d905110b6Matt Wala return new (Func->allocateInst<InstInsertElement>()) 51449889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Func, Dest, Source1, Source2, Source3); 51549889239d4c7ab296c7430722d36032d905110b6Matt Wala } 51649889239d4c7ab296c7430722d36032d905110b6Matt Wala 517b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 51849889239d4c7ab296c7430722d36032d905110b6Matt Wala static bool classof(const Inst *Inst) { 51949889239d4c7ab296c7430722d36032d905110b6Matt Wala return Inst->getKind() == InsertElement; 52049889239d4c7ab296c7430722d36032d905110b6Matt Wala } 52149889239d4c7ab296c7430722d36032d905110b6Matt Wala 52249889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 52349889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 52449889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3); 525b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstInsertElement() override {} 52649889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 52749889239d4c7ab296c7430722d36032d905110b6Matt Wala 5283bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung// Call to an intrinsic function. The call target is captured as getSrc(0), 5293bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung// and arg I is captured as getSrc(I+1). 5303bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall { 5317b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall(const InstIntrinsicCall &) = delete; 5327b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 5337b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 5343bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic: 5353bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 5363bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, 5373bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo &Info) { 5383bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung return new (Func->allocateInst<InstIntrinsicCall>()) 5393bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 5403bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 5413bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung static bool classof(const Inst *Inst) { 5423bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung return Inst->getKind() == IntrinsicCall; 5433bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 5443bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 5453bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 5463bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 5473bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 5483bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 5493bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 5508df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, 5513bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Inst::IntrinsicCall), 5523bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Info(Info) {} 553b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstIntrinsicCall() override {} 5543bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo Info; 5553bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung}; 5563bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 557f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Load instruction. The source address is captured in getSrc(0). 558b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel { 5597b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad(const InstLoad &) = delete; 5607b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad &operator=(const InstLoad &) = delete; 5617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 562f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 56341689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 564c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth uint32_t Align = 1) { 56541689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 566c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth (void)Align; 567f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstLoad>()) 568f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstLoad(Func, Dest, SourceAddr); 569f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 570f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSourceAddress() const { return getSrc(0); } 571b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 572f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } 573f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 574f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 575f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 576b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstLoad() override {} 577f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 578f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 579f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Phi instruction. For incoming edge I, the node is Labels[I] and 580f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// the Phi source operand is getSrc(I). 581b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel { 5827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi(const InstPhi &) = delete; 5837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi &operator=(const InstPhi &) = delete; 5847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 585f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 586f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 587f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 588f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 589f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArgument(Operand *Source, CfgNode *Label); 5905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Operand *getOperandForTarget(CfgNode *Target) const; 59198712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 5924775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 593d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth Liveness *Liveness); 594144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth Inst *lower(Cfg *Func); 595b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 596f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } 597f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 598f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 599f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 600b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 601f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 602f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 603f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 604b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstPhi() override {} 605f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 606f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Labels[] duplicates the InEdges[] information in the enclosing 607f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // CfgNode, but the Phi instruction is created before InEdges[] 608f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // is available, so it's more complicated to share the list. 609f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode **Labels; 610f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 611f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 612f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Ret instruction. The return value is captured in getSrc(0), but if 613f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// there is no return value (void-type function), then 614f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrcSize()==0 and hasRetValue()==false. 615b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel { 6167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet(const InstRet &) = delete; 6177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet &operator=(const InstRet &) = delete; 6187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 619f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 620f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstRet *create(Cfg *Func, Operand *RetValue = NULL) { 621f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstRet>()) InstRet(Func, RetValue); 622f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 623f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasRetValue() const { return getSrcSize(); } 624f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getRetValue() const { 625f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(hasRetValue()); 626f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 627f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 628b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 629b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 630f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } 631f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 632f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 633f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstRet(Cfg *Func, Operand *RetValue); 634b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstRet() override {} 635f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 636f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 637f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Select instruction. The condition, true, and false operands are captured. 638b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel { 6397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect(const InstSelect &) = delete; 6407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect &operator=(const InstSelect &) = delete; 6417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 644f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *SourceTrue, Operand *SourceFalse) { 645f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstSelect>()) 646f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 647f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { return getSrc(0); } 649f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getTrueOperand() const { return getSrc(1); } 650f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getFalseOperand() const { return getSrc(2); } 651b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 652f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } 653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 655f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 657b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstSelect() override {} 658f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 659f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 660f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Store instruction. The address operand is captured, along with the 661f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// data operand to be stored into the address. 662b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel { 6637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore(const InstStore &) = delete; 6647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore &operator=(const InstStore &) = delete; 6657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 66741689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 66841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf uint32_t align = 1) { 66941689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 67041689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf (void)align; 671f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstStore>()) InstStore(Func, Data, Addr); 672f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getAddr() const { return getSrc(1); } 674f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getData() const { return getSrc(0); } 675b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 676f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } 677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 679f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstStore(Cfg *Func, Operand *Data, Operand *Addr); 680b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstStore() override {} 681f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 683f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Switch instruction. The single source operand is captured as 684f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// getSrc(0). 685b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel { 6867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch(const InstSwitch &) = delete; 6877b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch &operator=(const InstSwitch &) = delete; 6887b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 689f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 690f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 691f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault) { 692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstSwitch>()) 693f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Func, NumCases, Source, LabelDefault); 694f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 695f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getComparison() const { return getSrc(0); } 696f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabelDefault() const { return LabelDefault; } 697f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumCases() const { return NumCases; } 698f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint64_t getValue(SizeT I) const { 699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Values[I]; 701f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabel(SizeT I) const { 703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 704f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Labels[I]; 705f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 707b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 708336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; 709b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 710f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; } 711f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 712f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); 714b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<uint64_t>(Values); 716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 719b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstSwitch() override {} 720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 721f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault; 722f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT NumCases; // not including the default case 723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint64_t *Values; // size is NumCases 724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode **Labels; // size is NumCases 725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 727f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Unreachable instruction. This is a terminator instruction with no 728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// operands. 729b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel { 7307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable(const InstUnreachable &) = delete; 7317b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable &operator=(const InstUnreachable &) = delete; 7327b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 734f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstUnreachable *create(Cfg *Func) { 735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return new (Func->allocateInst<InstUnreachable>()) InstUnreachable(Func); 736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 737b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 738b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { 740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Inst->getKind() == Unreachable; 741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 742f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 743f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 744f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstUnreachable(Cfg *Func); 745b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstUnreachable() override {} 746f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 7485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// FakeDef instruction. This creates a fake definition of a variable, 7495bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// which is how we represent the case when an instruction produces 7505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// multiple results. This doesn't happen with high-level ICE 7515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// instructions, but might with lowered instructions. For example, 7525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// this would be a way to represent condition flags being modified by 7535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// an instruction. 7545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// 7555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// It's generally useful to set the optional source operand to be the 7565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest variable of the instruction that actually produces the FakeDef 7575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest. Otherwise, the original instruction could be dead-code 7585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// eliminated if its dest operand is unused, and therefore the FakeDef 7595bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dest wouldn't be properly initialized. 760b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel { 7617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef(const InstFakeDef &) = delete; 7627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef &operator=(const InstFakeDef &) = delete; 7637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 7645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 7655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) { 7665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth return new (Func->allocateInst<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 7675bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 768b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 769198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 770b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7715bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } 7725bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 7735bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 7745bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 775b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstFakeDef() override {} 7765bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 7775bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 7785bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// FakeUse instruction. This creates a fake use of a variable, to 7795bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// keep the instruction that produces that variable from being 7805bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// dead-code eliminated. This is useful in a variety of lowering 7815bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// situations. The FakeUse instruction has no dest, so it can itself 7825bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// never be dead-code eliminated. 783b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel { 7847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse(const InstFakeUse &) = delete; 7857b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse &operator=(const InstFakeUse &) = delete; 7867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 7875bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 7885bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static InstFakeUse *create(Cfg *Func, Variable *Src) { 7895bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth return new (Func->allocateInst<InstFakeUse>()) InstFakeUse(Func, Src); 7905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 791b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 792198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 793b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7945bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } 7955bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 7965bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 7975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstFakeUse(Cfg *Func, Variable *Src); 798b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstFakeUse() override {} 7995bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 8005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 80187ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// FakeKill instruction. This "kills" a set of variables by modeling 80287ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// a trivial live range at this instruction for each (implicit) 80387ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// variable. The primary use is to indicate that scratch registers 80487ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// are killed after a call, so that the register allocator won't 80587ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// assign a scratch register to a variable whose live range spans a 80687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth// call. 8075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// 8085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// The FakeKill instruction also holds a pointer to the instruction 8095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// that kills the set of variables, so that if that linked instruction 8105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// gets dead-code eliminated, the FakeKill instruction will as well. 811b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel { 8127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill(const InstFakeKill &) = delete; 8137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill &operator=(const InstFakeKill &) = delete; 8147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 81687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 81787ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth return new (Func->allocateInst<InstFakeKill>()) InstFakeKill(Func, Linked); 8185bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 8195bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *getLinked() const { return Linked; } 820b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 821198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 822b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8235bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } 8245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8255bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 82687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth InstFakeKill(Cfg *Func, const Inst *Linked); 827b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstFakeKill() override {} 8285bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8295bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth // This instruction is ignored if Linked->isDeleted() is true. 8305bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *Linked; 8315bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 8325bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8335bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// The Target instruction is the base class for all target-specific 8345bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth// instructions. 8355bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst { 8360795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget(const InstTarget &) = delete; 8370795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget &operator=(const InstTarget &) = delete; 838b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 8395bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 840b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth uint32_t getEmitInstCount() const override { return 1; } 841b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } 8435bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected: 8455bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 8465bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) { 8475bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth assert(Kind >= Target); 8485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 849b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth ~InstTarget() override {} 8505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 8515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 852f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice 853f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 854dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm { 855dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 856607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth// Override the default ilist traits so that Inst's private ctor and 857607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth// deleted dtor aren't invoked. 858607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <> 859dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 860607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *createSentinel() const { 861607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth return static_cast<Ice::Inst *>(&Sentinel); 862607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth } 863607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void destroySentinel(Ice::Inst *) {} 864607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *provideInitialHead() const { return createSentinel(); } 865607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 866607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void noteHead(Ice::Inst *, Ice::Inst *) {} 867607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth void deleteNode(Ice::Inst *) {} 868607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 869607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate: 870607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth mutable ilist_half_node<Ice::Inst> Sentinel; 871607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth}; 872607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 873dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm 874dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 875f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H 876