| 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 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 void setDead(bool Value = true) { Dead = Value; } | 96 void setDead(bool Value = true) { Dead = Value; } |
| 97 void deleteIfDead(); | 97 void deleteIfDead(); |
| 98 | 98 |
| 99 bool hasSideEffects() const { return HasSideEffects; } | 99 bool hasSideEffects() const { return HasSideEffects; } |
| 100 | 100 |
| 101 bool isDestRedefined() const { return IsDestRedefined; } | 101 bool isDestRedefined() const { return IsDestRedefined; } |
| 102 void setDestRedefined() { IsDestRedefined = true; } | 102 void setDestRedefined() { IsDestRedefined = true; } |
| 103 | 103 |
| 104 Variable *getDest() const { return Dest; } | 104 Variable *getDest() const { return Dest; } |
| 105 | 105 |
| 106 SizeT getSrcSize() const { return NumSrcs; } | 106 SizeT getSrcSize() const { return Srcs.size(); } |
| 107 Operand *getSrc(SizeT I) const { | 107 Operand *getSrc(SizeT I) const { |
| 108 assert(I < getSrcSize()); | 108 assert(I < getSrcSize()); |
| 109 return Srcs[I]; | 109 return Srcs[I]; |
| 110 } | 110 } |
| 111 void replaceSource(SizeT Index, Operand *Replacement) { | 111 void replaceSource(SizeT Index, Operand *Replacement) { |
| 112 assert(Index < NumSrcs); | 112 assert(Index < getSrcSize()); |
| 113 assert(!isDeleted()); | 113 assert(!isDeleted()); |
| 114 assert(LiveRangesEnded == 0); | 114 assert(LiveRangesEnded == 0); |
| 115 // Invalidates liveness info because the use Srcs[Index] is removed. | 115 // Invalidates liveness info because the use Srcs[Index] is removed. |
| 116 Srcs[Index] = Replacement; | 116 Srcs[Index] = Replacement; |
| 117 } | 117 } |
| 118 | 118 |
| 119 bool isLastUse(const Operand *Src) const; | 119 bool isLastUse(const Operand *Src) const; |
| 120 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); | 120 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); |
| 121 | 121 |
| 122 /// Returns a list of out-edges corresponding to a terminator instruction, | 122 /// Returns a list of out-edges corresponding to a terminator instruction, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 void dumpSources(const Cfg *Func) const; | 182 void dumpSources(const Cfg *Func) const; |
| 183 void dumpDest(const Cfg *Func) const; | 183 void dumpDest(const Cfg *Func) const; |
| 184 virtual bool isRedundantAssign() const { return false; } | 184 virtual bool isRedundantAssign() const { return false; } |
| 185 | 185 |
| 186 virtual ~Inst() = default; | 186 virtual ~Inst() = default; |
| 187 | 187 |
| 188 protected: | 188 protected: |
| 189 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); | 189 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); |
| 190 void addSource(Operand *Src) { | 190 void addSource(Operand *Src) { |
| 191 assert(Src); | 191 assert(Src); |
| 192 assert(NumSrcs < MaxSrcs); | 192 Srcs.push_back(Src); |
| 193 Srcs[NumSrcs++] = Src; | |
| 194 } | 193 } |
| 195 void setLastUse(SizeT VarIndex) { | 194 void setLastUse(SizeT VarIndex) { |
| 196 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) | 195 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) |
| 197 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); | 196 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); |
| 198 } | 197 } |
| 199 void resetLastUses() { LiveRangesEnded = 0; } | 198 void resetLastUses() { LiveRangesEnded = 0; } |
| 200 /// The destroy() method lets the instruction cleanly release any memory that | 199 /// The destroy() method lets the instruction cleanly release any memory that |
| 201 /// was allocated via the Cfg's allocator. | 200 /// was allocated via the Cfg's allocator. |
| 202 virtual void destroy(Cfg *Func) { Func->deallocateArrayOf<Operand *>(Srcs); } | 201 virtual void destroy(Cfg *) {} |
| 203 | 202 |
| 204 const InstKind Kind; | 203 const InstKind Kind; |
| 205 /// Number is the instruction number for describing live ranges. | 204 /// Number is the instruction number for describing live ranges. |
| 206 InstNumberT Number; | 205 InstNumberT Number; |
| 207 /// Deleted means irrevocably deleted. | 206 /// Deleted means irrevocably deleted. |
| 208 bool Deleted = false; | 207 bool Deleted = false; |
| 209 /// Dead means one of two things depending on context: (1) pending deletion | 208 /// Dead means one of two things depending on context: (1) pending deletion |
| 210 /// after liveness analysis converges, or (2) marked for deletion during | 209 /// after liveness analysis converges, or (2) marked for deletion during |
| 211 /// lowering due to a folded bool operation. | 210 /// lowering due to a folded bool operation. |
| 212 bool Dead = false; | 211 bool Dead = false; |
| 213 /// HasSideEffects means the instruction is something like a function call or | 212 /// HasSideEffects means the instruction is something like a function call or |
| 214 /// a volatile load that can't be removed even if its Dest variable is not | 213 /// a volatile load that can't be removed even if its Dest variable is not |
| 215 /// live. | 214 /// live. |
| 216 bool HasSideEffects = false; | 215 bool HasSideEffects = false; |
| 217 /// IsDestRedefined indicates that this instruction is not the first | 216 /// IsDestRedefined indicates that this instruction is not the first |
| 218 /// definition of Dest in the basic block. The effect is that liveness | 217 /// definition of Dest in the basic block. The effect is that liveness |
| 219 /// analysis shouldn't consider this instruction to be the start of Dest's | 218 /// analysis shouldn't consider this instruction to be the start of Dest's |
| 220 /// live range; rather, there is some other instruction earlier in the basic | 219 /// live range; rather, there is some other instruction earlier in the basic |
| 221 /// block with the same Dest. This is maintained because liveness analysis | 220 /// block with the same Dest. This is maintained because liveness analysis |
| 222 /// has an invariant (primarily for performance reasons) that any Variable's | 221 /// has an invariant (primarily for performance reasons) that any Variable's |
| 223 /// live range recorded in a basic block has at most one start and at most one | 222 /// live range recorded in a basic block has at most one start and at most one |
| 224 /// end. | 223 /// end. |
| 225 bool IsDestRedefined = false; | 224 bool IsDestRedefined = false; |
| 226 | 225 |
| 227 Variable *Dest; | 226 Variable *Dest; |
| 228 const SizeT MaxSrcs; // only used for assert | 227 const SizeT MaxSrcs; // only used for assert |
| 229 SizeT NumSrcs = 0; | 228 |
| 230 Operand **Srcs; | 229 CfgVector<Operand *> Srcs; |
| 231 | 230 |
| 232 /// LiveRangesEnded marks which Variables' live ranges end in this | 231 /// LiveRangesEnded marks which Variables' live ranges end in this |
| 233 /// instruction. An instruction can have an arbitrary number of source | 232 /// instruction. An instruction can have an arbitrary number of source |
| 234 /// operands (e.g. a call instruction), and each source operand can contain 0 | 233 /// operands (e.g. a call instruction), and each source operand can contain 0 |
| 235 /// or 1 Variable (and target-specific operands could contain more than 1 | 234 /// or 1 Variable (and target-specific operands could contain more than 1 |
| 236 /// Variable). All the variables in an instruction are conceptually flattened | 235 /// Variable). All the variables in an instruction are conceptually flattened |
| 237 /// and each variable is mapped to one bit position of the LiveRangesEnded bit | 236 /// and each variable is mapped to one bit position of the LiveRangesEnded bit |
| 238 /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are | 237 /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are |
| 239 /// tracked this way. | 238 /// tracked this way. |
| 240 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry | 239 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } | 658 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } |
| 660 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, | 659 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
| 661 Liveness *Liveness); | 660 Liveness *Liveness); |
| 662 Inst *lower(Cfg *Func); | 661 Inst *lower(Cfg *Func); |
| 663 bool isMemoryWrite() const override { return false; } | 662 bool isMemoryWrite() const override { return false; } |
| 664 void dump(const Cfg *Func) const override; | 663 void dump(const Cfg *Func) const override; |
| 665 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } | 664 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } |
| 666 | 665 |
| 667 private: | 666 private: |
| 668 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); | 667 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); |
| 669 void destroy(Cfg *Func) override { | 668 void destroy(Cfg *Func) override { Inst::destroy(Func); } |
| 670 Func->deallocateArrayOf<CfgNode *>(Labels); | |
| 671 Inst::destroy(Func); | |
| 672 } | |
| 673 | 669 |
| 674 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, | 670 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, |
| 675 /// but the Phi instruction is created before InEdges[] is available, so it's | 671 /// but the Phi instruction is created before InEdges[] is available, so it's |
| 676 /// more complicated to share the list. | 672 /// more complicated to share the list. |
| 677 CfgNode **Labels; | 673 CfgVector<CfgNode *> Labels; |
| 678 }; | 674 }; |
| 679 | 675 |
| 680 /// Ret instruction. The return value is captured in getSrc(0), but if there is | 676 /// Ret instruction. The return value is captured in getSrc(0), but if there is |
| 681 /// no return value (void-type function), then getSrcSize()==0 and | 677 /// no return value (void-type function), then getSrcSize()==0 and |
| 682 /// hasRetValue()==false. | 678 /// hasRetValue()==false. |
| 683 class InstRet : public InstHighLevel { | 679 class InstRet : public InstHighLevel { |
| 684 InstRet() = delete; | 680 InstRet() = delete; |
| 685 InstRet(const InstRet &) = delete; | 681 InstRet(const InstRet &) = delete; |
| 686 InstRet &operator=(const InstRet &) = delete; | 682 InstRet &operator=(const InstRet &) = delete; |
| 687 | 683 |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 | 1146 |
| 1151 inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; } | 1147 inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; } |
| 1152 | 1148 |
| 1153 inline const Inst *iteratorToInst(InstList::const_iterator Iter) { | 1149 inline const Inst *iteratorToInst(InstList::const_iterator Iter) { |
| 1154 return &*Iter; | 1150 return &*Iter; |
| 1155 } | 1151 } |
| 1156 | 1152 |
| 1157 } // end of namespace Ice | 1153 } // end of namespace Ice |
| 1158 | 1154 |
| 1159 #endif // SUBZERO_SRC_ICEINST_H | 1155 #endif // SUBZERO_SRC_ICEINST_H |
| OLD | NEW |