IceInst.h revision b9a847280e4486e566dabdd5b0d571309b4ad628
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; 194f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 195f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprotected: 196f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); 197f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addSource(Operand *Src) { 198f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(Src); 19945f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee Srcs.push_back(Src); 200f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 201d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void setLastUse(SizeT VarIndex) { 202d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 203d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 204d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth } 205d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth void resetLastUses() { LiveRangesEnded = 0; } 20657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// The destroy() method lets the instruction cleanly release any memory that 20757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// was allocated via the Cfg's allocator. 20845f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee virtual void destroy(Cfg *) {} 209f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 210f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const InstKind Kind; 2119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Number is the instruction number for describing live ranges. 212d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth InstNumberT Number; 2139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Deleted means irrevocably deleted. 214eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Deleted = false; 21557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Dead means one of two things depending on context: (1) pending deletion 21657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// after liveness analysis converges, or (2) marked for deletion during 21757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// lowering due to a folded bool operation. 218eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool Dead = false; 21957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// HasSideEffects means the instruction is something like a function call or 22057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// a volatile load that can't be removed even if its Dest variable is not 22157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// live. 222eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool HasSideEffects = false; 223230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// IsDestRedefined indicates that this instruction is not the first 224230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// definition of Dest in the basic block. The effect is that liveness 225230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// analysis shouldn't consider this instruction to be the start of Dest's 226230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// live range; rather, there is some other instruction earlier in the basic 227230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// block with the same Dest. This is maintained because liveness analysis 228230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// has an invariant (primarily for performance reasons) that any Variable's 229230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// live range recorded in a basic block has at most one start and at most one 230230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth /// end. 231230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth bool IsDestRedefined = false; 232f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 233f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Variable *Dest; 234f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const SizeT MaxSrcs; // only used for assert 23545f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee 23645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee CfgVector<Operand *> Srcs; 237f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 2389612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// LiveRangesEnded marks which Variables' live ranges end in this 23957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction. An instruction can have an arbitrary number of source 24057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// operands (e.g. a call instruction), and each source operand can contain 0 24157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// or 1 Variable (and target-specific operands could contain more than 1 24257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Variable). All the variables in an instruction are conceptually flattened 24357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// and each variable is mapped to one bit position of the LiveRangesEnded bit 24457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are 2459612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// tracked this way. 2468072bae156fa62e51e02925997992c4908a2682fAndrew Scull using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry 247d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth LREndedBits LiveRangesEnded; 248f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 249f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 250b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstHighLevel : public Inst { 251c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstHighLevel() = delete; 2520795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel(const InstHighLevel &) = delete; 2530795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstHighLevel &operator=(const InstHighLevel &) = delete; 254b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 255b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothprotected: 256b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 257b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) {} 258b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg * /*Func*/) const override { 259b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emit() called on a non-lowered instruction"); 260b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 261b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emitIAS(const Cfg * /*Func*/) const override { 262b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth llvm_unreachable("emitIAS() called on a non-lowered instruction"); 263b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth } 264b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth}; 265b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 26657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Alloca instruction. This captures the size in bytes as getSrc(0), and the 26757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required alignment in bytes. The alignment must be either 0 (no alignment 26857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// required) or a power of 2. 269b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAlloca : public InstHighLevel { 270c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAlloca() = delete; 2717b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca(const InstAlloca &) = delete; 2727b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAlloca &operator=(const InstAlloca &) = delete; 2737b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 274f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 2752f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, 2762f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr uint32_t AlignInBytes) { 27731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAlloca>()) 2782f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr InstAlloca(Func, Dest, ByteCount, AlignInBytes); 279f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 280f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint32_t getAlignInBytes() const { return AlignInBytes; } 281f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSizeInBytes() const { return getSrc(0); } 28255f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth bool getKnownFrameOffset() const { return KnownFrameOffset; } 28355f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth void setKnownFrameOffset() { KnownFrameOffset = true; } 284f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 285b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 2868cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } 287f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 288f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 2892f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, 2902f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr uint32_t AlignInBytes); 2911bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 292f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const uint32_t AlignInBytes; 29355f931f65f307116c2def40c3b11ec93998a907eJim Stichnoth bool KnownFrameOffset = false; 294f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 295f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 29657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Binary arithmetic instruction. The source operands are captured in getSrc(0) 29757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// and getSrc(1). 298b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstArithmetic : public InstHighLevel { 299c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstArithmetic() = delete; 3007b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic(const InstArithmetic &) = delete; 3017b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstArithmetic &operator=(const InstArithmetic &) = delete; 3027b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 303f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 304f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 305f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str, commutative) tag, 306f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTARITHMETIC_TABLE 307f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 3084376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 309f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 3105bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 311f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, 312f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 31331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstArithmetic>()) 314f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Func, Op, Dest, Source1, Source2); 315f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 316f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getOp() const { return Op; } 317e37076a176e04eee0f35058ccd2109754c193015Eric Holk 318467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth virtual const char *getInstName() const override; 319e37076a176e04eee0f35058ccd2109754c193015Eric Holk 320d6064a1aaca7a5596618e559a17cb9b20283ca46Karl Schimpf static const char *getOpName(OpKind Op); 321f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool isCommutative() const; 322f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 323b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 3248cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 3258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == Arithmetic; 326f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 327f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 328f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 329f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 330f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 331f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 332f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind Op; 333f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 334f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 33557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Assignment instruction. The source operand is captured in getSrc(0). This is 33657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// not part of the LLVM bitcode, but is a useful abstraction for some of the 33757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering. E.g., if Phi instruction lowering happens before target lowering, 33857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// or for representing an Inttoptr instruction, or as an intermediate step for 33957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// lowering a Load instruction. 340b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstAssign : public InstHighLevel { 341c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstAssign() = delete; 3427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign(const InstAssign &) = delete; 3437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstAssign &operator=(const InstAssign &) = delete; 3447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 345f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 346f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 34731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 348f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 34928b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth bool isVarAssign() const override; 350f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 351b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 3528cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } 353f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 354f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 355f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 356f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 357f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 35857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Branch instruction. This represents both conditional and unconditional 35957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// branches. 360b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstBr : public InstHighLevel { 361c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBr() = delete; 3627b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr(const InstBr &) = delete; 3637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstBr &operator=(const InstBr &) = delete; 3647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 365f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 36657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized 36757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// to an unconditional branch. 368f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 369f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *TargetFalse) { 37031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) 371f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Func, Source, TargetTrue, TargetFalse); 372f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 3739612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Create an unconditional branch. 374f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstBr *create(Cfg *Func, CfgNode *Target) { 37531c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstBr>()) InstBr(Func, Target); 376f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 377ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth bool isUnconditional() const { return getTargetTrue() == nullptr; } 378f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { 379f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(!isUnconditional()); 380f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 381f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 382f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetTrue() const { return TargetTrue; } 383f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetFalse() const { return TargetFalse; } 384f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getTargetUnconditional() const { 385f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(isUnconditional()); 386f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getTargetFalse(); 387f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 388b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 389336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth bool isUnconditionalBranch() const override { return isUnconditional(); } 39087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 391f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 392b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 3938cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } 394f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 395f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 3969612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Conditional branch 397f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 3989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Unconditional branch 399f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstBr(Cfg *Func, CfgNode *Target); 400f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetFalse; /// Doubles as unconditional branch target 4029612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode *TargetTrue; /// nullptr if unconditional branch 403f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 404f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 40557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction. The call target is captured as getSrc(0), and arg I is 40657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// captured as getSrc(I+1). 407b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCall : public InstHighLevel { 408c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCall() = delete; 4097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall(const InstCall &) = delete; 4107b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCall &operator=(const InstCall &) = delete; 4117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 412f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 413f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 4145e0a8a71b75ec56981883587612b16f7c1635a03John Porto Operand *CallTarget, bool HasTailCall, 4155e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool IsTargetHelperCall = false) { 4169612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Set HasSideEffects to true so that the call instruction can't be 41757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// dead-code eliminated. IntrinsicCalls can override this if the particular 41857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// intrinsic is deletable and has no side-effects. 4195bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth constexpr bool HasSideEffects = true; 4205bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth constexpr InstKind Kind = Inst::Call; 4215e0a8a71b75ec56981883587612b16f7c1635a03John Porto return new (Func->allocate<InstCall>()) 4225e0a8a71b75ec56981883587612b16f7c1635a03John Porto InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, 4235e0a8a71b75ec56981883587612b16f7c1635a03John Porto IsTargetHelperCall, HasSideEffects, Kind); 424f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 425f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArg(Operand *Arg) { addSource(Arg); } 426f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCallTarget() const { return getSrc(0); } 427f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getArg(SizeT I) const { return getSrc(I + 1); } 428f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumArgs() const { return getSrcSize() - 1; } 4298df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf bool isTailcall() const { return HasTailCall; } 4305e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool isTargetHelperCall() const { return IsTargetHelperCall; } 431f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return true; } 4323ce1a991150c1f1954f542d0d998f6f75e89fbc6Jan Voung void dump(const Cfg *Func) const override; 4338cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } 4348df26f3e5fcfe8f5eff00ebd2f308bebcc09153bKarl Schimpf Type getReturnType() const; 435f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4363bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprotected: 4373bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 4385e0a8a71b75ec56981883587612b16f7c1635a03John Porto bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff, 4395e0a8a71b75ec56981883587612b16f7c1635a03John Porto InstKind Kind) 4405e0a8a71b75ec56981883587612b16f7c1635a03John Porto : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), 4415e0a8a71b75ec56981883587612b16f7c1635a03John Porto IsTargetHelperCall(IsTargetHelperCall) { 4423bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung HasSideEffects = HasSideEff; 443f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth addSource(CallTarget); 444f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 4453bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 4463bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 4475e0a8a71b75ec56981883587612b16f7c1635a03John Porto const bool HasTailCall; 4485e0a8a71b75ec56981883587612b16f7c1635a03John Porto const bool IsTargetHelperCall; 449f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 450f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4519612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Cast instruction (a.k.a. conversion operation). 452b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstCast : public InstHighLevel { 453c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstCast() = delete; 4547b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast(const InstCast &) = delete; 4557b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstCast &operator=(const InstCast &) = delete; 4567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 457f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 458f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum OpKind { 459f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 460f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTCAST_TABLE 461f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 4624376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 463f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 4645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 465bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf static const char *getCastName(OpKind Kind); 466bf170370805150026104a9e42e07fb17b0971ad7Karl Schimpf 467f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 468f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source) { 46931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstCast>()) 470f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Func, CastKind, Dest, Source); 471f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 472f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth OpKind getCastKind() const { return CastKind; } 473f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 474b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 4758cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } 476f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 477f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 478f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 4791bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 480f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const OpKind CastKind; 481f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 482f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 4839612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// ExtractElement instruction. 484b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstExtractElement : public InstHighLevel { 485c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstExtractElement() = delete; 4867b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement(const InstExtractElement &) = delete; 4877b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstExtractElement &operator=(const InstExtractElement &) = delete; 4887b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 48949889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 49049889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 49149889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2) { 49231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstExtractElement>()) 49349889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Func, Dest, Source1, Source2); 49449889239d4c7ab296c7430722d36032d905110b6Matt Wala } 49549889239d4c7ab296c7430722d36032d905110b6Matt Wala 496f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 497b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 4988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 4998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == ExtractElement; 50049889239d4c7ab296c7430722d36032d905110b6Matt Wala } 50149889239d4c7ab296c7430722d36032d905110b6Matt Wala 50249889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 50349889239d4c7ab296c7430722d36032d905110b6Matt Wala InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 50449889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2); 50549889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 50649889239d4c7ab296c7430722d36032d905110b6Matt Wala 50757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Floating-point comparison instruction. The source operands are captured in 50857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1). 509b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFcmp : public InstHighLevel { 510c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFcmp() = delete; 5117b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp(const InstFcmp &) = delete; 5127b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFcmp &operator=(const InstFcmp &) = delete; 5137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 514f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 515f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum FCond { 516f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#define X(tag, str) tag, 517f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTFCMP_TABLE 518f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 5194376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 520f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 5215bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 522f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 523f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 52431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFcmp>()) 525f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Func, Condition, Dest, Source1, Source2); 526f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 527f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth FCond getCondition() const { return Condition; } 528f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 529b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5308cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } 531f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 533f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 534f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 5351bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 536f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth const FCond Condition; 537f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 538f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 53957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Integer comparison instruction. The source operands are captured in 54057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// getSrc(0) and getSrc(1). 541b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstIcmp : public InstHighLevel { 542c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIcmp() = delete; 5437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp(const InstIcmp &) = delete; 5447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIcmp &operator=(const InstIcmp &) = delete; 5457b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 546f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 547f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth enum ICond { 5480c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee#define X(tag, inverse, str) tag, 549f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICEINSTICMP_TABLE 550f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#undef X 5514376d2929a6d09055222f41600b165d3a2130657Jim Stichnoth _num 552f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth }; 5535bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 554f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 555f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source1, Operand *Source2) { 55631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIcmp>()) 557f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Func, Condition, Dest, Source1, Source2); 558f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 559f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth ICond getCondition() const { return Condition; } 5600c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee void reverseConditionAndOperands(); 561f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 562b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5638cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } 564f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 565f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 566f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 567f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 5681bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 5690c70417672c2da35b06d121fc49e8bb6967e102eManasij Mukherjee ICond Condition; 570f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 571f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 5729612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// InsertElement instruction. 573b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstInsertElement : public InstHighLevel { 574c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstInsertElement() = delete; 5757b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement(const InstInsertElement &) = delete; 5767b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstInsertElement &operator=(const InstInsertElement &) = delete; 5777b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 57849889239d4c7ab296c7430722d36032d905110b6Matt Walapublic: 57949889239d4c7ab296c7430722d36032d905110b6Matt Wala static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 58049889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3) { 58131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstInsertElement>()) 58249889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Func, Dest, Source1, Source2, Source3); 58349889239d4c7ab296c7430722d36032d905110b6Matt Wala } 58449889239d4c7ab296c7430722d36032d905110b6Matt Wala 585f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 586b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 5878cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 5888cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == InsertElement; 58949889239d4c7ab296c7430722d36032d905110b6Matt Wala } 59049889239d4c7ab296c7430722d36032d905110b6Matt Wala 59149889239d4c7ab296c7430722d36032d905110b6Matt Walaprivate: 59249889239d4c7ab296c7430722d36032d905110b6Matt Wala InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 59349889239d4c7ab296c7430722d36032d905110b6Matt Wala Operand *Source2, Operand *Source3); 59449889239d4c7ab296c7430722d36032d905110b6Matt Wala}; 59549889239d4c7ab296c7430722d36032d905110b6Matt Wala 59657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call to an intrinsic function. The call target is captured as getSrc(0), and 59757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// arg I is captured as getSrc(I+1). 5983bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungclass InstIntrinsicCall : public InstCall { 599c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstIntrinsicCall() = delete; 6007b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall(const InstIntrinsicCall &) = delete; 6017b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 6027b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 6033bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungpublic: 6043bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 6053bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, 6063bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo &Info) { 60731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstIntrinsicCall>()) 6083bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 6093bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 6108cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 6118cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == IntrinsicCall; 6123bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung } 6133bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 6143bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 615f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { 616f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth return getIntrinsicInfo().IsMemoryWrite; 617f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth } 6183bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 6193bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voungprivate: 6203bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 6213bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 6225e0a8a71b75ec56981883587612b16f7c1635a03John Porto : InstCall(Func, NumArgs, Dest, CallTarget, false, false, 6235e0a8a71b75ec56981883587612b16f7c1635a03John Porto Info.HasSideEffects, Inst::IntrinsicCall), 6243bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung Info(Info) {} 6251bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 6263bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung const Intrinsics::IntrinsicInfo Info; 6273bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung}; 6283bd9f1af8fd8ff81857ae79adec01ae56fb3413fJan Voung 62957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Load instruction. The source address is captured in getSrc(0). 630b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstLoad : public InstHighLevel { 631c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstLoad() = delete; 6327b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad(const InstLoad &) = delete; 6337b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstLoad &operator=(const InstLoad &) = delete; 6347b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 635f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 63641689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 637c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth uint32_t Align = 1) { 63841689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 639c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth (void)Align; 64031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 641f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 642f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getSourceAddress() const { return getSrc(0); } 643f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 644b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6458cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } 646f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 647f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 648f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 649f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 650f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 65157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi 65257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// source operand is getSrc(I). 653b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstPhi : public InstHighLevel { 654c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstPhi() = delete; 6557b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi(const InstPhi &) = delete; 6567b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstPhi &operator=(const InstPhi &) = delete; 6577b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 658f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 659f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 66031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 661f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 662f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addArgument(Operand *Source, CfgNode *Label); 6635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth Operand *getOperandForTarget(CfgNode *Target) const; 664263ac526cb5d182e5bedb16e90566ae8ba1f36ffDavid Sehr void clearOperandForTarget(CfgNode *Target); 66598712a39588f258eba8e6448a53a182de4fd1c3cJim Stichnoth CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 66616f8061ca23653172ea4c1a43659bb0501b5b474Eric Holk void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } 6674775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 668d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth Liveness *Liveness); 669144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth Inst *lower(Cfg *Func); 670f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 671b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 6728cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } 673f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 674f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 675f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 67645f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee void destroy(Cfg *Func) override { Inst::destroy(Func); } 677f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 67857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, 67957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// but the Phi instruction is created before InEdges[] is available, so it's 68057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// more complicated to share the list. 68145f51a2675e8367a2d7ce90e5b63e161da668856Manasij Mukherjee CfgVector<CfgNode *> Labels; 682f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 683f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 68457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret instruction. The return value is captured in getSrc(0), but if there is 68557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// no return value (void-type function), then getSrcSize()==0 and 68657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// hasRetValue()==false. 687b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstRet : public InstHighLevel { 688c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstRet() = delete; 6897b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet(const InstRet &) = delete; 6907b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstRet &operator=(const InstRet &) = delete; 6917b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 692f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 693ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 69431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 695f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 696f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth bool hasRetValue() const { return getSrcSize(); } 697f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getRetValue() const { 698f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(hasRetValue()); 699f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return getSrc(0); 700f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 701b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 702f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 703b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7048cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } 705f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 706f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 707f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstRet(Cfg *Func, Operand *RetValue); 708f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 709f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 7109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Select instruction. The condition, true, and false operands are captured. 711b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSelect : public InstHighLevel { 712c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSelect() = delete; 7137b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect(const InstSelect &) = delete; 7147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSelect &operator=(const InstSelect &) = delete; 7157b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 716f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 717f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 718f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *SourceTrue, Operand *SourceFalse) { 71931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSelect>()) 720f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 721f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 722f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getCondition() const { return getSrc(0); } 723f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getTrueOperand() const { return getSrc(1); } 724f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getFalseOperand() const { return getSrc(2); } 725f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 726b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7278cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } 728f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 729f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 730f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 731f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *Source2); 732f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 733f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 73457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. The address operand is captured, along with the data 73557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// operand to be stored into the address. 736b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstStore : public InstHighLevel { 737c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstStore() = delete; 7387b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore(const InstStore &) = delete; 7397b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstStore &operator=(const InstStore &) = delete; 7407b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 741f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 74241689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 743e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth uint32_t Align = 1) { 74441689df2f71c6bcf964248f58824bd6061e7f6c3Karl Schimpf // TODO(kschimpf) Stop ignoring alignment specification. 745e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth (void)Align; 74631c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 747f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 748f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getAddr() const { return getSrc(1); } 749f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getData() const { return getSrc(0); } 750aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull Variable *getRmwBeacon() const; 751e4f65d86d863cc8ec0851846b5716280443cd882Jim Stichnoth void setRmwBeacon(Variable *Beacon); 752f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return true; } 753b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7548cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } 755f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 756f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 757f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstStore(Cfg *Func, Operand *Data, Operand *Addr); 758f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 759f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 76057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Switch instruction. The single source operand is captured as getSrc(0). 761b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstSwitch : public InstHighLevel { 762c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstSwitch() = delete; 7637b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch(const InstSwitch &) = delete; 7647b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstSwitch &operator=(const InstSwitch &) = delete; 7657b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 766f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 767f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 768f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault) { 76931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstSwitch>()) 770f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Func, NumCases, Source, LabelDefault); 771f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 772f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Operand *getComparison() const { return getSrc(0); } 773f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabelDefault() const { return LabelDefault; } 774f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth SizeT getNumCases() const { return NumCases; } 775f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth uint64_t getValue(SizeT I) const { 776f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 777f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Values[I]; 778f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 779f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *getLabel(SizeT I) const { 780f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth assert(I < NumCases); 781f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth return Labels[I]; 782f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 783f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 784b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override; 78587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 786f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 787b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 7888cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } 789f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 790f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 791f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); 792b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void destroy(Cfg *Func) override { 793f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<uint64_t>(Values); 794f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Func->deallocateArrayOf<CfgNode *>(Labels); 795f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth Inst::destroy(Func); 796f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 797f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 798f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth CfgNode *LabelDefault; 7999612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull SizeT NumCases; /// not including the default case 8009612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull uint64_t *Values; /// size is NumCases 8019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull CfgNode **Labels; /// size is NumCases 802f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 803f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 80457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Unreachable instruction. This is a terminator instruction with no operands. 805b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstUnreachable : public InstHighLevel { 806c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstUnreachable() = delete; 8077b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable(const InstUnreachable &) = delete; 8087b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstUnreachable &operator=(const InstUnreachable &) = delete; 8097b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 810f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothpublic: 811f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth static InstUnreachable *create(Cfg *Func) { 81231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 813f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 814b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth NodeList getTerminatorEdges() const override { return NodeList(); } 815f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 816b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 8188cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == Unreachable; 819f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth } 820f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 821f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothprivate: 822c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth explicit InstUnreachable(Cfg *Func); 823f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}; 824f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 82557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleLock instruction. There are no operands. Contains an option 8269612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// indicating whether align_to_end is specified. 8279f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleLock : public InstHighLevel { 828c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleLock() = delete; 8299f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(const InstBundleLock &) = delete; 8309f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock &operator=(const InstBundleLock &) = delete; 8319f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8329f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 83356958cb33d3c1d045f2844408d825442d523f59fJohn Porto enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; 8349f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleLock *create(Cfg *Func, Option BundleOption) { 8359f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleLock>()) 8369f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Func, BundleOption); 8379f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8389f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 8399f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 840f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 8419f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 8429f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option getOption() const { return BundleOption; } 8438cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 8448cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == BundleLock; 8459f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8469f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8479f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 8489f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth Option BundleOption; 8499f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleLock(Cfg *Func, Option BundleOption); 8509f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 8519f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 85257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// BundleUnlock instruction. There are no operands. 8539f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothclass InstBundleUnlock : public InstHighLevel { 854c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstBundleUnlock() = delete; 8559f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock(const InstBundleUnlock &) = delete; 8569f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; 8579f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8589f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothpublic: 8599f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth static InstBundleUnlock *create(Cfg *Func) { 8609f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); 8619f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8629f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emit(const Cfg *Func) const override; 8639f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void emitIAS(const Cfg * /* Func */) const override {} 864f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 8659f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth void dump(const Cfg *Func) const override; 8668cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 8678cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == BundleUnlock; 8689f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth } 8699f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 8709f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnothprivate: 8719f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth explicit InstBundleUnlock(Cfg *Func); 8729f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth}; 8739f42d8ca95d6ed94b6334e652181f82d2edcaa05Jim Stichnoth 87457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeDef instruction. This creates a fake definition of a variable, which is 87557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// how we represent the case when an instruction produces multiple results. 87657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This doesn't happen with high-level ICE instructions, but might with lowered 87757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. For example, this would be a way to represent condition flags 87857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// being modified by an instruction. 8799612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 88057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// It's generally useful to set the optional source operand to be the dest 88157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// variable of the instruction that actually produces the FakeDef dest. 88257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Otherwise, the original instruction could be dead-code eliminated if its 88357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly 88457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// initialized. 885b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeDef : public InstHighLevel { 886c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeDef() = delete; 8877b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef(const InstFakeDef &) = delete; 8887b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeDef &operator=(const InstFakeDef &) = delete; 8897b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 8905bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 891ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth static InstFakeDef *create(Cfg *Func, Variable *Dest, 892ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth Variable *Src = nullptr) { 89331c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 8945bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 895b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 896198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 897f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 898b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 8998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } 9005bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 9025bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 9035bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 90557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeUse instruction. This creates a fake use of a variable, to keep the 90657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instruction that produces that variable from being dead-code eliminated. 90757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// This is useful in a variety of lowering situations. The FakeUse instruction 9088ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// has no dest, so it can itself never be dead-code eliminated. A weight can 9098ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// be provided to provide extra bias to the register allocator - for simplicity 9108ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// of implementation, weight=N is handled by holding N copies of the variable 9118ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth/// as source operands. 912b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeUse : public InstHighLevel { 913c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeUse() = delete; 9147b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse(const InstFakeUse &) = delete; 9157b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeUse &operator=(const InstFakeUse &) = delete; 9167b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 9175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 9188ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { 9198ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); 9205bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 921b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 922198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 923f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 924b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9258cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } 9265bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9275bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 9288ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); 9295bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9305bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 93157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// FakeKill instruction. This "kills" a set of variables by modeling a trivial 93257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// live range at this instruction for each (implicit) variable. The primary use 93357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// is to indicate that scratch registers are killed after a call, so that the 93457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register allocator won't assign a scratch register to a variable whose live 93557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range spans a call. 9369612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 93757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The FakeKill instruction also holds a pointer to the instruction that kills 93857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the set of variables, so that if that linked instruction gets dead-code 93957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// eliminated, the FakeKill instruction will as well. 940b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnothclass InstFakeKill : public InstHighLevel { 941c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstFakeKill() = delete; 9427b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill(const InstFakeKill &) = delete; 9437b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth InstFakeKill &operator=(const InstFakeKill &) = delete; 9447b451a928d91d1c38805c7a53e18519000fe7c42Jim Stichnoth 9455bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 94687ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 94731c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 9485bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 9495bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *getLinked() const { return Linked; } 950b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void emit(const Cfg *Func) const override; 951198b294823bc12bfcf3addb11dc26d4772e2cb8fJan Voung void emitIAS(const Cfg * /* Func */) const override {} 952f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 953b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 9548cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 9558cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == FakeKill; 9568cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth } 9575bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9585bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprivate: 95987ff3a186eb0e5a9ff791964e377910acceed84eJim Stichnoth InstFakeKill(Cfg *Func, const Inst *Linked); 9605bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 9619612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// This instruction is ignored if Linked->isDeleted() is true. 9625bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth const Inst *Linked; 9635bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 9645bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 965a47c11c7f17022050043d69c0802241e0747a056John Porto/// ShuffleVector instruction. This represents a shuffle operation on vector 966a47c11c7f17022050043d69c0802241e0747a056John Porto/// types. This instruction is not part of the PNaCl bitcode: it is generated 967a47c11c7f17022050043d69c0802241e0747a056John Porto/// by Subzero when it matches the pattern used by pnacl-clang when compiling 968a47c11c7f17022050043d69c0802241e0747a056John Porto/// to bitcode. 969a47c11c7f17022050043d69c0802241e0747a056John Portoclass InstShuffleVector : public InstHighLevel { 970a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector() = delete; 971a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector(const InstShuffleVector &) = delete; 972a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector &operator=(const InstShuffleVector &) = delete; 973a47c11c7f17022050043d69c0802241e0747a056John Porto 974a47c11c7f17022050043d69c0802241e0747a056John Portopublic: 975a47c11c7f17022050043d69c0802241e0747a056John Porto static InstShuffleVector *create(Cfg *Func, Variable *Dest, Variable *Src0, 976a47c11c7f17022050043d69c0802241e0747a056John Porto Variable *Src1) { 977a47c11c7f17022050043d69c0802241e0747a056John Porto return new (Func->allocate<InstShuffleVector>()) 978a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector(Func, Dest, Src0, Src1); 979a47c11c7f17022050043d69c0802241e0747a056John Porto } 980a47c11c7f17022050043d69c0802241e0747a056John Porto 981a47c11c7f17022050043d69c0802241e0747a056John Porto SizeT getNumIndexes() const { return NumIndexes; } 982a47c11c7f17022050043d69c0802241e0747a056John Porto 983a47c11c7f17022050043d69c0802241e0747a056John Porto void addIndex(ConstantInteger32 *Index) { 984a47c11c7f17022050043d69c0802241e0747a056John Porto assert(CurrentIndex < NumIndexes); 985a47c11c7f17022050043d69c0802241e0747a056John Porto Indexes[CurrentIndex++] = Index; 986a47c11c7f17022050043d69c0802241e0747a056John Porto } 987a47c11c7f17022050043d69c0802241e0747a056John Porto 988a47c11c7f17022050043d69c0802241e0747a056John Porto ConstantInteger32 *getIndex(SizeT Pos) const { 989a47c11c7f17022050043d69c0802241e0747a056John Porto assert(Pos < NumIndexes); 990a47c11c7f17022050043d69c0802241e0747a056John Porto return Indexes[Pos]; 991a47c11c7f17022050043d69c0802241e0747a056John Porto } 992a47c11c7f17022050043d69c0802241e0747a056John Porto 993cd261e9187a065dc7b917af8f2f8ff435fcf4c15Jim Stichnoth bool isMemoryWrite() const override { return false; } 994a47c11c7f17022050043d69c0802241e0747a056John Porto void dump(const Cfg *Func) const override; 995a47c11c7f17022050043d69c0802241e0747a056John Porto static bool classof(const Inst *Instr) { 996a47c11c7f17022050043d69c0802241e0747a056John Porto return Instr->getKind() == ShuffleVector; 997a47c11c7f17022050043d69c0802241e0747a056John Porto } 998a47c11c7f17022050043d69c0802241e0747a056John Porto 999a47c11c7f17022050043d69c0802241e0747a056John Portoprivate: 1000a47c11c7f17022050043d69c0802241e0747a056John Porto InstShuffleVector(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1); 1001a47c11c7f17022050043d69c0802241e0747a056John Porto 1002a47c11c7f17022050043d69c0802241e0747a056John Porto void destroy(Cfg *Func) override { 1003a47c11c7f17022050043d69c0802241e0747a056John Porto Func->deallocateArrayOf<ConstantInteger32 *>(Indexes); 1004a47c11c7f17022050043d69c0802241e0747a056John Porto Inst::destroy(Func); 1005a47c11c7f17022050043d69c0802241e0747a056John Porto } 1006a47c11c7f17022050043d69c0802241e0747a056John Porto 1007a47c11c7f17022050043d69c0802241e0747a056John Porto ConstantInteger32 **Indexes; 1008a47c11c7f17022050043d69c0802241e0747a056John Porto SizeT CurrentIndex = 0; 1009a47c11c7f17022050043d69c0802241e0747a056John Porto const SizeT NumIndexes; 1010a47c11c7f17022050043d69c0802241e0747a056John Porto}; 1011a47c11c7f17022050043d69c0802241e0747a056John Porto 101257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// JumpTable instruction. This represents a jump table that will be stored in 101357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// the .rodata section. This is used to track and repoint the target CfgNodes 101457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// which may change, for example due to splitting for phi lowering. 101587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass InstJumpTable : public InstHighLevel { 101687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable() = delete; 101787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(const InstJumpTable &) = delete; 101887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable &operator=(const InstJumpTable &) = delete; 101987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 102087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic: 102187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 102287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull return new (Func->allocate<InstJumpTable>()) 102387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Func, NumTargets, Default); 102487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 102587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void addTarget(SizeT TargetIndex, CfgNode *Target) { 102687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull assert(TargetIndex < NumTargets); 102787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Targets[TargetIndex] = Target; 102887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 102987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 103086df4e9e6d183f07638440afd2c225b485c03917Andrew Scull SizeT getId() const { return Id; } 103186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull SizeT getNumTargets() const { return NumTargets; } 103286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull CfgNode *getTarget(SizeT I) const { 103386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull assert(I < NumTargets); 103486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull return Targets[I]; 103586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull } 1036f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 103787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void dump(const Cfg *Func) const override; 10388cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { 10398cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == JumpTable; 10408cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth } 1041030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // Creates a JumpTableData struct (used for ELF emission) that represents this 1042030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // InstJumpTable. 1043030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto JumpTableData toJumpTableData(Assembler *Asm) const; 104487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 1045030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // InstJumpTable is just a placeholder for the switch targets, and it does not 1046030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto // need to emit any code, so we redefine emit and emitIAS to do nothing. 1047030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto void emit(const Cfg *) const override {} 1048030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto void emitIAS(const Cfg * /* Func */) const override {} 1049030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto 1050030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto const std::string getName() const { 1051030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto assert(Name.hasStdString()); 1052030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto return Name.toString(); 1053030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto } 1054030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto 1055030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto std::string getSectionName() const { 1056030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto return JumpTableData::createSectionName(FuncName); 105786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull } 105886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull 105987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate: 106087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); 106187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull void destroy(Cfg *Func) override { 106287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Func->deallocateArrayOf<CfgNode *>(Targets); 106387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull Inst::destroy(Func); 106487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull } 106587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 106686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull const SizeT Id; 106787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull const SizeT NumTargets; 106887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull CfgNode **Targets; 1069030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto GlobalString Name; // This JumpTable's name in the output. 1070030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto GlobalString FuncName; 107187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull}; 107287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 107367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction inserts an unconditional breakpoint. 107467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// 107567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// On x86, this assembles into an INT 3 instruction. 107667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// 107767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk/// This instruction is primarily meant for debugging the code generator. 107867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkclass InstBreakpoint : public InstHighLevel { 107967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic: 108067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk InstBreakpoint() = delete; 108167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk InstBreakpoint(const InstBreakpoint &) = delete; 108267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk InstBreakpoint &operator=(const InstBreakpoint &) = delete; 108367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 1084f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth explicit InstBreakpoint(Cfg *Func); 1085f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { return false; } 108667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 108767c7c4161ad5bcf234357348a421e313932a8ee3Eric Holkpublic: 108867c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk static InstBreakpoint *create(Cfg *Func) { 108967c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func); 109067c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk } 109167c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 109267c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk static bool classof(const Inst *Instr) { 109367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk return Instr->getKind() == Breakpoint; 109467c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk } 109567c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk}; 109667c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk 10979612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// The Target instruction is the base class for all target-specific 10989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// instructions. 10995bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothclass InstTarget : public Inst { 1100c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth InstTarget() = delete; 11010795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget(const InstTarget &) = delete; 11020795ba012d00ef611ce1c6898db7652ed4559c62Jim Stichnoth InstTarget &operator=(const InstTarget &) = delete; 1103b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth 11045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothpublic: 1105b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth uint32_t getEmitInstCount() const override { return 1; } 1106f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth bool isMemoryWrite() const override { 1107f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth return true; // conservative answer 1108f1f773dd2c9c7118e07caa61d580bdba4447c25cJim Stichnoth } 1109b56c8f426e0dfc7cb952945252051a009b5a2f20Jim Stichnoth void dump(const Cfg *Func) const override; 11108cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } 11115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 11125bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothprotected: 11135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 11145bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth : Inst(Func, Kind, MaxSrcs, Dest) { 11155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth assert(Kind >= Target); 11166ef7949448bbe3fdb1a0cf3dcbd32fd46c4baf9dAndrew Scull assert(Kind <= Target_Max); 11175bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth } 11185bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}; 11195bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth 1120b3401d27a236b81393092b4d571df473b5bba64bJan Voungbool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 1121b3401d27a236b81393092b4d571df473b5bba64bJan Voung 1122f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice 1123f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth 1124dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothnamespace llvm { 1125dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 112657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Override the default ilist traits so that Inst's private ctor and deleted 112757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// dtor aren't invoked. 1128607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothtemplate <> 1129dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnothstruct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 1130607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *createSentinel() const { 1131607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth return static_cast<Ice::Inst *>(&Sentinel); 1132607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth } 1133607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void destroySentinel(Ice::Inst *) {} 1134607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *provideInitialHead() const { return createSentinel(); } 1135607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 1136607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth static void noteHead(Ice::Inst *, Ice::Inst *) {} 1137607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth void deleteNode(Ice::Inst *) {} 1138607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 1139607e9f0e947305da9b54df6573920299c9f6610eJim Stichnothprivate: 1140607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth mutable ilist_half_node<Ice::Inst> Sentinel; 1141607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth}; 1142607e9f0e947305da9b54df6573920299c9f6610eJim Stichnoth 1143dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth} // end of namespace llvm 1144dddaf9cae5107a60becbe69628d774815e9305e7Jim Stichnoth 1145f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothnamespace Ice { 1146f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1147f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline InstList::iterator instToIterator(Inst *Instr) { 1148f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#ifdef PNACL_LLVM 1149f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth return Instr; 1150a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#else // !PNACL_LLVM 1151f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth return Instr->getIterator(); 1152f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#endif // !PNACL_LLVM 1153f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} 1154f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1155a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnothinline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; } 1156f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1157f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnothinline const Inst *iteratorToInst(InstList::const_iterator Iter) { 1158f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth return &*Iter; 1159f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} 1160f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1161f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth} // end of namespace Ice 1162f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth 1163f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#endif // SUBZERO_SRC_ICEINST_H 1164