IceInst.h revision 1448d95c891c926f480e4b898c6cb5716983e582
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" 25a47c11c7f17022050043d69c0802241e0747a056John Porto#include "IceOperand.h" 26030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto#include "IceSwitchLowering.h" 27f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceTypes.h" 28f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 29f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// TODO: The Cfg structure, and instructions in particular, need to be 306ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull// validated for things like valid operand types, valid branch targets, proper 3157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// ordering of Phi and non-Phi instructions, etc. Most of the validity checking 3257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// will be done in the bitcode reader. We need a list of everything that should 3357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// be validated, and tests for each. 34f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 35f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice { 36f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 376ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and 386ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and 396ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull/// low-level (target-specific) ICE instructions inherit from InstTarget. 40607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothclass Inst : public llvm::ilist_node<Inst> { 41c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth Inst() = delete; 427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst(const Inst &) = delete; 437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth Inst &operator=(const Inst &) = delete; 447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 45f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 46f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum InstKind { 47f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth // Arbitrary (alphabetical) order, except put Unreachable first. 48f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Unreachable, 49f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Alloca, 50f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Arithmetic, 51f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Br, 52f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Call, 53f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Cast, 5449889239d4c7ab296c7430722d36032d905110b6Matt Wala ExtractElement, 55f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Fcmp, 56f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Icmp, 573bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung IntrinsicCall, 5849889239d4c7ab296c7430722d36032d905110b6Matt Wala InsertElement, 59f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Load, 60f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Phi, 61f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Ret, 62f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Select, 63f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Store, 645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Switch, 65a47c11c7f17022050043d69c0802241e0747a056John Porto Assign, // not part of LLVM/PNaCl bitcode 66a47c11c7f17022050043d69c0802241e0747a056John Porto Breakpoint, // not part of LLVM/PNaCl bitcode 67a47c11c7f17022050043d69c0802241e0747a056John Porto BundleLock, // not part of LLVM/PNaCl bitcode 68a47c11c7f17022050043d69c0802241e0747a056John Porto BundleUnlock, // not part of LLVM/PNaCl bitcode 69a47c11c7f17022050043d69c0802241e0747a056John Porto FakeDef, // not part of LLVM/PNaCl bitcode 70a47c11c7f17022050043d69c0802241e0747a056John Porto FakeUse, // not part of LLVM/PNaCl bitcode 71a47c11c7f17022050043d69c0802241e0747a056John Porto FakeKill, // not part of LLVM/PNaCl bitcode 72a47c11c7f17022050043d69c0802241e0747a056John Porto JumpTable, // not part of LLVM/PNaCl bitcode 73a47c11c7f17022050043d69c0802241e0747a056John Porto ShuffleVector, // not part of LLVM/PNaCl bitcode 746ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // Anything >= Target is an InstTarget subclass. Note that the value-spaces 756ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // are shared across targets. To avoid confusion over the definition of 766ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // shared values, an object specific to one target should never be passed 776ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // to a different target. 786ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull Target, 796ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull Target_Max = std::numeric_limits<uint8_t>::max(), 80f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 816ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull static_assert(Target <= Target_Max, "Must not be above max."); 82f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstKind getKind() const { return Kind; } 83467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth virtual const char *getInstName() const; 84f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 85d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT getNumber() const { return Number; } 86d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void renumber(Cfg *Func); 87e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth enum { 88e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberDeleted = -1, 89e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberSentinel = 0, 90e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberInitial = 2, 91e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth NumberExtended = NumberInitial - 1 92e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth }; 93f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 94f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isDeleted() const { return Deleted; } 95f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void setDeleted() { Deleted = true; } 96a59ae6ffa3d06baaedc25883615a8e8bce67e3feJim Stichnoth void setDead(bool Value = true) { Dead = Value; } 97d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void deleteIfDead(); 98f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 99f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasSideEffects() const { return HasSideEffects; } 100f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 101230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth bool isDestRedefined() const { return IsDestRedefined; } 102230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth void setDestRedefined() { IsDestRedefined = true; } 1034775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth 104f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *getDest() const { return Dest; } 105f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 10645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee SizeT getSrcSize() const { return Srcs.size(); } 107f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSrc(SizeT I) const { 108f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < getSrcSize()); 109f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Srcs[I]; 110f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 111032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee void replaceSource(SizeT Index, Operand *Replacement) { 11245f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee assert(Index < getSrcSize()); 113032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee assert(!isDeleted()); 114032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee Srcs[Index] = Replacement; 115032c315836b8c1ed9ff6bb2be1981b6d4a1a3594Manasij Mukherjee } 116f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 117d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth bool isLastUse(const Operand *Src) const; 1188e6bf6e113f496a80b900e61aec802196d83fb6dJim Stichnoth void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); 119d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth 1206ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// Returns a list of out-edges corresponding to a terminator instruction, 1216ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// which is the last instruction of the block. The list must not contain 1226ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// duplicates. 123f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual NodeList getTerminatorEdges() const { 1246ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // All valid terminator instructions override this method. For the default 1256ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // implementation, we assert in case some CfgNode is constructed without a 1266ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull // terminator instruction at the end. 127f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth llvm_unreachable( 128f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth "getTerminatorEdges() called on a non-terminator instruction"); 129f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return NodeList(); 130f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 131336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth virtual bool isUnconditionalBranch() const { return false; } 13257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// If the instruction is a branch-type instruction with OldNode as a target, 13357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// repoint it to NewNode and return true, otherwise return false. Repoint all 13457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instances of OldNode as a target. 13587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { 136336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)OldNode; 137336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth (void)NewNode; 138336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth return false; 139336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth } 140f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 14128b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth /// Returns true if the instruction is equivalent to a simple 14228b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth /// "var_dest=var_src" assignment where the dest and src are both variables. 14328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth virtual bool isVarAssign() const { return false; } 144ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth 145f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth /// Returns true if the instruction has a possible side effect of changing 146f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth /// memory, in which case a memory load should not be reordered with respect 147f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth /// to this instruction. It should really be pure virtual, but we can't 148f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth /// because of g++ and llvm::ilist<>, so we implement it as 149f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth /// report_fatal_error(). 150f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth virtual bool isMemoryWrite() const; 151f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth 152b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth /// Returns true if the (target-specific) instruction represents an 153b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth /// intra-block label, i.e. branch target. This is meant primarily for 154b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth /// Cfg::splitLocalVars(). 155b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth virtual bool isLabel() const { return false; } 156b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth /// If the (target-specific) instruction represents an intra-block branch to 157b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth /// some Label instruction, return that Label branch target instruction; 158b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth /// otherwise return nullptr. 159b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; } 160b9a847280e4486e566dabdd5b0d571309b4ad628Jim Stichnoth 1614775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessLightweight(Cfg *Func, LivenessBV &Live); 16257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Calculates liveness for this instruction. Returns true if this instruction 16357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// is (tentatively) still live and should be retained, and false if this 16457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction is (tentatively) dead and should be deleted. The decision is 16557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// tentative until the liveness dataflow algorithm has converged, and then a 16657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// separate pass permanently deletes dead instructions. 167336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 1684775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 1691873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth 1706ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// Get the number of native instructions that this instruction ultimately 1716ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// emits. By default, high-level instructions don't result in any native 1726ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// instructions, and a target-specific instruction results in a single native 1736ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull /// instruction. 1741873560a5b49434905d52460532c7fcce9b7e6deJim Stichnoth virtual uint32_t getEmitInstCount() const { return 0; } 17557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // TODO(stichnot): Change Inst back to abstract once the g++ build issue is 17657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the 17757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't 17857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // allow the abstract class Ice::Inst. The method should be declared 17957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func) 18057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // const = 0; virtual void emitIAS(const Cfg *Func) const = 0; 181dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emit(const Cfg *) const { 182dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth llvm_unreachable("emit on abstract class"); 183dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth } 184dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth virtual void emitIAS(const Cfg *Func) const { emit(Func); } 185f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth virtual void dump(const Cfg *Func) const; 186d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth virtual void dumpExtras(const Cfg *Func) const; 187f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDecorated(const Cfg *Func) const; 1885bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth void emitSources(const Cfg *Func) const; 189f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpSources(const Cfg *Func) const; 190f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void dumpDest(const Cfg *Func) const; 1915bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth virtual bool isRedundantAssign() const { return false; } 192f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 193fc707ffe812339bddf4ca28fbe8c01045e2b42d6Sean Klein virtual ~Inst() = default; 1947cd926d6d4f401dd3595e0682f48ede3e04ac7f7Manasij Mukherjee void replaceDest(Variable *Var) { Dest = Var; } 195f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 196038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens void operator delete(void *Ptr, std::size_t Size) { 197038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens assert(CfgAllocatorTraits::current() != nullptr); 198038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens CfgAllocatorTraits::current()->Deallocate(Ptr, Size); 199038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens llvm::report_fatal_error("Inst unexpectedly deleted"); 200038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens } 201038a9b9e2b3c3b2e2e532b6194a2b9f8351ad76cNicolas Capens 202f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected: 203f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); 204f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addSource(Operand *Src) { 205f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(Src); 20645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee Srcs.push_back(Src); 207f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 208d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void setLastUse(SizeT VarIndex) { 209d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 210d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 211d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth } 212d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void resetLastUses() { LiveRangesEnded = 0; } 21357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// The destroy() method lets the instruction cleanly release any memory that 21457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// was allocated via the Cfg's allocator. 21545f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee virtual void destroy(Cfg *) {} 216f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 217f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const InstKind Kind; 2189612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Number is the instruction number for describing live ranges. 219d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT Number; 2209612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Deleted means irrevocably deleted. 221eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Deleted = false; 22257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Dead means one of two things depending on context: (1) pending deletion 22357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// after liveness analysis converges, or (2) marked for deletion during 22457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// lowering due to a folded bool operation. 225eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Dead = false; 22657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// HasSideEffects means the instruction is something like a function call or 22757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// a volatile load that can't be removed even if its Dest variable is not 22857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// live. 229eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool HasSideEffects = false; 230230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// IsDestRedefined indicates that this instruction is not the first 231230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// definition of Dest in the basic block. The effect is that liveness 232230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// analysis shouldn't consider this instruction to be the start of Dest's 233230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// live range; rather, there is some other instruction earlier in the basic 234230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// block with the same Dest. This is maintained because liveness analysis 235230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// has an invariant (primarily for performance reasons) that any Variable's 236230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// live range recorded in a basic block has at most one start and at most one 237230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// end. 238230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth bool IsDestRedefined = false; 239f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 240f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *Dest; 241f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const SizeT MaxSrcs; // only used for assert 24245f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee 24345f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee CfgVector<Operand *> Srcs; 244f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 2459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// LiveRangesEnded marks which Variables' live ranges end in this 24657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction. An instruction can have an arbitrary number of source 24757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// operands (e.g. a call instruction), and each source operand can contain 0 24857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// or 1 Variable (and target-specific operands could contain more than 1 24957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Variable). All the variables in an instruction are conceptually flattened 25057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// and each variable is mapped to one bit position of the LiveRangesEnded bit 25157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are 2529612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// tracked this way. 2538072bae156fa62e51e02925997992c4908a2682fAndrew Scull using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry 254d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LREndedBits LiveRangesEnded; 255f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 256f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 257b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst { 258c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstHighLevel() = delete; 2590795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel(const InstHighLevel &) = delete; 2600795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel &operator=(const InstHighLevel &) = delete; 261b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 262b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected: 263b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 264b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) {} 265b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg * /*Func*/) const override { 266b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emit() called on a non-lowered instruction"); 267b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 268b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emitIAS(const Cfg * /*Func*/) const override { 269b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emitIAS() called on a non-lowered instruction"); 270b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 271b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth}; 272b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 27357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the 27457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment 27557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2. 276b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel { 277c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAlloca() = delete; 2787b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca(const InstAlloca &) = delete; 2797b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca &operator=(const InstAlloca &) = delete; 2807b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 2822f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, 2832f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr uint32_t AlignInBytes) { 28431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAlloca>()) 2852f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr InstAlloca(Func, Dest, ByteCount, AlignInBytes); 286f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint32_t getAlignInBytes() const { return AlignInBytes; } 288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSizeInBytes() const { return getSrc(0); } 28955f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth bool getKnownFrameOffset() const { return KnownFrameOffset; } 29055f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth void setKnownFrameOffset() { KnownFrameOffset = true; } 291f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 292b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 2938cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } 294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 2962f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, 2972f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr uint32_t AlignInBytes); 2981bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 299f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const uint32_t AlignInBytes; 30055f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth bool KnownFrameOffset = false; 301f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 302f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 30357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0) 30457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1). 305b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel { 306c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstArithmetic() = delete; 3077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic(const InstArithmetic &) = delete; 3087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic &operator=(const InstArithmetic &) = delete; 3097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 310f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 311f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 312f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag, 313f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTARITHMETIC_TABLE 314f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 3154376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 316f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 3175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 318f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, 319f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 32031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstArithmetic>()) 321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Func, Op, Dest, Source1, Source2); 322f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 323f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getOp() const { return Op; } 324e37076a176e04eee0f35058ccd2109754c193015Eric Holk 325467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth virtual const char *getInstName() const override; 326e37076a176e04eee0f35058ccd2109754c193015Eric Holk 327d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf static const char *getOpName(OpKind Op); 328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isCommutative() const; 329f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 330b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 3318cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 3328cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == Arithmetic; 333f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 335f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 336f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 337f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 338f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 339f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind Op; 340f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 341f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 34257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is 34357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the 34457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering, 34557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for 34657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction. 347b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel { 348c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAssign() = delete; 3497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign(const InstAssign &) = delete; 3507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign &operator=(const InstAssign &) = delete; 3517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 352f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 35431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 355f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 35628b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth bool isVarAssign() const override; 357f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 358b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 3598cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } 360f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 361f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 362f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 363f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 364f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 36557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional 36657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches. 367b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel { 368c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBr() = delete; 3697b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr(const InstBr &) = delete; 3707b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr &operator=(const InstBr &) = delete; 3717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 37357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized 37457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// to an unconditional branch. 375f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *TargetFalse) { 37731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) 378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Func, Source, TargetTrue, TargetFalse); 379f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 3809612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Create an unconditional branch. 381f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, CfgNode *Target) { 38231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) InstBr(Func, Target); 383f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 384ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth bool isUnconditional() const { return getTargetTrue() == nullptr; } 385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { 386f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(!isUnconditional()); 387f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 388f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 389f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetTrue() const { return TargetTrue; } 390f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetFalse() const { return TargetFalse; } 391f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetUnconditional() const { 392f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(isUnconditional()); 393f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getTargetFalse(); 394f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 395b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 396336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool isUnconditionalBranch() const override { return isUnconditional(); } 39787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 398f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 399b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 4008cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } 401f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 402f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 4039612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Conditional branch 404f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 4059612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Unconditional branch 406f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, CfgNode *Target); 407f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4089612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetFalse; /// Doubles as unconditional branch target 4099612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetTrue; /// nullptr if unconditional branch 410f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 411f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 41257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is 41357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1). 414b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel { 415c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCall() = delete; 4167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall(const InstCall &) = delete; 4177b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall &operator=(const InstCall &) = delete; 4187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 419f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 420f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 4215e0a8a71b75ec56981883587612b16f7c1635a03John Porto Operand *CallTarget, bool HasTailCall, 4225e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool IsTargetHelperCall = false) { 4239612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Set HasSideEffects to true so that the call instruction can't be 42457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// dead-code eliminated. IntrinsicCalls can override this if the particular 42557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// intrinsic is deletable and has no side-effects. 4265bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth constexpr bool HasSideEffects = true; 4275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth constexpr InstKind Kind = Inst::Call; 4285e0a8a71b75ec56981883587612b16f7c1635a03John Porto return new (Func->allocate<InstCall>()) 4295e0a8a71b75ec56981883587612b16f7c1635a03John Porto InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, 4305e0a8a71b75ec56981883587612b16f7c1635a03John Porto IsTargetHelperCall, HasSideEffects, Kind); 431f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 432f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArg(Operand *Arg) { addSource(Arg); } 433f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCallTarget() const { return getSrc(0); } 434f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getArg(SizeT I) const { return getSrc(I + 1); } 435f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumArgs() const { return getSrcSize() - 1; } 4368df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool isTailcall() const { return HasTailCall; } 4375e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool isTargetHelperCall() const { return IsTargetHelperCall; } 438f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return true; } 4393ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung void dump(const Cfg *Func) const override; 4408cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } 4418df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Type getReturnType() const; 442f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4433bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected: 4443bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 4455e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff, 4465e0a8a71b75ec56981883587612b16f7c1635a03John Porto InstKind Kind) 4475e0a8a71b75ec56981883587612b16f7c1635a03John Porto : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), 4485e0a8a71b75ec56981883587612b16f7c1635a03John Porto IsTargetHelperCall(IsTargetHelperCall) { 4493bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung HasSideEffects = HasSideEff; 450f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth addSource(CallTarget); 451f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 4523bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 4533bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 4545e0a8a71b75ec56981883587612b16f7c1635a03John Porto const bool HasTailCall; 4555e0a8a71b75ec56981883587612b16f7c1635a03John Porto const bool IsTargetHelperCall; 456f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 457f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4589612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation). 459b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel { 460c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCast() = delete; 4617b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast(const InstCast &) = delete; 4627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast &operator=(const InstCast &) = delete; 4637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 464f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 465f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 466f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 467f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTCAST_TABLE 468f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4694376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4715bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 472bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf static const char *getCastName(OpKind Kind); 473bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf 474f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 475f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source) { 47631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstCast>()) 477f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Func, CastKind, Dest, Source); 478f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 479f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getCastKind() const { return CastKind; } 480f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 481b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 4828cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } 483f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 484f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 485f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 4861bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 487f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind CastKind; 488f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 489f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4909612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction. 491b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel { 492c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstExtractElement() = delete; 4937b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement(const InstExtractElement &) = delete; 4947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement &operator=(const InstExtractElement &) = delete; 4957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 49649889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 49749889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 49849889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2) { 49931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstExtractElement>()) 50049889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Func, Dest, Source1, Source2); 50149889239d4c7ab296c7430722d36032d905110b6Matt Wala } 50249889239d4c7ab296c7430722d36032d905110b6Matt Wala 503f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 504b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5058cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 5068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == ExtractElement; 50749889239d4c7ab296c7430722d36032d905110b6Matt Wala } 50849889239d4c7ab296c7430722d36032d905110b6Matt Wala 50949889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 51049889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 51149889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2); 51249889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 51349889239d4c7ab296c7430722d36032d905110b6Matt Wala 51457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in 51557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1). 516b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel { 517c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFcmp() = delete; 5187b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp(const InstFcmp &) = delete; 5197b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp &operator=(const InstFcmp &) = delete; 5207b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 521f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum FCond { 523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 524f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTFCMP_TABLE 525f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 5264376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 527f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 5285bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 529f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 530f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 53131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFcmp>()) 532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Func, Condition, Dest, Source1, Source2); 533f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 534f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth FCond getCondition() const { return Condition; } 535f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 536b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5378cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } 538f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 539f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 540f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 541f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 5421bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 543f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const FCond Condition; 544f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 545f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 54657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in 54757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1). 548b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel { 549c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIcmp() = delete; 5507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp(const InstIcmp &) = delete; 5517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp &operator=(const InstIcmp &) = delete; 5527b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 553f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 554f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum ICond { 5550c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee#define X(tag, inverse, str) tag, 556f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTICMP_TABLE 557f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 5584376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 559f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 5605bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 561f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 562f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 56331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIcmp>()) 564f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Func, Condition, Dest, Source1, Source2); 565f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 566f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICond getCondition() const { return Condition; } 5670c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee void reverseConditionAndOperands(); 568f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 569b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5708cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } 571f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 572f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 573f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 574f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 5751bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 5760c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee ICond Condition; 577f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 578f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 5799612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction. 580b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel { 581c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstInsertElement() = delete; 5827b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement(const InstInsertElement &) = delete; 5837b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement &operator=(const InstInsertElement &) = delete; 5847b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 58549889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 58649889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 58749889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3) { 58831c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstInsertElement>()) 58949889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Func, Dest, Source1, Source2, Source3); 59049889239d4c7ab296c7430722d36032d905110b6Matt Wala } 59149889239d4c7ab296c7430722d36032d905110b6Matt Wala 592f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 593b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5948cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 5958cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == InsertElement; 59649889239d4c7ab296c7430722d36032d905110b6Matt Wala } 59749889239d4c7ab296c7430722d36032d905110b6Matt Wala 59849889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 59949889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 60049889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3); 60149889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 60249889239d4c7ab296c7430722d36032d905110b6Matt Wala 60357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and 60457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1). 6053bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall { 606c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIntrinsicCall() = delete; 6077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall(const InstIntrinsicCall &) = delete; 6087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 6097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 6103bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic: 6113bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 6123bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, 6133bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo &Info) { 61431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIntrinsicCall>()) 6153bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 6163bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 6178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 6188cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == IntrinsicCall; 6193bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 6203bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 6213bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 622f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { 623f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth return getIntrinsicInfo().IsMemoryWrite; 624f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth } 6253bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 6263bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 6273bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 6283bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 6295e0a8a71b75ec56981883587612b16f7c1635a03John Porto : InstCall(Func, NumArgs, Dest, CallTarget, false, false, 6305e0a8a71b75ec56981883587612b16f7c1635a03John Porto Info.HasSideEffects, Inst::IntrinsicCall), 6313bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Info(Info) {} 6321bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 6333bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo Info; 6343bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung}; 6353bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 63657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0). 637b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel { 638c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstLoad() = delete; 6397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad(const InstLoad &) = delete; 6407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad &operator=(const InstLoad &) = delete; 6417b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 64341689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 644c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth uint32_t Align = 1) { 64541689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 646c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth (void)Align; 64731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 649f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSourceAddress() const { return getSrc(0); } 650f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 651b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } 653f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 654f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 655f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 656f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 657f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 65857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi 65957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I). 660b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel { 661c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstPhi() = delete; 6627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi(const InstPhi &) = delete; 6637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi &operator=(const InstPhi &) = delete; 6647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 665f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 666f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 66731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 668f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 669f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArgument(Operand *Source, CfgNode *Label); 6705bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Operand *getOperandForTarget(CfgNode *Target) const; 671263ac526cb5d182e5bedb16e90566ae8ba1f36ffDavid Sehr void clearOperandForTarget(CfgNode *Target); 67298712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 67316f8061ca23653172ea4c1a43659bb0501b5b474Eric Holk void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } 6744775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 675d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth Liveness *Liveness); 676144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth Inst *lower(Cfg *Func); 677f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 678b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6798cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } 680f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 681f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 68345f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee void destroy(Cfg *Func) override { Inst::destroy(Func); } 684f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 68557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, 68657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// but the Phi instruction is created before InEdges[] is available, so it's 68757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// more complicated to share the list. 68845f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee CfgVector<CfgNode *> Labels; 689f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 690f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 69157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is 69257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and 69357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false. 694b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel { 695c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstRet() = delete; 6967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet(const InstRet &) = delete; 6977b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet &operator=(const InstRet &) = delete; 6987b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 700ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 70131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 702f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 703f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasRetValue() const { return getSrcSize(); } 704f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getRetValue() const { 705f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(hasRetValue()); 706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 707f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 708b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 709f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 710b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7118cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } 712f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 713f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 714f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstRet(Cfg *Func, Operand *RetValue); 715f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 7179612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction. The condition, true, and false operands are captured. 718b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel { 719c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSelect() = delete; 7207b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect(const InstSelect &) = delete; 7217b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect &operator=(const InstSelect &) = delete; 7227b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 725f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *SourceTrue, Operand *SourceFalse) { 72631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSelect>()) 727f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { return getSrc(0); } 730f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getTrueOperand() const { return getSrc(1); } 731f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getFalseOperand() const { return getSrc(2); } 732f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 733b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7348cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } 735f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 736f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 737f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 738f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 739f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 740f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 74157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data 74257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address. 743b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel { 744c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstStore() = delete; 7457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore(const InstStore &) = delete; 7467b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore &operator=(const InstStore &) = delete; 7477b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 748f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 74941689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 750e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth uint32_t Align = 1) { 75141689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 752e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth (void)Align; 75331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 754f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getAddr() const { return getSrc(1); } 756f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getData() const { return getSrc(0); } 757aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull Variable *getRmwBeacon() const; 758e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth void setRmwBeacon(Variable *Beacon); 759f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return true; } 760b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7618cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } 762f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 763f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 764f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstStore(Cfg *Func, Operand *Data, Operand *Addr); 765f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 76757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0). 768b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel { 769c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSwitch() = delete; 7707b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch(const InstSwitch &) = delete; 7717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch &operator=(const InstSwitch &) = delete; 7727b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 773f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 774f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 775f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault) { 77631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSwitch>()) 777f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Func, NumCases, Source, LabelDefault); 778f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 779f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getComparison() const { return getSrc(0); } 780f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabelDefault() const { return LabelDefault; } 781f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumCases() const { return NumCases; } 782f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint64_t getValue(SizeT I) const { 783f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 784f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Values[I]; 785f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 786f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabel(SizeT I) const { 787f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 788f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Labels[I]; 789f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 790f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 791b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 79287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 793f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 794b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7958cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } 796f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 797f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 798f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); 799b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 800f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<uint64_t>(Values); 801f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 802f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 803f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 804f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 805f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault; 8069612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull SizeT NumCases; /// not including the default case 8079612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull uint64_t *Values; /// size is NumCases 8089612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode **Labels; /// size is NumCases 809f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 810f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 81157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands. 812b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel { 813c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstUnreachable() = delete; 8147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable(const InstUnreachable &) = delete; 8157b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable &operator=(const InstUnreachable &) = delete; 8167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 817f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 818f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstUnreachable *create(Cfg *Func) { 81931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 820f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 821b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 822f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 823b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8248cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 8258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == Unreachable; 826f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 827f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 828f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 829c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth explicit InstUnreachable(Cfg *Func); 830f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 831f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 83257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction. There are no operands. Contains an option 8339612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified. 8349f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel { 835c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleLock() = delete; 8369f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(const InstBundleLock &) = delete; 8379f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock &operator=(const InstBundleLock &) = delete; 8389f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8399f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 84056958cb33d3c1d045f2844408d825442d523f59fJohn Porto enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; 8419f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleLock *create(Cfg *Func, Option BundleOption) { 8429f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleLock>()) 8439f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Func, BundleOption); 8449f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8459f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 8469f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 847f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 8489f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 8499f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option getOption() const { return BundleOption; } 8508cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 8518cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == BundleLock; 8529f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8539f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8549f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 8559f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option BundleOption; 8569f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Cfg *Func, Option BundleOption); 8579f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 8589f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 85957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands. 8609f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel { 861c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleUnlock() = delete; 8629f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock(const InstBundleUnlock &) = delete; 8639f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; 8649f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 8669f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleUnlock *create(Cfg *Func) { 8679f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); 8689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 8709f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 871f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 8729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 8738cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 8748cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == BundleUnlock; 8759f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8769f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8779f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 8789f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth explicit InstBundleUnlock(Cfg *Func); 8799f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 8809f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 88157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is 88257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results. 88357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered 88457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags 88557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction. 8869612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 88757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest 88857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest. 88957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its 89057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly 89157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized. 892b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel { 893c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeDef() = delete; 8947b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef(const InstFakeDef &) = delete; 8957b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef &operator=(const InstFakeDef &) = delete; 8967b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 898ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstFakeDef *create(Cfg *Func, Variable *Dest, 899ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth Variable *Src = nullptr) { 90031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 902b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 903198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 904f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 905b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9068cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } 9075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9085bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 9095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 9105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 91257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the 91357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated. 91457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction 9158ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// has no dest, so it can itself never be dead-code eliminated. A weight can 9168ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// be provided to provide extra bias to the register allocator - for simplicity 9178ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// of implementation, weight=N is handled by holding N copies of the variable 9188ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// as source operands. 919b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel { 920c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeUse() = delete; 9217b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse(const InstFakeUse &) = delete; 9227b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse &operator=(const InstFakeUse &) = delete; 9237b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 9245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 9258ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { 9268ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); 9275bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 928b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 929198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 930f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 931b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9328cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } 9335bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9345bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 9358ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); 9365bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9375bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 93857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial 93957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use 94057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the 94157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live 94257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call. 9439612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 94457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills 94557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code 94657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well. 947b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel { 948c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeKill() = delete; 9497b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill(const InstFakeKill &) = delete; 9507b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill &operator=(const InstFakeKill &) = delete; 9517b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 9525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 95387ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 95431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 9555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 9565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *getLinked() const { return Linked; } 957b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 958198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 959f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 960b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9618cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 9628cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == FakeKill; 9638cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth } 9645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9655bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 96687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth InstFakeKill(Cfg *Func, const Inst *Linked); 9675bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9689612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// This instruction is ignored if Linked->isDeleted() is true. 9695bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *Linked; 9705bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9715bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 972a47c11c7f17022050043d69c0802241e0747a056John Porto/// ShuffleVector instruction. This represents a shuffle operation on vector 973a47c11c7f17022050043d69c0802241e0747a056John Porto/// types. This instruction is not part of the PNaCl bitcode: it is generated 974a47c11c7f17022050043d69c0802241e0747a056John Porto/// by Subzero when it matches the pattern used by pnacl-clang when compiling 975a47c11c7f17022050043d69c0802241e0747a056John Porto/// to bitcode. 976a47c11c7f17022050043d69c0802241e0747a056John Portoclass InstShuffleVector : public InstHighLevel { 977a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector() = delete; 978a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector(const InstShuffleVector &) = delete; 979a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector &operator=(const InstShuffleVector &) = delete; 980a47c11c7f17022050043d69c0802241e0747a056John Porto 981a47c11c7f17022050043d69c0802241e0747a056John Portopublic: 982a47c11c7f17022050043d69c0802241e0747a056John Porto static InstShuffleVector *create(Cfg *Func, Variable *Dest, Variable *Src0, 983a47c11c7f17022050043d69c0802241e0747a056John Porto Variable *Src1) { 984a47c11c7f17022050043d69c0802241e0747a056John Porto return new (Func->allocate<InstShuffleVector>()) 985a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector(Func, Dest, Src0, Src1); 986a47c11c7f17022050043d69c0802241e0747a056John Porto } 987a47c11c7f17022050043d69c0802241e0747a056John Porto 988a47c11c7f17022050043d69c0802241e0747a056John Porto SizeT getNumIndexes() const { return NumIndexes; } 989a47c11c7f17022050043d69c0802241e0747a056John Porto 990a47c11c7f17022050043d69c0802241e0747a056John Porto void addIndex(ConstantInteger32 *Index) { 991a47c11c7f17022050043d69c0802241e0747a056John Porto assert(CurrentIndex < NumIndexes); 992a47c11c7f17022050043d69c0802241e0747a056John Porto Indexes[CurrentIndex++] = Index; 993a47c11c7f17022050043d69c0802241e0747a056John Porto } 994a47c11c7f17022050043d69c0802241e0747a056John Porto 995a47c11c7f17022050043d69c0802241e0747a056John Porto ConstantInteger32 *getIndex(SizeT Pos) const { 996a47c11c7f17022050043d69c0802241e0747a056John Porto assert(Pos < NumIndexes); 997a47c11c7f17022050043d69c0802241e0747a056John Porto return Indexes[Pos]; 998a47c11c7f17022050043d69c0802241e0747a056John Porto } 999a47c11c7f17022050043d69c0802241e0747a056John Porto 10001448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens inline bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, 10011448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens int32_t i4, int32_t i5, int32_t i6, int32_t i7) const { 10021448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens static constexpr SizeT ExpectedNumElements = 8; 10031448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens assert(ExpectedNumElements == getNumIndexes()); 10041448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens (void)ExpectedNumElements; 10051448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens 10061448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens return getIndex(0)->getValue() == i0 && getIndex(1)->getValue() == i1 && 10071448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(2)->getValue() == i2 && getIndex(3)->getValue() == i3 && 10081448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(4)->getValue() == i4 && getIndex(5)->getValue() == i5 && 10091448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(6)->getValue() == i6 && getIndex(7)->getValue() == i7; 10101448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens } 10111448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens 10121448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens inline bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, 10131448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens int32_t i4, int32_t i5, int32_t i6, int32_t i7, 10141448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens int32_t i8, int32_t i9, int32_t i10, int32_t i11, 10151448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens int32_t i12, int32_t i13, int32_t i14, 10161448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens int32_t i15) const { 10171448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens static constexpr SizeT ExpectedNumElements = 16; 10181448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens assert(ExpectedNumElements == getNumIndexes()); 10191448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens (void)ExpectedNumElements; 10201448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens 10211448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens return getIndex(0)->getValue() == i0 && getIndex(1)->getValue() == i1 && 10221448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(2)->getValue() == i2 && getIndex(3)->getValue() == i3 && 10231448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(4)->getValue() == i4 && getIndex(5)->getValue() == i5 && 10241448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(6)->getValue() == i6 && getIndex(7)->getValue() == i7 && 10251448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(8)->getValue() == i8 && getIndex(9)->getValue() == i9 && 10261448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(10)->getValue() == i10 && getIndex(11)->getValue() == i11 && 10271448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(12)->getValue() == i12 && getIndex(13)->getValue() == i13 && 10281448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens getIndex(14)->getValue() == i14 && getIndex(15)->getValue() == i15; 10291448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens } 10301448d95c891c926f480e4b898c6cb5716983e582Nicolas Capens 1031cd261e9187a065dc7b917af8f2f8ff435fcf4c15Jim Stichnoth bool isMemoryWrite() const override { return false; } 1032a47c11c7f17022050043d69c0802241e0747a056John Porto void dump(const Cfg *Func) const override; 1033a47c11c7f17022050043d69c0802241e0747a056John Porto static bool classof(const Inst *Instr) { 1034a47c11c7f17022050043d69c0802241e0747a056John Porto return Instr->getKind() == ShuffleVector; 1035a47c11c7f17022050043d69c0802241e0747a056John Porto } 1036a47c11c7f17022050043d69c0802241e0747a056John Porto 1037a47c11c7f17022050043d69c0802241e0747a056John Portoprivate: 1038a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1); 1039a47c11c7f17022050043d69c0802241e0747a056John Porto 1040a47c11c7f17022050043d69c0802241e0747a056John Porto void destroy(Cfg *Func) override { 1041a47c11c7f17022050043d69c0802241e0747a056John Porto Func->deallocateArrayOf<ConstantInteger32 *>(Indexes); 1042a47c11c7f17022050043d69c0802241e0747a056John Porto Inst::destroy(Func); 1043a47c11c7f17022050043d69c0802241e0747a056John Porto } 1044a47c11c7f17022050043d69c0802241e0747a056John Porto 1045a47c11c7f17022050043d69c0802241e0747a056John Porto ConstantInteger32 **Indexes; 1046a47c11c7f17022050043d69c0802241e0747a056John Porto SizeT CurrentIndex = 0; 1047a47c11c7f17022050043d69c0802241e0747a056John Porto const SizeT NumIndexes; 1048a47c11c7f17022050043d69c0802241e0747a056John Porto}; 1049a47c11c7f17022050043d69c0802241e0747a056John Porto 105057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in 105157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes 105257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering. 105387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel { 105487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable() = delete; 105587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(const InstJumpTable &) = delete; 105687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable &operator=(const InstJumpTable &) = delete; 105787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 105887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic: 105987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 106087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull return new (Func->allocate<InstJumpTable>()) 106187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Func, NumTargets, Default); 106287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 106387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void addTarget(SizeT TargetIndex, CfgNode *Target) { 106487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull assert(TargetIndex < NumTargets); 106587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Targets[TargetIndex] = Target; 106687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 106787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 106886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull SizeT getId() const { return Id; } 106986df4e9e6d183f07638440afd2c225b485c03917Andrew Scull SizeT getNumTargets() const { return NumTargets; } 107086df4e9e6d183f07638440afd2c225b485c03917Andrew Scull CfgNode *getTarget(SizeT I) const { 107186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull assert(I < NumTargets); 107286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull return Targets[I]; 107386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull } 1074f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 107587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void dump(const Cfg *Func) const override; 10768cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 10778cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == JumpTable; 10788cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth } 1079030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // Creates a JumpTableData struct (used for ELF emission) that represents this 1080030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // InstJumpTable. 1081030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto JumpTableData toJumpTableData(Assembler *Asm) const; 108287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 1083030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // InstJumpTable is just a placeholder for the switch targets, and it does not 1084030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // need to emit any code, so we redefine emit and emitIAS to do nothing. 1085030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto void emit(const Cfg *) const override {} 1086030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto void emitIAS(const Cfg * /* Func */) const override {} 1087030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto 1088030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto const std::string getName() const { 1089030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto assert(Name.hasStdString()); 1090030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto return Name.toString(); 1091030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto } 1092030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto 1093030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto std::string getSectionName() const { 1094030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto return JumpTableData::createSectionName(FuncName); 109586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull } 109686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull 109787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate: 109887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); 109987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void destroy(Cfg *Func) override { 110087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Func->deallocateArrayOf<CfgNode *>(Targets); 110187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Inst::destroy(Func); 110287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 110387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 110486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull const SizeT Id; 110587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull const SizeT NumTargets; 110687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull CfgNode **Targets; 1107030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto GlobalString Name; // This JumpTable's name in the output. 1108030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto GlobalString FuncName; 110987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull}; 111087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 111167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction inserts an unconditional breakpoint. 111267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// 111367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// On x86, this assembles into an INT 3 instruction. 111467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// 111567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction is primarily meant for debugging the code generator. 111667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkclass InstBreakpoint : public InstHighLevel { 111767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic: 111867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk InstBreakpoint() = delete; 111967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk InstBreakpoint(const InstBreakpoint &) = delete; 112067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk InstBreakpoint &operator=(const InstBreakpoint &) = delete; 112167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 1122f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth explicit InstBreakpoint(Cfg *Func); 1123f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 112467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 112567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic: 112667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk static InstBreakpoint *create(Cfg *Func) { 112767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func); 112867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk } 112967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 113067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk static bool classof(const Inst *Instr) { 113167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk return Instr->getKind() == Breakpoint; 113267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk } 113367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk}; 113467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 11359612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific 11369612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions. 11375bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst { 1138c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstTarget() = delete; 11390795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget(const InstTarget &) = delete; 11400795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget &operator=(const InstTarget &) = delete; 1141b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 11425bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 1143b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth uint32_t getEmitInstCount() const override { return 1; } 1144f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { 1145f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth return true; // conservative answer 1146f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth } 1147b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 11488cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } 11495bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 11505bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected: 11515bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 11525bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) { 11535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth assert(Kind >= Target); 11546ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull assert(Kind <= Target_Max); 11555bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 11565bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 11575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 1158b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 1159b3401d27a236b81393092b4d571df473b5bba64bJan Voung 1160f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice 1161f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 11628b21cc589f0cc01344a6a772c97c1f24a40718ccJim Stichnoth#ifdef PNACL_LLVM 1163dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm { 1164dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 116557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted 116657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked. 1167607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <> 1168dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 1169607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *createSentinel() const { 1170607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth return static_cast<Ice::Inst *>(&Sentinel); 1171607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth } 1172607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void destroySentinel(Ice::Inst *) {} 1173607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *provideInitialHead() const { return createSentinel(); } 1174607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 1175607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void noteHead(Ice::Inst *, Ice::Inst *) {} 1176607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth void deleteNode(Ice::Inst *) {} 1177607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 1178607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate: 1179607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth mutable ilist_half_node<Ice::Inst> Sentinel; 1180607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth}; 1181607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 1182dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm 11838b21cc589f0cc01344a6a772c97c1f24a40718ccJim Stichnoth#endif // PNACL_LLVM 1184dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 1185f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothnamespace Ice { 1186f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1187f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline InstList::iterator instToIterator(Inst *Instr) { 1188f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#ifdef PNACL_LLVM 1189f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth return Instr; 1190a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#else // !PNACL_LLVM 1191f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth return Instr->getIterator(); 1192f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#endif // !PNACL_LLVM 1193f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} 1194f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1195a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnothinline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; } 1196f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1197f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline const Inst *iteratorToInst(InstList::const_iterator Iter) { 1198f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth return &*Iter; 1199f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} 1200f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 12017c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnothinline InstList::iterator 12027c9728faead1368150bcaa8313bc460df29ea1b7Jim StichnothreverseToForwardIterator(InstList::reverse_iterator RI) { 12037c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth#ifdef PNACL_LLVM 12047c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth return RI.base(); 12057c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth#else // !PNACL_LLVM 12067c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth return ++RI.getReverse(); 12077c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth#endif // !PNACL_LLVM 12087c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth} 12097c9728faead1368150bcaa8313bc460df29ea1b7Jim Stichnoth 1210f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} // end of namespace Ice 1211f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1212f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H 1213