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 |