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