IceInst.h revision 8cfeb69e17190d3bfe22a8a1cbd7679a114d68cf
1f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// 2f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 3f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// The Subzero Code Generator 4f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 5f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// This file is distributed under the University of Illinois Open Source 6f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// License. See LICENSE.TXT for details. 7f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// 8f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===// 99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file 1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the Inst class and its target-independent subclasses. 1292a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// 1392a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// These represent the high-level Vanilla ICE instructions and map roughly 1:1 1492a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// to LLVM instructions. 159612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 16f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===// 17f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#ifndef SUBZERO_SRC_ICEINST_H 19f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define SUBZERO_SRC_ICEINST_H 20f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 217e93c62d7e223b7fd9e6e0889e4b70b635589282John Porto#include "IceCfg.h" 22f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceDefs.h" 23f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.def" 243bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung#include "IceIntrinsics.h" 25f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h" 26f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be 286ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull// validated for things like valid operand types, valid branch targets, proper 2957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// ordering of Phi and non-Phi instructions, etc. Most of the validity checking 3057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// will be done in the bitcode reader. We need a list of everything that should 3157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// be validated, and tests for each. 32f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 33f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice { 34f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 356ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and 366ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and 376ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// low-level (target-specific) ICE instructions inherit from InstTarget. 38607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> { 39c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth Inst() = delete; 407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst(const Inst &) = delete; 417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst &operator=(const Inst &) = delete; 427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 43f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 44f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum InstKind { 45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Arbitrary (alphabetical) order, except put Unreachable first. 46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Unreachable, 47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Alloca, 48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Arithmetic, 49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Br, 50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Call, 51f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Cast, 5249889239d4c7ab296c7430722d36032d905110b6Matt Wala ExtractElement, 53f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Fcmp, 54f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Icmp, 553bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung IntrinsicCall, 5649889239d4c7ab296c7430722d36032d905110b6Matt Wala InsertElement, 57f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Load, 58f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Phi, 59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Ret, 60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Select, 61f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Store, 625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Switch, 63c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth Assign, // not part of LLVM/PNaCl bitcode 649f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth BundleLock, // not part of LLVM/PNaCl bitcode 659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth BundleUnlock, // not part of LLVM/PNaCl bitcode 669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth FakeDef, // not part of LLVM/PNaCl bitcode 679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth FakeUse, // not part of LLVM/PNaCl bitcode 689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth FakeKill, // not part of LLVM/PNaCl bitcode 6987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull JumpTable, // not part of LLVM/PNaCl bitcode 706ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // Anything >= Target is an InstTarget subclass. Note that the value-spaces 716ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // are shared across targets. To avoid confusion over the definition of 726ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // shared values, an object specific to one target should never be passed 736ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // to a different target. 746ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull Target, 756ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull Target_Max = std::numeric_limits<uint8_t>::max(), 76f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 776ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull static_assert(Target <= Target_Max, "Must not be above max."); 78f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstKind getKind() const { return Kind; } 79e37076a176e04eee0f35058ccd2109754c193015Eric Holk virtual IceString getInstName() const; 80f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 81d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT getNumber() const { return Number; } 82d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void renumber(Cfg *Func); 83e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth enum { 84e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberDeleted = -1, 85e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberSentinel = 0, 86e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberInitial = 2, 87e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberExtended = NumberInitial - 1 88e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth }; 89f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 90f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isDeleted() const { return Deleted; } 91f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void setDeleted() { Deleted = true; } 92a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth void setDead(bool Value = true) { Dead = Value; } 93d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void deleteIfDead(); 94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasSideEffects() const { return HasSideEffects; } 96f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 97230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth bool isDestRedefined() const { return IsDestRedefined; } 98230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth void setDestRedefined() { IsDestRedefined = true; } 994775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth 100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *getDest() const { return Dest; } 101f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 102f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getSrcSize() const { return NumSrcs; } 103f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSrc(SizeT I) const { 104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < getSrcSize()); 105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Srcs[I]; 106f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 108d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth bool isLastUse(const Operand *Src) const; 1098e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); 110d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth 1116ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// Returns a list of out-edges corresponding to a terminator instruction, 1126ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// which is the last instruction of the block. The list must not contain 1136ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// duplicates. 114f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual NodeList getTerminatorEdges() const { 1156ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // All valid terminator instructions override this method. For the default 1166ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // implementation, we assert in case some CfgNode is constructed without a 1176ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // terminator instruction at the end. 118f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth llvm_unreachable( 119f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth "getTerminatorEdges() called on a non-terminator instruction"); 120f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return NodeList(); 121f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 122336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth virtual bool isUnconditionalBranch() const { return false; } 12357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// If the instruction is a branch-type instruction with OldNode as a target, 12457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// repoint it to NewNode and return true, otherwise return false. Repoint all 12557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instances of OldNode as a target. 12687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { 127336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)OldNode; 128336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)NewNode; 129336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth return false; 130336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth } 131f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 13228b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth /// Returns true if the instruction is equivalent to a simple 13328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth /// "var_dest=var_src" assignment where the dest and src are both variables. 13428b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth virtual bool isVarAssign() const { return false; } 135ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth 1364775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessLightweight(Cfg *Func, LivenessBV &Live); 13757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Calculates liveness for this instruction. Returns true if this instruction 13857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// is (tentatively) still live and should be retained, and false if this 13957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction is (tentatively) dead and should be deleted. The decision is 14057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// tentative until the liveness dataflow algorithm has converged, and then a 14157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// separate pass permanently deletes dead instructions. 142336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 1434775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 1441873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth 1456ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// Get the number of native instructions that this instruction ultimately 1466ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// emits. By default, high-level instructions don't result in any native 1476ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// instructions, and a target-specific instruction results in a single native 1486ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// instruction. 1491873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth virtual uint32_t getEmitInstCount() const { return 0; } 15057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // TODO(stichnot): Change Inst back to abstract once the g++ build issue is 15157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the 15257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't 15357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // allow the abstract class Ice::Inst. The method should be declared 15457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func) 15557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // const = 0; virtual void emitIAS(const Cfg *Func) const = 0; 156dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emit(const Cfg *) const { 157dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth llvm_unreachable("emit on abstract class"); 158dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth } 159dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emitIAS(const Cfg *Func) const { emit(Func); } 160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual void dump(const Cfg *Func) const; 161d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth virtual void dumpExtras(const Cfg *Func) const; 162f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDecorated(const Cfg *Func) const; 1635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth void emitSources(const Cfg *Func) const; 164f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpSources(const Cfg *Func) const; 165f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDest(const Cfg *Func) const; 1665bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth virtual bool isRedundantAssign() const { return false; } 167f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 16800741a005cf242d2e9108f7cc7c454246e13741cAndrew Scull ~Inst() = default; 169f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 170f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected: 171f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); 172f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addSource(Operand *Src) { 173f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(Src); 174f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(NumSrcs < MaxSrcs); 175f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Srcs[NumSrcs++] = Src; 176f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 177d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void setLastUse(SizeT VarIndex) { 178d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 180d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth } 181d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void resetLastUses() { LiveRangesEnded = 0; } 18257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// The destroy() method lets the instruction cleanly release any memory that 18357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// was allocated via the Cfg's allocator. 184f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); } 185f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 186f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const InstKind Kind; 1879612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Number is the instruction number for describing live ranges. 188d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT Number; 1899612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Deleted means irrevocably deleted. 190eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Deleted = false; 19157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Dead means one of two things depending on context: (1) pending deletion 19257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// after liveness analysis converges, or (2) marked for deletion during 19357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// lowering due to a folded bool operation. 194eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Dead = false; 19557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// HasSideEffects means the instruction is something like a function call or 19657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// a volatile load that can't be removed even if its Dest variable is not 19757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// live. 198eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool HasSideEffects = false; 199230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// IsDestRedefined indicates that this instruction is not the first 200230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// definition of Dest in the basic block. The effect is that liveness 201230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// analysis shouldn't consider this instruction to be the start of Dest's 202230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// live range; rather, there is some other instruction earlier in the basic 203230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// block with the same Dest. This is maintained because liveness analysis 204230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// has an invariant (primarily for performance reasons) that any Variable's 205230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// live range recorded in a basic block has at most one start and at most one 206230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// end. 207230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth bool IsDestRedefined = false; 208f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 209f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *Dest; 210f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const SizeT MaxSrcs; // only used for assert 211eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth SizeT NumSrcs = 0; 212f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand **Srcs; 213f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 2149612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// LiveRangesEnded marks which Variables' live ranges end in this 21557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction. An instruction can have an arbitrary number of source 21657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// operands (e.g. a call instruction), and each source operand can contain 0 21757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// or 1 Variable (and target-specific operands could contain more than 1 21857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Variable). All the variables in an instruction are conceptually flattened 21957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// and each variable is mapped to one bit position of the LiveRangesEnded bit 22057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are 2219612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// tracked this way. 2228072bae156fa62e51e02925997992c4908a2682fAndrew Scull using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry 223d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LREndedBits LiveRangesEnded; 224f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 225f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 226b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst { 227c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstHighLevel() = delete; 2280795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel(const InstHighLevel &) = delete; 2290795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel &operator=(const InstHighLevel &) = delete; 230b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 231b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected: 232b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 233b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) {} 234b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg * /*Func*/) const override { 235b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emit() called on a non-lowered instruction"); 236b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 237b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emitIAS(const Cfg * /*Func*/) const override { 238b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emitIAS() called on a non-lowered instruction"); 239b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 240b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth}; 241b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 24257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the 24357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment 24457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2. 245b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel { 246c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAlloca() = delete; 2477b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca(const InstAlloca &) = delete; 2487b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca &operator=(const InstAlloca &) = delete; 2497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 250f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 2512f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, 2522f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr uint32_t AlignInBytes) { 25331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAlloca>()) 2542f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr InstAlloca(Func, Dest, ByteCount, AlignInBytes); 255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 256f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint32_t getAlignInBytes() const { return AlignInBytes; } 257f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSizeInBytes() const { return getSrc(0); } 25855f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth bool getKnownFrameOffset() const { return KnownFrameOffset; } 25955f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth void setKnownFrameOffset() { KnownFrameOffset = true; } 260b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 2618cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } 262f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 263f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 2642f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, 2652f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr uint32_t AlignInBytes); 2661bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 267f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const uint32_t AlignInBytes; 26855f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth bool KnownFrameOffset = false; 269f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 270f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 27157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0) 27257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1). 273b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel { 274c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstArithmetic() = delete; 2757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic(const InstArithmetic &) = delete; 2767b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic &operator=(const InstArithmetic &) = delete; 2777b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 278f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 280f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag, 281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTARITHMETIC_TABLE 282f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 2834376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 284f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 2855bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, 287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 28831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstArithmetic>()) 289f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Func, Op, Dest, Source1, Source2); 290f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 291f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getOp() const { return Op; } 292e37076a176e04eee0f35058ccd2109754c193015Eric Holk 293e37076a176e04eee0f35058ccd2109754c193015Eric Holk virtual IceString getInstName() const override; 294e37076a176e04eee0f35058ccd2109754c193015Eric Holk 295d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf static const char *getOpName(OpKind Op); 296f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isCommutative() const; 297b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 2988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 2998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == Arithmetic; 300f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 302f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 304f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 305f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 306f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind Op; 307f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 308f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 30957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is 31057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the 31157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering, 31257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for 31357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction. 314b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel { 315c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAssign() = delete; 3167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign(const InstAssign &) = delete; 3177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign &operator=(const InstAssign &) = delete; 3187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 320f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 32131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 32328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth bool isVarAssign() const override; 324b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 3258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } 326f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 327f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 329f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 330f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 33157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional 33257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches. 333b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel { 334c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBr() = delete; 3357b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr(const InstBr &) = delete; 3367b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr &operator=(const InstBr &) = delete; 3377b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 338f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 33957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized 34057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// to an unconditional branch. 341f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 342f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *TargetFalse) { 34331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) 344f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Func, Source, TargetTrue, TargetFalse); 345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 3469612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Create an unconditional branch. 347f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, CfgNode *Target) { 34831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) InstBr(Func, Target); 349f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 350ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth bool isUnconditional() const { return getTargetTrue() == nullptr; } 351f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { 352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(!isUnconditional()); 353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 354f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 355f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetTrue() const { return TargetTrue; } 356f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetFalse() const { return TargetFalse; } 357f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetUnconditional() const { 358f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(isUnconditional()); 359f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getTargetFalse(); 360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 361b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 362336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool isUnconditionalBranch() const override { return isUnconditional(); } 36387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 364b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 3658cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } 366f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 367f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 3689612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Conditional branch 369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 3709612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Unconditional branch 371f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, CfgNode *Target); 372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 3739612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetFalse; /// Doubles as unconditional branch target 3749612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetTrue; /// nullptr if unconditional branch 375f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 37757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is 37857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1). 379b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel { 380c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCall() = delete; 3817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall(const InstCall &) = delete; 3827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall &operator=(const InstCall &) = delete; 3837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 384f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 3865e0a8a71b75ec56981883587612b16f7c1635a03John Porto Operand *CallTarget, bool HasTailCall, 3875e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool IsTargetHelperCall = false) { 3889612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Set HasSideEffects to true so that the call instruction can't be 38957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// dead-code eliminated. IntrinsicCalls can override this if the particular 39057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// intrinsic is deletable and has no side-effects. 3915bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth constexpr bool HasSideEffects = true; 3925bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth constexpr InstKind Kind = Inst::Call; 3935e0a8a71b75ec56981883587612b16f7c1635a03John Porto return new (Func->allocate<InstCall>()) 3945e0a8a71b75ec56981883587612b16f7c1635a03John Porto InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, 3955e0a8a71b75ec56981883587612b16f7c1635a03John Porto IsTargetHelperCall, HasSideEffects, Kind); 396f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 397f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArg(Operand *Arg) { addSource(Arg); } 398f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCallTarget() const { return getSrc(0); } 399f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getArg(SizeT I) const { return getSrc(I + 1); } 400f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumArgs() const { return getSrcSize() - 1; } 4018df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool isTailcall() const { return HasTailCall; } 4025e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool isTargetHelperCall() const { return IsTargetHelperCall; } 4033ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung void dump(const Cfg *Func) const override; 4048cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } 4058df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Type getReturnType() const; 406f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4073bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected: 4083bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 4095e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff, 4105e0a8a71b75ec56981883587612b16f7c1635a03John Porto InstKind Kind) 4115e0a8a71b75ec56981883587612b16f7c1635a03John Porto : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), 4125e0a8a71b75ec56981883587612b16f7c1635a03John Porto IsTargetHelperCall(IsTargetHelperCall) { 4133bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung HasSideEffects = HasSideEff; 414f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth addSource(CallTarget); 415f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 4163bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 4173bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 4185e0a8a71b75ec56981883587612b16f7c1635a03John Porto const bool HasTailCall; 4195e0a8a71b75ec56981883587612b16f7c1635a03John Porto const bool IsTargetHelperCall; 420f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 421f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4229612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation). 423b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel { 424c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCast() = delete; 4257b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast(const InstCast &) = delete; 4267b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast &operator=(const InstCast &) = delete; 4277b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 428f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 429f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 430f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 431f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTCAST_TABLE 432f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4334376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 434f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4355bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 436bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf static const char *getCastName(OpKind Kind); 437bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf 438f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 439f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source) { 44031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstCast>()) 441f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Func, CastKind, Dest, Source); 442f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 443f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getCastKind() const { return CastKind; } 444b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 4458cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } 446f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 447f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 448f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 4491bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 450f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind CastKind; 451f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 452f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4539612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction. 454b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel { 455c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstExtractElement() = delete; 4567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement(const InstExtractElement &) = delete; 4577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement &operator=(const InstExtractElement &) = delete; 4587b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 45949889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 46049889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 46149889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2) { 46231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstExtractElement>()) 46349889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Func, Dest, Source1, Source2); 46449889239d4c7ab296c7430722d36032d905110b6Matt Wala } 46549889239d4c7ab296c7430722d36032d905110b6Matt Wala 466b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 4678cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 4688cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == ExtractElement; 46949889239d4c7ab296c7430722d36032d905110b6Matt Wala } 47049889239d4c7ab296c7430722d36032d905110b6Matt Wala 47149889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 47249889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 47349889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2); 47449889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 47549889239d4c7ab296c7430722d36032d905110b6Matt Wala 47657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in 47757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1). 478b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel { 479c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFcmp() = delete; 4807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp(const InstFcmp &) = delete; 4817b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp &operator=(const InstFcmp &) = delete; 4827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 484f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum FCond { 485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 486f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTFCMP_TABLE 487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4884376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 491f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 49331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFcmp>()) 494f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Func, Condition, Dest, Source1, Source2); 495f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 496f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth FCond getCondition() const { return Condition; } 497b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 4988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } 499f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 500f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 501f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 502f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 5031bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 504f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const FCond Condition; 505f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 506f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 50757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in 50857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1). 509b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel { 510c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIcmp() = delete; 5117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp(const InstIcmp &) = delete; 5127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp &operator=(const InstIcmp &) = delete; 5137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 515f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum ICond { 516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTICMP_TABLE 518f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 5194376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 5215bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 52431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIcmp>()) 525f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Func, Condition, Dest, Source1, Source2); 526f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 527f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICond getCondition() const { return Condition; } 528b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5298cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } 530f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 531f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 533f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 5341bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 535f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const ICond Condition; 536f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 537f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 5389612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction. 539b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel { 540c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstInsertElement() = delete; 5417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement(const InstInsertElement &) = delete; 5427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement &operator=(const InstInsertElement &) = delete; 5437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 54449889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 54549889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 54649889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3) { 54731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstInsertElement>()) 54849889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Func, Dest, Source1, Source2, Source3); 54949889239d4c7ab296c7430722d36032d905110b6Matt Wala } 55049889239d4c7ab296c7430722d36032d905110b6Matt Wala 551b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 5538cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == InsertElement; 55449889239d4c7ab296c7430722d36032d905110b6Matt Wala } 55549889239d4c7ab296c7430722d36032d905110b6Matt Wala 55649889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 55749889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 55849889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3); 55949889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 56049889239d4c7ab296c7430722d36032d905110b6Matt Wala 56157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and 56257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1). 5633bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall { 564c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIntrinsicCall() = delete; 5657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall(const InstIntrinsicCall &) = delete; 5667b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 5677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 5683bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic: 5693bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 5703bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, 5713bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo &Info) { 57231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIntrinsicCall>()) 5733bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 5743bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 5758cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 5768cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == IntrinsicCall; 5773bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 5783bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 5793bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 5803bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 5813bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 5823bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 5833bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 5845e0a8a71b75ec56981883587612b16f7c1635a03John Porto : InstCall(Func, NumArgs, Dest, CallTarget, false, false, 5855e0a8a71b75ec56981883587612b16f7c1635a03John Porto Info.HasSideEffects, Inst::IntrinsicCall), 5863bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Info(Info) {} 5871bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 5883bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo Info; 5893bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung}; 5903bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 59157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0). 592b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel { 593c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstLoad() = delete; 5947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad(const InstLoad &) = delete; 5957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad &operator=(const InstLoad &) = delete; 5967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 597f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 59841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 599c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth uint32_t Align = 1) { 60041689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 601c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth (void)Align; 60231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 603f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 604f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSourceAddress() const { return getSrc(0); } 605b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } 607f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 608f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 609f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 610f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 611f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 61257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi 61357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I). 614b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel { 615c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstPhi() = delete; 6167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi(const InstPhi &) = delete; 6177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi &operator=(const InstPhi &) = delete; 6187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 619f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 620f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 62131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 622f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 623f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArgument(Operand *Source, CfgNode *Label); 6245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Operand *getOperandForTarget(CfgNode *Target) const; 62598712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 6264775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 627d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth Liveness *Liveness); 628144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth Inst *lower(Cfg *Func); 629b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6308cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } 631f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 632f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 633f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 634b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 635f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 636f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 637f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 638f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 63957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, 64057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// but the Phi instruction is created before InEdges[] is available, so it's 64157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// more complicated to share the list. 642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode **Labels; 643f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 644f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 64557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is 64657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and 64757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false. 648b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel { 649c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstRet() = delete; 6507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet(const InstRet &) = delete; 6517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet &operator=(const InstRet &) = delete; 6527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 654ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 65531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 657f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasRetValue() const { return getSrcSize(); } 658f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getRetValue() const { 659f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(hasRetValue()); 660f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 661f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 662b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 663b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6648cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } 665f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 667f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstRet(Cfg *Func, Operand *RetValue); 668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 669f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 6709612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction. The condition, true, and false operands are captured. 671b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel { 672c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSelect() = delete; 6737b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect(const InstSelect &) = delete; 6747b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect &operator=(const InstSelect &) = delete; 6757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 676f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 678f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *SourceTrue, Operand *SourceFalse) { 67931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSelect>()) 680f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 681f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { return getSrc(0); } 683f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getTrueOperand() const { return getSrc(1); } 684f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getFalseOperand() const { return getSrc(2); } 685b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6868cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } 687f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 688f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 689f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 690f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 691f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 69357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data 69457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address. 695b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel { 696c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstStore() = delete; 6977b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore(const InstStore &) = delete; 6987b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore &operator=(const InstStore &) = delete; 6997b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 70141689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 702e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth uint32_t Align = 1) { 70341689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 704e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth (void)Align; 70531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 707f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getAddr() const { return getSrc(1); } 708f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getData() const { return getSrc(0); } 709aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull Variable *getRmwBeacon() const; 710e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth void setRmwBeacon(Variable *Beacon); 711b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7128cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } 713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 714f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstStore(Cfg *Func, Operand *Data, Operand *Addr); 716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 71857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0). 719b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel { 720c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSwitch() = delete; 7217b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch(const InstSwitch &) = delete; 7227b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch &operator=(const InstSwitch &) = delete; 7237b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 726f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault) { 72731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSwitch>()) 728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Func, NumCases, Source, LabelDefault); 729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 730f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getComparison() const { return getSrc(0); } 731f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabelDefault() const { return LabelDefault; } 732f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumCases() const { return NumCases; } 733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint64_t getValue(SizeT I) const { 734f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Values[I]; 736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 737f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabel(SizeT I) const { 738f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Labels[I]; 740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 742b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 74387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 744b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7458cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } 746f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 748f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); 749b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 750f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<uint64_t>(Values); 751f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 752f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 753f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 754f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault; 7569612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull SizeT NumCases; /// not including the default case 7579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull uint64_t *Values; /// size is NumCases 7589612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode **Labels; /// size is NumCases 759f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 760f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 76157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands. 762b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel { 763c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstUnreachable() = delete; 7647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable(const InstUnreachable &) = delete; 7657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable &operator=(const InstUnreachable &) = delete; 7667b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 767f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 768f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstUnreachable *create(Cfg *Func) { 76931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 770f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 771b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 772b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7738cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 7748cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == Unreachable; 775f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 776f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 777f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 778c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth explicit InstUnreachable(Cfg *Func); 779f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 780f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 78157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction. There are no operands. Contains an option 7829612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified. 7839f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel { 784c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleLock() = delete; 7859f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(const InstBundleLock &) = delete; 7869f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock &operator=(const InstBundleLock &) = delete; 7879f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 7889f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 78956958cb33d3c1d045f2844408d825442d523f59fJohn Porto enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; 7909f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleLock *create(Cfg *Func, Option BundleOption) { 7919f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleLock>()) 7929f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Func, BundleOption); 7939f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 7949f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 7959f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 7969f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 7979f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option getOption() const { return BundleOption; } 7988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 7998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == BundleLock; 8009f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8019f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8029f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 8039f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option BundleOption; 8049f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Cfg *Func, Option BundleOption); 8059f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 8069f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 80757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands. 8089f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel { 809c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleUnlock() = delete; 8109f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock(const InstBundleUnlock &) = delete; 8119f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; 8129f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8139f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 8149f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleUnlock *create(Cfg *Func) { 8159f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); 8169f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8179f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 8189f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 8199f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 8208cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 8218cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == BundleUnlock; 8229f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8239f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8249f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 8259f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth explicit InstBundleUnlock(Cfg *Func); 8269f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 8279f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 82857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is 82957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results. 83057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered 83157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags 83257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction. 8339612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 83457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest 83557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest. 83657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its 83757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly 83857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized. 839b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel { 840c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeDef() = delete; 8417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef(const InstFakeDef &) = delete; 8427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef &operator=(const InstFakeDef &) = delete; 8437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8445bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 845ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstFakeDef *create(Cfg *Func, Variable *Dest, 846ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth Variable *Src = nullptr) { 84731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 8485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 849b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 850198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 851b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } 8535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8545bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 8555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 8565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 8575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 85857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the 85957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated. 86057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction 8618ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// has no dest, so it can itself never be dead-code eliminated. A weight can 8628ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// be provided to provide extra bias to the register allocator - for simplicity 8638ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// of implementation, weight=N is handled by holding N copies of the variable 8648ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// as source operands. 865b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel { 866c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeUse() = delete; 8677b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse(const InstFakeUse &) = delete; 8687b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse &operator=(const InstFakeUse &) = delete; 8697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8705bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 8718ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { 8728ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); 8735bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 874b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 875198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 876b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8778cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } 8785bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 8795bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 8808ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); 8815bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 8825bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 88357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial 88457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use 88557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the 88657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live 88757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call. 8889612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 88957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills 89057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code 89157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well. 892b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel { 893c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeKill() = delete; 8947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill(const InstFakeKill &) = delete; 8957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill &operator=(const InstFakeKill &) = delete; 8967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 89887ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 89931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 9005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *getLinked() const { return Linked; } 902b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 903198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 904b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9058cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 9068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == FakeKill; 9078cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth } 9085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 91087ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth InstFakeKill(Cfg *Func, const Inst *Linked); 9115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// This instruction is ignored if Linked->isDeleted() is true. 9135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *Linked; 9145bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 91657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in 91757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes 91857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering. 91987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel { 92087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable() = delete; 92187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(const InstJumpTable &) = delete; 92287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable &operator=(const InstJumpTable &) = delete; 92387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 92487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic: 92587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 92687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull return new (Func->allocate<InstJumpTable>()) 92787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Func, NumTargets, Default); 92887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 92987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void addTarget(SizeT TargetIndex, CfgNode *Target) { 93087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull assert(TargetIndex < NumTargets); 93187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Targets[TargetIndex] = Target; 93287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 93387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 93486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull SizeT getId() const { return Id; } 93586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull SizeT getNumTargets() const { return NumTargets; } 93686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull CfgNode *getTarget(SizeT I) const { 93786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull assert(I < NumTargets); 93886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull return Targets[I]; 93986df4e9e6d183f07638440afd2c225b485c03917Andrew Scull } 94087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void dump(const Cfg *Func) const override; 9418cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 9428cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == JumpTable; 9438cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth } 94487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 94586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull static IceString makeName(const IceString &FuncName, SizeT Id) { 94686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull return ".L" + FuncName + "$jumptable$__" + std::to_string(Id); 94786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull } 94886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull 94987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate: 95087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); 95187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void destroy(Cfg *Func) override { 95287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Func->deallocateArrayOf<CfgNode *>(Targets); 95387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Inst::destroy(Func); 95487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 95587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 95686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull const SizeT Id; 95787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull const SizeT NumTargets; 95887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull CfgNode **Targets; 95987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull}; 96087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 9619612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific 9629612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions. 9635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst { 964c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstTarget() = delete; 9650795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget(const InstTarget &) = delete; 9660795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget &operator=(const InstTarget &) = delete; 967b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 9685bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 969b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth uint32_t getEmitInstCount() const override { return 1; } 970b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9718cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } 9725bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9735bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected: 9745bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 9755bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) { 9765bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth assert(Kind >= Target); 9776ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull assert(Kind <= Target_Max); 9785bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 9795bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9805bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 981b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 982b3401d27a236b81393092b4d571df473b5bba64bJan Voung 983f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice 984f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 985dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm { 986dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 98757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted 98857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked. 989607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <> 990dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 991607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *createSentinel() const { 992607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth return static_cast<Ice::Inst *>(&Sentinel); 993607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth } 994607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void destroySentinel(Ice::Inst *) {} 995607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *provideInitialHead() const { return createSentinel(); } 996607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 997607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void noteHead(Ice::Inst *, Ice::Inst *) {} 998607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth void deleteNode(Ice::Inst *) {} 999607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 1000607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate: 1001607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth mutable ilist_half_node<Ice::Inst> Sentinel; 1002607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth}; 1003607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 1004dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm 1005dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 1006f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H 1007