IceInst.h revision 87f80c128a9e2bc95829cd1aac2bbc3c44b44ac1
1f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// 2f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 3f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// The Subzero Code Generator 4f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 5f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// This file is distributed under the University of Illinois Open Source 6f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// License. See LICENSE.TXT for details. 7f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 8f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===// 99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file 119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// This file declares the Inst class and its target-independent 129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// subclasses, which represent the high-level Vanilla ICE instructions 139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// and map roughly 1:1 to LLVM instructions. 149612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 15f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===// 16f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 17f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#ifndef SUBZERO_SRC_ICEINST_H 18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define SUBZERO_SRC_ICEINST_H 19f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 207e93c62d7e223b7fd9e6e0889e4b70b635589282John Porto#include "IceCfg.h" 21f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceDefs.h" 22f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.def" 233bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung#include "IceIntrinsics.h" 24f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h" 25f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 26f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be 27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// validated for things like valid operand types, valid branch 28f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// targets, proper ordering of Phi and non-Phi instructions, etc. 29f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// Most of the validity checking will be done in the bitcode reader. 30f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// We need a list of everything that should be validated, and tests 31f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// for each. 32f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 33f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice { 34f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 359612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Base instruction class for ICE. Inst has two subclasses: 369612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InstHighLevel and InstTarget. High-level ICE instructions inherit 379612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// from InstHighLevel, and low-level (target-specific) ICE 389612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions inherit from InstTarget. 39607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> { 40c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth Inst() = delete; 417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst(const Inst &) = delete; 427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst &operator=(const Inst &) = delete; 437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 44f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum InstKind { 46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Arbitrary (alphabetical) order, except put Unreachable first. 47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Unreachable, 48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Alloca, 49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Arithmetic, 50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Br, 51f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Call, 52f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Cast, 5349889239d4c7ab296c7430722d36032d905110b6Matt Wala ExtractElement, 54f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Fcmp, 55f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Icmp, 563bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung IntrinsicCall, 5749889239d4c7ab296c7430722d36032d905110b6Matt Wala InsertElement, 58f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Load, 59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Phi, 60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Ret, 61f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Select, 62f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Store, 635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Switch, 64c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth Assign, // not part of LLVM/PNaCl bitcode 659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth BundleLock, // not part of LLVM/PNaCl bitcode 669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth BundleUnlock, // not part of LLVM/PNaCl bitcode 679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth FakeDef, // not part of LLVM/PNaCl bitcode 689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth FakeUse, // not part of LLVM/PNaCl bitcode 699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth FakeKill, // not part of LLVM/PNaCl bitcode 7087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull JumpTable, // not part of LLVM/PNaCl bitcode 719f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Target // target-specific low-level ICE 729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth // Anything >= Target is an InstTarget subclass. 73b3401d27a236b81393092b4d571df473b5bba64bJan Voung // Note that the value-spaces are shared across targets. 74b3401d27a236b81393092b4d571df473b5bba64bJan Voung // To avoid confusion over the definition of shared values, 75b3401d27a236b81393092b4d571df473b5bba64bJan Voung // an object specific to one target should never be passed 76b3401d27a236b81393092b4d571df473b5bba64bJan Voung // to a different target. 77f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 78f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstKind getKind() const { return Kind; } 79f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 80d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT getNumber() const { return Number; } 81d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void renumber(Cfg *Func); 82e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth enum { 83e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberDeleted = -1, 84e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberSentinel = 0, 85e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberInitial = 2, 86e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberExtended = NumberInitial - 1 87e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth }; 88f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 89f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isDeleted() const { return Deleted; } 90f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void setDeleted() { Deleted = true; } 91a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth void setDead(bool Value = true) { Dead = Value; } 92d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void deleteIfDead(); 93f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasSideEffects() const { return HasSideEffects; } 95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 964775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth bool isDestNonKillable() const { return IsDestNonKillable; } 974775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void setDestNonKillable() { IsDestNonKillable = true; } 984775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth 99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *getDest() const { return Dest; } 100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 101f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getSrcSize() const { return NumSrcs; } 102f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSrc(SizeT I) const { 103f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < getSrcSize()); 104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Srcs[I]; 105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 106f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 107d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth bool isLastUse(const Operand *Src) const; 1088e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); 109d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth 1109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Returns a list of out-edges corresponding to a terminator 1119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// instruction, which is the last instruction of the block. 11287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull /// The list must not contain duplicates. 113f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual NodeList getTerminatorEdges() const { 114f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // All valid terminator instructions override this method. For 115f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // the default implementation, we assert in case some CfgNode 116f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // is constructed without a terminator instruction at the end. 117f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth llvm_unreachable( 118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth "getTerminatorEdges() called on a non-terminator instruction"); 119f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return NodeList(); 120f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 121336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth virtual bool isUnconditionalBranch() const { return false; } 1229612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// If the instruction is a branch-type instruction with OldNode as a 1239612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// target, repoint it to NewNode and return true, otherwise return 12487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull /// false. Repoint all instances of OldNode as a target. 12587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { 126336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)OldNode; 127336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)NewNode; 128336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth return false; 129336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth } 130f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 131ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth virtual bool isSimpleAssign() const { return false; } 132ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth 1334775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessLightweight(Cfg *Func, LivenessBV &Live); 1349612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Calculates liveness for this instruction. Returns true if this 1359612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// instruction is (tentatively) still live and should be retained, 1369612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// and false if this instruction is (tentatively) dead and should be 1379612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// deleted. The decision is tentative until the liveness dataflow 1389612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// algorithm has converged, and then a separate pass permanently 1399612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// deletes dead instructions. 140336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 1414775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 1421873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth 1439612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Get the number of native instructions that this instruction 1449612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// ultimately emits. By default, high-level instructions don't 1459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// result in any native instructions, and a target-specific 1469612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// instruction results in a single native instruction. 1471873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth virtual uint32_t getEmitInstCount() const { return 0; } 148dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // TODO(stichnot): Change Inst back to abstract once the g++ build 149dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ 150dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // because the resize(size_t, Ice::Inst) method is incorrectly 151dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // declared and thus doesn't allow the abstract class Ice::Inst. 152dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // The method should be declared resize(size_t, const Ice::Inst &). 153dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // virtual void emit(const Cfg *Func) const = 0; 154dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth // virtual void emitIAS(const Cfg *Func) const = 0; 155dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emit(const Cfg *) const { 156dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth llvm_unreachable("emit on abstract class"); 157dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth } 158dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emitIAS(const Cfg *Func) const { emit(Func); } 159f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual void dump(const Cfg *Func) const; 160d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth virtual void dumpExtras(const Cfg *Func) const; 161f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDecorated(const Cfg *Func) const; 1625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth void emitSources(const Cfg *Func) const; 163f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpSources(const Cfg *Func) const; 164f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDest(const Cfg *Func) const; 1655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth virtual bool isRedundantAssign() const { return false; } 166f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 1671bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto // TODO(jpp): Insts should not have non-trivial destructors, but they 1681bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto // currently do. This dtor is marked final as a multi-step refactor that 1691bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto // will eventually fix this problem. 170eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth virtual ~Inst() = default; 171f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 172f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected: 173f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); 174f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addSource(Operand *Src) { 175f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(Src); 176f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(NumSrcs < MaxSrcs); 177f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Srcs[NumSrcs++] = Src; 178f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void setLastUse(SizeT VarIndex) { 180d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 181d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 182d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth } 183d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void resetLastUses() { LiveRangesEnded = 0; } 1849612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// The destroy() method lets the instruction cleanly release any 1859612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// memory that was allocated via the Cfg's allocator. 186f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); } 187f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 188f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const InstKind Kind; 1899612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Number is the instruction number for describing live ranges. 190d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT Number; 1919612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Deleted means irrevocably deleted. 192eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Deleted = false; 1939612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Dead means one of two things depending on context: (1) pending 1949612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// deletion after liveness analysis converges, or (2) marked for 1959612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// deletion during lowering due to a folded bool operation. 196eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Dead = false; 1979612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// HasSideEffects means the instruction is something like a function 1989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// call or a volatile load that can't be removed even if its Dest 1999612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// variable is not live. 200eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool HasSideEffects = false; 2019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// IsDestNonKillable means that liveness analysis shouldn't consider 2029612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// this instruction to kill the Dest variable. This is used when 2039612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// lowering produces two assignments to the same variable. 204eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool IsDestNonKillable = false; 205f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 206f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *Dest; 207f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const SizeT MaxSrcs; // only used for assert 208eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth SizeT NumSrcs = 0; 209f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand **Srcs; 210f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 2119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// LiveRangesEnded marks which Variables' live ranges end in this 2129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// instruction. An instruction can have an arbitrary number of 2139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// source operands (e.g. a call instruction), and each source 2149612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// operand can contain 0 or 1 Variable (and target-specific operands 2159612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// could contain more than 1 Variable). All the variables in an 2169612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// instruction are conceptually flattened and each variable is 2179612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// mapped to one bit position of the LiveRangesEnded bit vector. 2189612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Only the first CHAR_BIT * sizeof(LREndedBits) variables are 2199612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// tracked this way. 220d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry 221d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LREndedBits LiveRangesEnded; 222f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 223f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 224b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst { 225c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstHighLevel() = delete; 2260795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel(const InstHighLevel &) = delete; 2270795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel &operator=(const InstHighLevel &) = delete; 228b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 229b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected: 230b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 231b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) {} 232b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg * /*Func*/) const override { 233b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emit() called on a non-lowered instruction"); 234b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 235b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emitIAS(const Cfg * /*Func*/) const override { 236b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emitIAS() called on a non-lowered instruction"); 237b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 238b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth}; 239b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 2409612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), 2419612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// and the required alignment in bytes. The alignment must be either 2429612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 0 (no alignment required) or a power of 2. 243b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel { 244c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAlloca() = delete; 2457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca(const InstAlloca &) = delete; 2467b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca &operator=(const InstAlloca &) = delete; 2477b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 248f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 249f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstAlloca *create(Cfg *Func, Operand *ByteCount, 250f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint32_t AlignInBytes, Variable *Dest) { 25131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAlloca>()) 252f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAlloca(Func, ByteCount, AlignInBytes, Dest); 253f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 254f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint32_t getAlignInBytes() const { return AlignInBytes; } 255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSizeInBytes() const { return getSrc(0); } 256b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 257f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } 258f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 259f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 260f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, 261f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *Dest); 2621bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 263f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const uint32_t AlignInBytes; 264f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 265f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 2669612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Binary arithmetic instruction. The source operands are captured in 2679612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// getSrc(0) and getSrc(1). 268b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel { 269c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstArithmetic() = delete; 2707b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic(const InstArithmetic &) = delete; 2717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic &operator=(const InstArithmetic &) = delete; 2727b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 273f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 275f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag, 276f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTARITHMETIC_TABLE 277f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 2784376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 2805bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, 282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 28331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstArithmetic>()) 284f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Func, Op, Dest, Source1, Source2); 285f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getOp() const { return Op; } 287d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf static const char *getOpName(OpKind Op); 288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isCommutative() const; 289b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 290f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { 291f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Inst->getKind() == Arithmetic; 292f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 293f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 296f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 297f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 298f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind Op; 299f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 3019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Assignment instruction. The source operand is captured in 3029612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// getSrc(0). This is not part of the LLVM bitcode, but is a useful 3039612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// abstraction for some of the lowering. E.g., if Phi instruction 3049612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// lowering happens before target lowering, or for representing an 3059612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Inttoptr instruction, or as an intermediate step for lowering a 3069612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Load instruction. 307b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel { 308c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAssign() = delete; 3097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign(const InstAssign &) = delete; 3107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign &operator=(const InstAssign &) = delete; 3117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 312f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 313f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 31431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 316b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth bool isSimpleAssign() const override { return true; } 317b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 318f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } 319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 323f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 3249612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Branch instruction. This represents both conditional and 3259612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// unconditional branches. 326b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel { 327c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBr() = delete; 3287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr(const InstBr &) = delete; 3297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr &operator=(const InstBr &) = delete; 3307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 331f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 3329612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Create a conditional branch. If TargetTrue==TargetFalse, it is 3339612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// optimized to an unconditional branch. 334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 335f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *TargetFalse) { 33631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) 337f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Func, Source, TargetTrue, TargetFalse); 338f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 3399612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Create an unconditional branch. 340f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, CfgNode *Target) { 34131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) InstBr(Func, Target); 342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 343ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth bool isUnconditional() const { return getTargetTrue() == nullptr; } 344f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { 345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(!isUnconditional()); 346f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 347f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetTrue() const { return TargetTrue; } 349f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetFalse() const { return TargetFalse; } 350f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetUnconditional() const { 351f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(isUnconditional()); 352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getTargetFalse(); 353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 354b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 355336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool isUnconditionalBranch() const override { return isUnconditional(); } 35687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 357b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 358f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } 359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 3619612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Conditional branch 362f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 3639612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Unconditional branch 364f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, CfgNode *Target); 365f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 3669612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetFalse; /// Doubles as unconditional branch target 3679612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetTrue; /// nullptr if unconditional branch 368f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 3709612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Call instruction. The call target is captured as getSrc(0), and 3719612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// arg I is captured as getSrc(I+1). 372b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel { 373c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCall() = delete; 3747b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall(const InstCall &) = delete; 3757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall &operator=(const InstCall &) = delete; 3767b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 377f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 3798df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Operand *CallTarget, bool HasTailCall) { 3809612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Set HasSideEffects to true so that the call instruction can't be 3819612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// dead-code eliminated. IntrinsicCalls can override this if the 3829612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// particular intrinsic is deletable and has no side-effects. 3833bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const bool HasSideEffects = true; 3843bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const InstKind Kind = Inst::Call; 38531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstCall>()) InstCall( 3868df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); 387f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 388f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArg(Operand *Arg) { addSource(Arg); } 389f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCallTarget() const { return getSrc(0); } 390f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getArg(SizeT I) const { return getSrc(I + 1); } 391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumArgs() const { return getSrcSize() - 1; } 3928df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool isTailcall() const { return HasTailCall; } 3933ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung void dump(const Cfg *Func) const override; 394f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } 3958df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Type getReturnType() const; 396f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 3973bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected: 3983bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 3998df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool HasTailCall, bool HasSideEff, InstKind Kind) 400b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) { 4013bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung HasSideEffects = HasSideEff; 402f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth addSource(CallTarget); 403f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 4043bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 4053bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 4068df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool HasTailCall; 407f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 408f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4099612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation). 410b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel { 411c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCast() = delete; 4127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast(const InstCast &) = delete; 4137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast &operator=(const InstCast &) = delete; 4147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 415f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 416f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 417f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 418f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTCAST_TABLE 419f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4204376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 421f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4225bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 423bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf static const char *getCastName(OpKind Kind); 424bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf 425f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 426f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source) { 42731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstCast>()) 428f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Func, CastKind, Dest, Source); 429f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 430f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getCastKind() const { return CastKind; } 431b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 432f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } 433f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 434f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 435f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 4361bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 437f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind CastKind; 438f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 439f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4409612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction. 441b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel { 442c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstExtractElement() = delete; 4437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement(const InstExtractElement &) = delete; 4447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement &operator=(const InstExtractElement &) = delete; 4457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 44649889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 44749889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 44849889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2) { 44931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstExtractElement>()) 45049889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Func, Dest, Source1, Source2); 45149889239d4c7ab296c7430722d36032d905110b6Matt Wala } 45249889239d4c7ab296c7430722d36032d905110b6Matt Wala 453b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 45449889239d4c7ab296c7430722d36032d905110b6Matt Wala static bool classof(const Inst *Inst) { 45549889239d4c7ab296c7430722d36032d905110b6Matt Wala return Inst->getKind() == ExtractElement; 45649889239d4c7ab296c7430722d36032d905110b6Matt Wala } 45749889239d4c7ab296c7430722d36032d905110b6Matt Wala 45849889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 45949889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 46049889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2); 46149889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 46249889239d4c7ab296c7430722d36032d905110b6Matt Wala 4639612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Floating-point comparison instruction. The source operands are 4649612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// captured in getSrc(0) and getSrc(1). 465b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel { 466c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFcmp() = delete; 4677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp(const InstFcmp &) = delete; 4687b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp &operator=(const InstFcmp &) = delete; 4697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 471f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum FCond { 472f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 473f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTFCMP_TABLE 474f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4754376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4775bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 478f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 479f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 48031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFcmp>()) 481f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Func, Condition, Dest, Source1, Source2); 482f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth FCond getCondition() const { return Condition; } 484b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } 486f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 488f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 4901bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 491f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const FCond Condition; 492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 493f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4949612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Integer comparison instruction. The source operands are captured 4959612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// in getSrc(0) and getSrc(1). 496b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel { 497c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIcmp() = delete; 4987b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp(const InstIcmp &) = delete; 4997b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp &operator=(const InstIcmp &) = delete; 5007b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 501f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 502f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum ICond { 503f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 504f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTICMP_TABLE 505f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 5064376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 507f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 5085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 509f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 510f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 51131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIcmp>()) 512f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Func, Condition, Dest, Source1, Source2); 513f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICond getCondition() const { return Condition; } 515b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } 517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 518f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 519f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 5211bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const ICond Condition; 523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 524f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 5259612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction. 526b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel { 527c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstInsertElement() = delete; 5287b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement(const InstInsertElement &) = delete; 5297b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement &operator=(const InstInsertElement &) = delete; 5307b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 53149889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 53249889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 53349889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3) { 53431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstInsertElement>()) 53549889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Func, Dest, Source1, Source2, Source3); 53649889239d4c7ab296c7430722d36032d905110b6Matt Wala } 53749889239d4c7ab296c7430722d36032d905110b6Matt Wala 538b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 53949889239d4c7ab296c7430722d36032d905110b6Matt Wala static bool classof(const Inst *Inst) { 54049889239d4c7ab296c7430722d36032d905110b6Matt Wala return Inst->getKind() == InsertElement; 54149889239d4c7ab296c7430722d36032d905110b6Matt Wala } 54249889239d4c7ab296c7430722d36032d905110b6Matt Wala 54349889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 54449889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 54549889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3); 54649889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 54749889239d4c7ab296c7430722d36032d905110b6Matt Wala 5489612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), 5499612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// and arg I is captured as getSrc(I+1). 5503bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall { 551c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIntrinsicCall() = delete; 5527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall(const InstIntrinsicCall &) = delete; 5537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 5547b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 5553bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic: 5563bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 5573bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, 5583bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo &Info) { 55931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIntrinsicCall>()) 5603bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 5613bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 5623bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung static bool classof(const Inst *Inst) { 5633bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung return Inst->getKind() == IntrinsicCall; 5643bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 5653bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 5663bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 5673bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 5683bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 5693bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 5703bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 5718df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, 5723bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Inst::IntrinsicCall), 5733bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Info(Info) {} 5741bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 5753bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo Info; 5763bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung}; 5773bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 5789612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Load instruction. The source address is captured in getSrc(0). 579b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel { 580c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstLoad() = delete; 5817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad(const InstLoad &) = delete; 5827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad &operator=(const InstLoad &) = delete; 5837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 584f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 58541689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 586c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth uint32_t Align = 1) { 58741689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 588c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth (void)Align; 58931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 590f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 591f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSourceAddress() const { return getSrc(0); } 592b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 593f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } 594f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 595f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 596f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 597f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 598f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 5999612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and 6009612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// the Phi source operand is getSrc(I). 601b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel { 602c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstPhi() = delete; 6037b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi(const InstPhi &) = delete; 6047b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi &operator=(const InstPhi &) = delete; 6057b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 606f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 607f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 60831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 609f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 610f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArgument(Operand *Source, CfgNode *Label); 6115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Operand *getOperandForTarget(CfgNode *Target) const; 61298712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 6134775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 614d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth Liveness *Liveness); 615144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth Inst *lower(Cfg *Func); 616b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 617f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } 618f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 619f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 620f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 621b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 622f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 623f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 624f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 625f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 6269612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Labels[] duplicates the InEdges[] information in the enclosing 6279612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// CfgNode, but the Phi instruction is created before InEdges[] 6289612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// is available, so it's more complicated to share the list. 629f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode **Labels; 630f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 631f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 6329612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if 6339612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// there is no return value (void-type function), then 6349612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// getSrcSize()==0 and hasRetValue()==false. 635b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel { 636c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstRet() = delete; 6377b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet(const InstRet &) = delete; 6387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet &operator=(const InstRet &) = delete; 6397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 640f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 641ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 64231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 644f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasRetValue() const { return getSrcSize(); } 645f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getRetValue() const { 646f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(hasRetValue()); 647f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 649b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 650b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 651f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } 652f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstRet(Cfg *Func, Operand *RetValue); 655f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 6579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction. The condition, true, and false operands are captured. 658b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel { 659c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSelect() = delete; 6607b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect(const InstSelect &) = delete; 6617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect &operator=(const InstSelect &) = delete; 6627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 663f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 664f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 665f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *SourceTrue, Operand *SourceFalse) { 66631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSelect>()) 667f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 669f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { return getSrc(0); } 670f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getTrueOperand() const { return getSrc(1); } 671f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getFalseOperand() const { return getSrc(2); } 672b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } 674f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 675f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 676f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 679f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 6809612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Store instruction. The address operand is captured, along with the 6819612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// data operand to be stored into the address. 682b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel { 683c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstStore() = delete; 6847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore(const InstStore &) = delete; 6857b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore &operator=(const InstStore &) = delete; 6867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 687f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 68841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 689e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth uint32_t Align = 1) { 69041689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 691e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth (void)Align; 69231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 693f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 694f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getAddr() const { return getSrc(1); } 695f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getData() const { return getSrc(0); } 696e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth Variable *getRmwBeacon() const { return llvm::dyn_cast<Variable>(getSrc(2)); } 697e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth void setRmwBeacon(Variable *Beacon); 698b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } 700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 701f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstStore(Cfg *Func, Operand *Data, Operand *Addr); 703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 704f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 7059612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Switch instruction. The single source operand is captured as 7069612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// getSrc(0). 707b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel { 708c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSwitch() = delete; 7097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch(const InstSwitch &) = delete; 7107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch &operator=(const InstSwitch &) = delete; 7117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 712f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 714f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault) { 71531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSwitch>()) 716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Func, NumCases, Source, LabelDefault); 717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getComparison() const { return getSrc(0); } 719f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabelDefault() const { return LabelDefault; } 720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumCases() const { return NumCases; } 721f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint64_t getValue(SizeT I) const { 722f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Values[I]; 724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabel(SizeT I) const { 726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 727f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Labels[I]; 728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 730b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 73187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 732b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; } 734f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); 737b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 738f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<uint64_t>(Values); 739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 742f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 743f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault; 7449612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull SizeT NumCases; /// not including the default case 7459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull uint64_t *Values; /// size is NumCases 7469612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode **Labels; /// size is NumCases 747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 748f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 7499612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Unreachable instruction. This is a terminator instruction with no 7509612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// operands. 751b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel { 752c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstUnreachable() = delete; 7537b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable(const InstUnreachable &) = delete; 7547b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable &operator=(const InstUnreachable &) = delete; 7557b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 756f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 757f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstUnreachable *create(Cfg *Func) { 75831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 759f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 760b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 761b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 762f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static bool classof(const Inst *Inst) { 763f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Inst->getKind() == Unreachable; 764f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 765f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 767c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth explicit InstUnreachable(Cfg *Func); 768f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 769f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 7709612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// BundleLock instruction. There are no operands. Contains an option 7719612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified. 7729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel { 773c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleLock() = delete; 7749f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(const InstBundleLock &) = delete; 7759f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock &operator=(const InstBundleLock &) = delete; 7769f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 7779f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 7789f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth enum Option { Opt_None, Opt_AlignToEnd }; 7799f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleLock *create(Cfg *Func, Option BundleOption) { 7809f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleLock>()) 7819f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Func, BundleOption); 7829f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 7839f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 7849f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 7859f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 7869f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option getOption() const { return BundleOption; } 7879f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static bool classof(const Inst *Inst) { 7889f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return Inst->getKind() == BundleLock; 7899f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 7909f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 7919f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 7929f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option BundleOption; 7939f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Cfg *Func, Option BundleOption); 7949f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 7959f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 7969612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// BundleUnlock instruction. There are no operands. 7979f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel { 798c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleUnlock() = delete; 7999f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock(const InstBundleUnlock &) = delete; 8009f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; 8019f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8029f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 8039f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleUnlock *create(Cfg *Func) { 8049f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); 8059f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8069f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 8079f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 8089f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 8099f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static bool classof(const Inst *Inst) { 8109f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return Inst->getKind() == BundleUnlock; 8119f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8129f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8139f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 8149f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth explicit InstBundleUnlock(Cfg *Func); 8159f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 8169f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8179612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// FakeDef instruction. This creates a fake definition of a variable, 8189612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// which is how we represent the case when an instruction produces 8199612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// multiple results. This doesn't happen with high-level ICE 8209612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions, but might with lowered instructions. For example, 8219612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// this would be a way to represent condition flags being modified by 8229612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// an instruction. 8239612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 8249612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// It's generally useful to set the optional source operand to be the 8259612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// dest variable of the instruction that actually produces the FakeDef 8269612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// dest. Otherwise, the original instruction could be dead-code 8279612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// eliminated if its dest operand is unused, and therefore the FakeDef 8289612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// dest wouldn't be properly initialized. 829b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel { 830c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeDef() = delete; 8317b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef(const InstFakeDef &) = delete; 8327b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef &operator=(const InstFakeDef &) = delete; 8337b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8345bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 835ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstFakeDef *create(Cfg *Func, Variable *Dest, 836ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth Variable *Src = nullptr) { 83731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 8385bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 839b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 840198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 841b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } 8435bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 8455bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 8465bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 8475bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8489612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// FakeUse instruction. This creates a fake use of a variable, to 8499612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// keep the instruction that produces that variable from being 8509612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// dead-code eliminated. This is useful in a variety of lowering 8519612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// situations. The FakeUse instruction has no dest, so it can itself 8529612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// never be dead-code eliminated. 853b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel { 854c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeUse() = delete; 8557b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse(const InstFakeUse &) = delete; 8567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse &operator=(const InstFakeUse &) = delete; 8577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 8595bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static InstFakeUse *create(Cfg *Func, Variable *Src) { 86031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); 8615bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 862b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 863198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 864b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } 8665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8675bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 8685bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstFakeUse(Cfg *Func, Variable *Src); 8695bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 8705bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8719612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling 8729612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// a trivial live range at this instruction for each (implicit) 8739612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// variable. The primary use is to indicate that scratch registers 8749612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// are killed after a call, so that the register allocator won't 8759612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// assign a scratch register to a variable whose live range spans a 8769612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// call. 8779612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 8789612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The FakeKill instruction also holds a pointer to the instruction 8799612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// that kills the set of variables, so that if that linked instruction 8809612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// gets dead-code eliminated, the FakeKill instruction will as well. 881b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel { 882c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeKill() = delete; 8837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill(const InstFakeKill &) = delete; 8847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill &operator=(const InstFakeKill &) = delete; 8857b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8865bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 88787ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 88831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 8895bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 8905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *getLinked() const { return Linked; } 891b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 892198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 893b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8945bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } 8955bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8965bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 89787ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth InstFakeKill(Cfg *Func, const Inst *Linked); 8985bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8999612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// This instruction is ignored if Linked->isDeleted() is true. 9005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *Linked; 9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9025bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 90387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull/// JumpTable instruction. This represents a jump table that will be 90487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull/// stored in the .rodata section. This is used to track and repoint 90587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull/// the target CfgNodes which may change, for example due to 90687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull/// splitting for phi lowering. 90787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel { 90887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable() = delete; 90987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(const InstJumpTable &) = delete; 91087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable &operator=(const InstJumpTable &) = delete; 91187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 91287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic: 91387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 91487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull return new (Func->allocate<InstJumpTable>()) 91587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Func, NumTargets, Default); 91687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 91787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void emit(const Cfg *Func) const override; 91887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void emitIAS(const Cfg *Func) const override; 91987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void addTarget(SizeT TargetIndex, CfgNode *Target) { 92087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull assert(TargetIndex < NumTargets); 92187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Targets[TargetIndex] = Target; 92287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 92387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 92487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull IceString getName(const Cfg *Func) const; 92587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void dump(const Cfg *Func) const override; 92687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull static bool classof(const Inst *Inst) { return Inst->getKind() == JumpTable; } 92787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 92887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate: 92987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); 93087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void destroy(Cfg *Func) override { 93187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Func->deallocateArrayOf<CfgNode *>(Targets); 93287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Inst::destroy(Func); 93387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 93487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 93587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull const SizeT LabelNumber; 93687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull const SizeT NumTargets; 93787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull CfgNode **Targets; 93887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull}; 93987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 9409612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific 9419612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions. 9425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst { 943c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstTarget() = delete; 9440795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget(const InstTarget &) = delete; 9450795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget &operator=(const InstTarget &) = delete; 946b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 9475bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 948b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth uint32_t getEmitInstCount() const override { return 1; } 949b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } 9515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected: 9535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 9545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) { 9555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth assert(Kind >= Target); 9565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 9575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 959b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 960b3401d27a236b81393092b4d571df473b5bba64bJan Voung 961f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice 962f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 963dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm { 964dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 9659612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Override the default ilist traits so that Inst's private ctor and 9669612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// deleted dtor aren't invoked. 967607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <> 968dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 969607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *createSentinel() const { 970607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth return static_cast<Ice::Inst *>(&Sentinel); 971607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth } 972607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void destroySentinel(Ice::Inst *) {} 973607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *provideInitialHead() const { return createSentinel(); } 974607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 975607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void noteHead(Ice::Inst *, Ice::Inst *) {} 976607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth void deleteNode(Ice::Inst *) {} 977607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 978607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate: 979607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth mutable ilist_half_node<Ice::Inst> Sentinel; 980607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth}; 981607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 982dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm 983dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 984f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H 985