Chromium Code Reviews| 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 "IceTargetKinds.def" | |
| 24 #include "IceTypes.h" | 25 #include "IceTypes.h" |
| 25 | 26 |
| 26 // TODO: The Cfg structure, and instructions in particular, need to be | 27 // TODO: The Cfg structure, and instructions in particular, need to be |
| 27 // validated for things like valid operand types, valid branch | 28 // validated for things like valid operand types, valid branch targets, proper |
| 28 // targets, proper ordering of Phi and non-Phi instructions, etc. | 29 // 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. | 30 // 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 | 31 // that should be validated, and tests for each. |
| 31 // for each. | |
| 32 | 32 |
| 33 namespace Ice { | 33 namespace Ice { |
| 34 | 34 |
| 35 /// Base instruction class for ICE. Inst has two subclasses: | 35 /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and |
| 36 /// InstHighLevel and InstTarget. High-level ICE instructions inherit | 36 /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and |
| 37 /// from InstHighLevel, and low-level (target-specific) ICE | 37 /// low-level (target-specific) ICE instructions inherit from InstTarget. |
| 38 /// instructions inherit from InstTarget. | |
| 39 class Inst : public llvm::ilist_node<Inst> { | 38 class Inst : public llvm::ilist_node<Inst> { |
| 40 Inst() = delete; | 39 Inst() = delete; |
| 41 Inst(const Inst &) = delete; | 40 Inst(const Inst &) = delete; |
| 42 Inst &operator=(const Inst &) = delete; | 41 Inst &operator=(const Inst &) = delete; |
| 43 | 42 |
| 44 public: | 43 public: |
| 45 enum InstKind { | 44 enum InstKind { |
| 46 // Arbitrary (alphabetical) order, except put Unreachable first. | 45 // Arbitrary (alphabetical) order, except put Unreachable first. |
| 47 Unreachable, | 46 Unreachable, |
| 48 Alloca, | 47 Alloca, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 61 Select, | 60 Select, |
| 62 Store, | 61 Store, |
| 63 Switch, | 62 Switch, |
| 64 Assign, // not part of LLVM/PNaCl bitcode | 63 Assign, // not part of LLVM/PNaCl bitcode |
| 65 BundleLock, // not part of LLVM/PNaCl bitcode | 64 BundleLock, // not part of LLVM/PNaCl bitcode |
| 66 BundleUnlock, // not part of LLVM/PNaCl bitcode | 65 BundleUnlock, // not part of LLVM/PNaCl bitcode |
| 67 FakeDef, // not part of LLVM/PNaCl bitcode | 66 FakeDef, // not part of LLVM/PNaCl bitcode |
| 68 FakeUse, // not part of LLVM/PNaCl bitcode | 67 FakeUse, // not part of LLVM/PNaCl bitcode |
| 69 FakeKill, // not part of LLVM/PNaCl bitcode | 68 FakeKill, // not part of LLVM/PNaCl bitcode |
| 70 JumpTable, // not part of LLVM/PNaCl bitcode | 69 JumpTable, // not part of LLVM/PNaCl bitcode |
| 71 Target // target-specific low-level ICE | 70 // target-specific low-level ICE Anything >= Target is an InstTarget |
|
Jim Stichnoth
2015/09/04 21:32:48
probably delete the "target-specific low-level ICE
ascull
2015/09/05 00:00:48
Done.
| |
| 72 // Anything >= Target is an InstTarget subclass. | 71 // subclass. Note that the value-spaces are shared across targets. To |
| 73 // Note that the value-spaces are shared across targets. | 72 // avoid confusion over the definition of shared values, an object specific |
| 74 // To avoid confusion over the definition of shared values, | 73 // to one target should never be passed to a different target. |
| 75 // an object specific to one target should never be passed | 74 #define X(n) Target##n, |
| 76 // to a different target. | 75 TARGETKINDS_INSTS_TABLE |
|
Jim Stichnoth
2015/09/04 21:32:49
IIRC, you are solving the problem by defining Targ
ascull
2015/09/05 00:00:48
I'm not sure I see what you mean here. You need to
Jim Stichnoth
2015/09/05 01:03:22
I believe the UB comes from trying to represent an
ascull
2015/09/08 17:29:26
Done.
| |
| 76 #undef X | |
| 77 }; | 77 }; |
| 78 InstKind getKind() const { return Kind; } | 78 InstKind getKind() const { return Kind; } |
| 79 | 79 |
| 80 InstNumberT getNumber() const { return Number; } | 80 InstNumberT getNumber() const { return Number; } |
| 81 void renumber(Cfg *Func); | 81 void renumber(Cfg *Func); |
| 82 enum { | 82 enum { |
| 83 NumberDeleted = -1, | 83 NumberDeleted = -1, |
| 84 NumberSentinel = 0, | 84 NumberSentinel = 0, |
| 85 NumberInitial = 2, | 85 NumberInitial = 2, |
| 86 NumberExtended = NumberInitial - 1 | 86 NumberExtended = NumberInitial - 1 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 100 | 100 |
| 101 SizeT getSrcSize() const { return NumSrcs; } | 101 SizeT getSrcSize() const { return NumSrcs; } |
| 102 Operand *getSrc(SizeT I) const { | 102 Operand *getSrc(SizeT I) const { |
| 103 assert(I < getSrcSize()); | 103 assert(I < getSrcSize()); |
| 104 return Srcs[I]; | 104 return Srcs[I]; |
| 105 } | 105 } |
| 106 | 106 |
| 107 bool isLastUse(const Operand *Src) const; | 107 bool isLastUse(const Operand *Src) const; |
| 108 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); | 108 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); |
| 109 | 109 |
| 110 /// Returns a list of out-edges corresponding to a terminator | 110 /// Returns a list of out-edges corresponding to a terminator instruction, |
| 111 /// instruction, which is the last instruction of the block. | 111 /// which is the last instruction of the block. The list must not contain |
| 112 /// The list must not contain duplicates. | 112 /// duplicates. |
| 113 virtual NodeList getTerminatorEdges() const { | 113 virtual NodeList getTerminatorEdges() const { |
| 114 // All valid terminator instructions override this method. For | 114 // All valid terminator instructions override this method. For the default |
| 115 // the default implementation, we assert in case some CfgNode | 115 // implementation, we assert in case some CfgNode is constructed without a |
| 116 // is constructed without a terminator instruction at the end. | 116 // terminator instruction at the end. |
| 117 llvm_unreachable( | 117 llvm_unreachable( |
| 118 "getTerminatorEdges() called on a non-terminator instruction"); | 118 "getTerminatorEdges() called on a non-terminator instruction"); |
| 119 return NodeList(); | 119 return NodeList(); |
| 120 } | 120 } |
| 121 virtual bool isUnconditionalBranch() const { return false; } | 121 virtual bool isUnconditionalBranch() const { return false; } |
| 122 /// If the instruction is a branch-type instruction with OldNode as a | 122 /// If the instruction is a branch-type instruction with OldNode as a |
| 123 /// target, repoint it to NewNode and return true, otherwise return | 123 /// target, repoint it to NewNode and return true, otherwise return |
| 124 /// false. Repoint all instances of OldNode as a target. | 124 /// false. Repoint all instances of OldNode as a target. |
| 125 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { | 125 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { |
| 126 (void)OldNode; | 126 (void)OldNode; |
| 127 (void)NewNode; | 127 (void)NewNode; |
| 128 return false; | 128 return false; |
| 129 } | 129 } |
| 130 | 130 |
| 131 virtual bool isSimpleAssign() const { return false; } | 131 virtual bool isSimpleAssign() const { return false; } |
| 132 | 132 |
| 133 void livenessLightweight(Cfg *Func, LivenessBV &Live); | 133 void livenessLightweight(Cfg *Func, LivenessBV &Live); |
| 134 /// Calculates liveness for this instruction. Returns true if this | 134 // Calculates liveness for this instruction. Returns true if this |
| 135 /// instruction is (tentatively) still live and should be retained, | 135 /// instruction is (tentatively) still live and should be retained, and false |
| 136 /// and false if this instruction is (tentatively) dead and should be | 136 /// if this instruction is (tentatively) dead and should be deleted. The |
| 137 /// deleted. The decision is tentative until the liveness dataflow | 137 /// decision is tentative until the liveness dataflow algorithm has converged, |
| 138 /// algorithm has converged, and then a separate pass permanently | 138 /// and then a separate pass permanently deletes dead instructions. |
| 139 /// deletes dead instructions. | |
| 140 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, | 139 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, |
| 141 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); | 140 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); |
| 142 | 141 |
| 143 /// Get the number of native instructions that this instruction | 142 /// Get the number of native instructions that this instruction ultimately |
| 144 /// ultimately emits. By default, high-level instructions don't | 143 /// emits. By default, high-level instructions don't result in any native |
| 145 /// result in any native instructions, and a target-specific | 144 /// instructions, and a target-specific instruction results in a single native |
| 146 /// instruction results in a single native instruction. | 145 /// instruction. |
| 147 virtual uint32_t getEmitInstCount() const { return 0; } | 146 virtual uint32_t getEmitInstCount() const { return 0; } |
| 148 // TODO(stichnot): Change Inst back to abstract once the g++ build | 147 // TODO(stichnot): Change Inst back to abstract once the g++ build |
| 149 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ | 148 // issue is fixed. llvm::ilist<Ice::Inst> doesn't work under g++ |
| 150 // because the resize(size_t, Ice::Inst) method is incorrectly | 149 // because the resize(size_t, Ice::Inst) method is incorrectly |
| 151 // declared and thus doesn't allow the abstract class Ice::Inst. | 150 // declared and thus doesn't allow the abstract class Ice::Inst. |
| 152 // The method should be declared resize(size_t, const Ice::Inst &). | 151 // The method should be declared resize(size_t, const Ice::Inst &). |
| 153 // virtual void emit(const Cfg *Func) const = 0; | 152 // virtual void emit(const Cfg *Func) const = 0; |
| 154 // virtual void emitIAS(const Cfg *Func) const = 0; | 153 // virtual void emitIAS(const Cfg *Func) const = 0; |
| 155 virtual void emit(const Cfg *) const { | 154 virtual void emit(const Cfg *) const { |
| 156 llvm_unreachable("emit on abstract class"); | 155 llvm_unreachable("emit on abstract class"); |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 947 /// The Target instruction is the base class for all target-specific | 946 /// The Target instruction is the base class for all target-specific |
| 948 /// instructions. | 947 /// instructions. |
| 949 class InstTarget : public Inst { | 948 class InstTarget : public Inst { |
| 950 InstTarget() = delete; | 949 InstTarget() = delete; |
| 951 InstTarget(const InstTarget &) = delete; | 950 InstTarget(const InstTarget &) = delete; |
| 952 InstTarget &operator=(const InstTarget &) = delete; | 951 InstTarget &operator=(const InstTarget &) = delete; |
| 953 | 952 |
| 954 public: | 953 public: |
| 955 uint32_t getEmitInstCount() const override { return 1; } | 954 uint32_t getEmitInstCount() const override { return 1; } |
| 956 void dump(const Cfg *Func) const override; | 955 void dump(const Cfg *Func) const override; |
| 957 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } | 956 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target0; } |
| 958 | 957 |
| 959 protected: | 958 protected: |
| 960 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 959 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| 961 : Inst(Func, Kind, MaxSrcs, Dest) { | 960 : Inst(Func, Kind, MaxSrcs, Dest) { |
| 962 assert(Kind >= Target); | 961 assert(Kind >= Target0); |
| 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 |