| OLD | NEW |
| 1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// | 1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| 11 /// This file declares the Inst class and its target-independent | 11 /// This file declares the Inst class and its target-independent |
| 12 /// subclasses, which represent the high-level Vanilla ICE instructions | 12 /// subclasses, which represent the high-level Vanilla ICE instructions |
| 13 /// and map roughly 1:1 to LLVM instructions. | 13 /// and map roughly 1:1 to LLVM instructions. |
| 14 /// | 14 /// |
| 15 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 16 | 16 |
| 17 #ifndef SUBZERO_SRC_ICEINST_H | 17 #ifndef SUBZERO_SRC_ICEINST_H |
| 18 #define SUBZERO_SRC_ICEINST_H | 18 #define SUBZERO_SRC_ICEINST_H |
| 19 | 19 |
| 20 #include "IceCfg.h" | 20 #include "IceCfg.h" |
| 21 #include "IceDefs.h" | 21 #include "IceDefs.h" |
| 22 #include "IceInst.def" | 22 #include "IceInst.def" |
| 23 #include "IceIntrinsics.h" | 23 #include "IceIntrinsics.h" |
| 24 #include "IceTypes.h" | 24 #include "IceTypes.h" |
| 25 | 25 |
| 26 // TODO: The Cfg structure, and instructions in particular, need to be | 26 // TODO: The Cfg structure, and instructions in particular, need to be |
| 27 // validated for things like valid operand types, valid branch | 27 // validated for things like valid operand types, valid branch targets, proper |
| 28 // targets, proper ordering of Phi and non-Phi instructions, etc. | 28 // ordering of Phi and non-Phi instructions, etc. Most of the validity |
| 29 // Most of the validity checking will be done in the bitcode reader. | 29 // checking will be done in the bitcode reader. We need a list of everything |
| 30 // We need a list of everything that should be validated, and tests | 30 // that should be validated, and tests for each. |
| 31 // for each. | |
| 32 | 31 |
| 33 namespace Ice { | 32 namespace Ice { |
| 34 | 33 |
| 35 /// Base instruction class for ICE. Inst has two subclasses: | 34 /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and |
| 36 /// InstHighLevel and InstTarget. High-level ICE instructions inherit | 35 /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and |
| 37 /// from InstHighLevel, and low-level (target-specific) ICE | 36 /// low-level (target-specific) ICE instructions inherit from InstTarget. |
| 38 /// instructions inherit from InstTarget. | |
| 39 class Inst : public llvm::ilist_node<Inst> { | 37 class Inst : public llvm::ilist_node<Inst> { |
| 40 Inst() = delete; | 38 Inst() = delete; |
| 41 Inst(const Inst &) = delete; | 39 Inst(const Inst &) = delete; |
| 42 Inst &operator=(const Inst &) = delete; | 40 Inst &operator=(const Inst &) = delete; |
| 43 | 41 |
| 44 public: | 42 public: |
| 45 enum InstKind { | 43 enum InstKind { |
| 46 // Arbitrary (alphabetical) order, except put Unreachable first. | 44 // Arbitrary (alphabetical) order, except put Unreachable first. |
| 47 Unreachable, | 45 Unreachable, |
| 48 Alloca, | 46 Alloca, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 61 Select, | 59 Select, |
| 62 Store, | 60 Store, |
| 63 Switch, | 61 Switch, |
| 64 Assign, // not part of LLVM/PNaCl bitcode | 62 Assign, // not part of LLVM/PNaCl bitcode |
| 65 BundleLock, // not part of LLVM/PNaCl bitcode | 63 BundleLock, // not part of LLVM/PNaCl bitcode |
| 66 BundleUnlock, // not part of LLVM/PNaCl bitcode | 64 BundleUnlock, // not part of LLVM/PNaCl bitcode |
| 67 FakeDef, // not part of LLVM/PNaCl bitcode | 65 FakeDef, // not part of LLVM/PNaCl bitcode |
| 68 FakeUse, // not part of LLVM/PNaCl bitcode | 66 FakeUse, // not part of LLVM/PNaCl bitcode |
| 69 FakeKill, // not part of LLVM/PNaCl bitcode | 67 FakeKill, // not part of LLVM/PNaCl bitcode |
| 70 JumpTable, // not part of LLVM/PNaCl bitcode | 68 JumpTable, // not part of LLVM/PNaCl bitcode |
| 71 Target // target-specific low-level ICE | 69 // Anything >= Target is an InstTarget subclass. Note that the value-spaces |
| 72 // Anything >= Target is an InstTarget subclass. | 70 // are shared across targets. To avoid confusion over the definition of |
| 73 // Note that the value-spaces are shared across targets. | 71 // shared values, an object specific to one target should never be passed |
| 74 // To avoid confusion over the definition of shared values, | 72 // to a different target. |
| 75 // an object specific to one target should never be passed | 73 Target, |
| 76 // to a different target. | 74 Target_Max = std::numeric_limits<uint8_t>::max(), |
| 77 }; | 75 }; |
| 76 static_assert(Target <= Target_Max, "Must not be above max."); |
| 78 InstKind getKind() const { return Kind; } | 77 InstKind getKind() const { return Kind; } |
| 79 | 78 |
| 80 InstNumberT getNumber() const { return Number; } | 79 InstNumberT getNumber() const { return Number; } |
| 81 void renumber(Cfg *Func); | 80 void renumber(Cfg *Func); |
| 82 enum { | 81 enum { |
| 83 NumberDeleted = -1, | 82 NumberDeleted = -1, |
| 84 NumberSentinel = 0, | 83 NumberSentinel = 0, |
| 85 NumberInitial = 2, | 84 NumberInitial = 2, |
| 86 NumberExtended = NumberInitial - 1 | 85 NumberExtended = NumberInitial - 1 |
| 87 }; | 86 }; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 100 | 99 |
| 101 SizeT getSrcSize() const { return NumSrcs; } | 100 SizeT getSrcSize() const { return NumSrcs; } |
| 102 Operand *getSrc(SizeT I) const { | 101 Operand *getSrc(SizeT I) const { |
| 103 assert(I < getSrcSize()); | 102 assert(I < getSrcSize()); |
| 104 return Srcs[I]; | 103 return Srcs[I]; |
| 105 } | 104 } |
| 106 | 105 |
| 107 bool isLastUse(const Operand *Src) const; | 106 bool isLastUse(const Operand *Src) const; |
| 108 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); | 107 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); |
| 109 | 108 |
| 110 /// Returns a list of out-edges corresponding to a terminator | 109 /// Returns a list of out-edges corresponding to a terminator instruction, |
| 111 /// instruction, which is the last instruction of the block. | 110 /// which is the last instruction of the block. The list must not contain |
| 112 /// The list must not contain duplicates. | 111 /// duplicates. |
| 113 virtual NodeList getTerminatorEdges() const { | 112 virtual NodeList getTerminatorEdges() const { |
| 114 // All valid terminator instructions override this method. For | 113 // All valid terminator instructions override this method. For the default |
| 115 // the default implementation, we assert in case some CfgNode | 114 // implementation, we assert in case some CfgNode is constructed without a |
| 116 // is constructed without a terminator instruction at the end. | 115 // terminator instruction at the end. |
| 117 llvm_unreachable( | 116 llvm_unreachable( |
| 118 "getTerminatorEdges() called on a non-terminator instruction"); | 117 "getTerminatorEdges() called on a non-terminator instruction"); |
| 119 return NodeList(); | 118 return NodeList(); |
| 120 } | 119 } |
| 121 virtual bool isUnconditionalBranch() const { return false; } | 120 virtual bool isUnconditionalBranch() const { return false; } |
| 122 /// If the instruction is a branch-type instruction with OldNode as a | 121 /// If the instruction is a branch-type instruction with OldNode as a |
| 123 /// target, repoint it to NewNode and return true, otherwise return | 122 /// target, repoint it to NewNode and return true, otherwise return |
| 124 /// false. Repoint all instances of OldNode as a target. | 123 /// false. Repoint all instances of OldNode as a target. |
| 125 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { | 124 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { |
| 126 (void)OldNode; | 125 (void)OldNode; |
| 127 (void)NewNode; | 126 (void)NewNode; |
| 128 return false; | 127 return false; |
| 129 } | 128 } |
| 130 | 129 |
| 131 virtual bool isSimpleAssign() const { return false; } | 130 virtual bool isSimpleAssign() const { return false; } |
| 132 | 131 |
| 133 void livenessLightweight(Cfg *Func, LivenessBV &Live); | 132 void livenessLightweight(Cfg *Func, LivenessBV &Live); |
| 134 /// Calculates liveness for this instruction. Returns true if this | 133 // Calculates liveness for this instruction. Returns true if this |
| 135 /// instruction is (tentatively) still live and should be retained, | 134 /// instruction is (tentatively) still live and should be retained, and false |
| 136 /// and false if this instruction is (tentatively) dead and should be | 135 /// if this instruction is (tentatively) dead and should be deleted. The |
| 137 /// deleted. The decision is tentative until the liveness dataflow | 136 /// decision is tentative until the liveness dataflow algorithm has converged, |
| 138 /// algorithm has converged, and then a separate pass permanently | 137 /// and then a separate pass permanently deletes dead instructions. |
| 139 /// deletes dead instructions. | |
| 140 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, | 138 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, |
| 141 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); | 139 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); |
| 142 | 140 |
| 143 /// Get the number of native instructions that this instruction | 141 /// Get the number of native instructions that this instruction ultimately |
| 144 /// ultimately emits. By default, high-level instructions don't | 142 /// emits. By default, high-level instructions don't result in any native |
| 145 /// result in any native instructions, and a target-specific | 143 /// instructions, and a target-specific instruction results in a single native |
| 146 /// instruction results in a single native instruction. | 144 /// instruction. |
| 147 virtual uint32_t getEmitInstCount() const { return 0; } | 145 virtual uint32_t getEmitInstCount() const { return 0; } |
| 148 // TODO(stichnot): Change Inst back to abstract once the g++ build | 146 // TODO(stichnot): Change Inst back to abstract once the g++ build |
| 149 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ | 147 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ |
| 150 // because the resize(size_t, Ice::Inst) method is incorrectly | 148 // because the resize(size_t, Ice::Inst) method is incorrectly |
| 151 // declared and thus doesn't allow the abstract class Ice::Inst. | 149 // declared and thus doesn't allow the abstract class Ice::Inst. |
| 152 // The method should be declared resize(size_t, const Ice::Inst &). | 150 // The method should be declared resize(size_t, const Ice::Inst &). |
| 153 // virtual void emit(const Cfg *Func) const = 0; | 151 // virtual void emit(const Cfg *Func) const = 0; |
| 154 // virtual void emitIAS(const Cfg *Func) const = 0; | 152 // virtual void emitIAS(const Cfg *Func) const = 0; |
| 155 virtual void emit(const Cfg *) const { | 153 virtual void emit(const Cfg *) const { |
| 156 llvm_unreachable("emit on abstract class"); | 154 llvm_unreachable("emit on abstract class"); |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 | 951 |
| 954 public: | 952 public: |
| 955 uint32_t getEmitInstCount() const override { return 1; } | 953 uint32_t getEmitInstCount() const override { return 1; } |
| 956 void dump(const Cfg *Func) const override; | 954 void dump(const Cfg *Func) const override; |
| 957 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } | 955 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } |
| 958 | 956 |
| 959 protected: | 957 protected: |
| 960 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 958 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| 961 : Inst(Func, Kind, MaxSrcs, Dest) { | 959 : Inst(Func, Kind, MaxSrcs, Dest) { |
| 962 assert(Kind >= Target); | 960 assert(Kind >= Target); |
| 961 assert(Kind <= Target_Max); |
| 963 } | 962 } |
| 964 }; | 963 }; |
| 965 | 964 |
| 966 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); | 965 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); |
| 967 | 966 |
| 968 } // end of namespace Ice | 967 } // end of namespace Ice |
| 969 | 968 |
| 970 namespace llvm { | 969 namespace llvm { |
| 971 | 970 |
| 972 /// Override the default ilist traits so that Inst's private ctor and | 971 /// Override the default ilist traits so that Inst's private ctor and |
| 973 /// deleted dtor aren't invoked. | 972 /// deleted dtor aren't invoked. |
| 974 template <> | 973 template <> |
| 975 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { | 974 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { |
| 976 Ice::Inst *createSentinel() const { | 975 Ice::Inst *createSentinel() const { |
| 977 return static_cast<Ice::Inst *>(&Sentinel); | 976 return static_cast<Ice::Inst *>(&Sentinel); |
| 978 } | 977 } |
| 979 static void destroySentinel(Ice::Inst *) {} | 978 static void destroySentinel(Ice::Inst *) {} |
| 980 Ice::Inst *provideInitialHead() const { return createSentinel(); } | 979 Ice::Inst *provideInitialHead() const { return createSentinel(); } |
| 981 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } | 980 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } |
| 982 static void noteHead(Ice::Inst *, Ice::Inst *) {} | 981 static void noteHead(Ice::Inst *, Ice::Inst *) {} |
| 983 void deleteNode(Ice::Inst *) {} | 982 void deleteNode(Ice::Inst *) {} |
| 984 | 983 |
| 985 private: | 984 private: |
| 986 mutable ilist_half_node<Ice::Inst> Sentinel; | 985 mutable ilist_half_node<Ice::Inst> Sentinel; |
| 987 }; | 986 }; |
| 988 | 987 |
| 989 } // end of namespace llvm | 988 } // end of namespace llvm |
| 990 | 989 |
| 991 #endif // SUBZERO_SRC_ICEINST_H | 990 #endif // SUBZERO_SRC_ICEINST_H |
| OLD | NEW |