OLD | NEW |
1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// | 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- 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 // This file declares the Operand class and its target-independent | 10 // This file declares the Operand class and its target-independent |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 private: | 74 private: |
75 Operand(const Operand &) LLVM_DELETED_FUNCTION; | 75 Operand(const Operand &) LLVM_DELETED_FUNCTION; |
76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION; | 76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION; |
77 }; | 77 }; |
78 | 78 |
79 // Constant is the abstract base class for constants. All | 79 // Constant is the abstract base class for constants. All |
80 // constants are allocated from a global arena and are pooled. | 80 // constants are allocated from a global arena and are pooled. |
81 class Constant : public Operand { | 81 class Constant : public Operand { |
82 public: | 82 public: |
83 uint32_t getPoolEntryID() const { return PoolEntryID; } | 83 uint32_t getPoolEntryID() const { return PoolEntryID; } |
84 virtual void emit(const Cfg *Func) const = 0; | 84 virtual void emit(const Cfg *Func) const { emit(Func->getContext()); } |
85 virtual void dump(const Cfg *Func) const = 0; | 85 virtual void dump(const Cfg *Func) const { dump(Func->getContext()); } |
| 86 virtual void emit(GlobalContext *Ctx) const = 0; |
| 87 virtual void dump(GlobalContext *Ctx) const = 0; |
86 | 88 |
87 static bool classof(const Operand *Operand) { | 89 static bool classof(const Operand *Operand) { |
88 OperandKind Kind = Operand->getKind(); | 90 OperandKind Kind = Operand->getKind(); |
89 return Kind >= kConst_Base && Kind <= kConst_Num; | 91 return Kind >= kConst_Base && Kind <= kConst_Num; |
90 } | 92 } |
91 | 93 |
92 protected: | 94 protected: |
93 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) | 95 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) |
94 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { | 96 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { |
95 Vars = NULL; | 97 Vars = NULL; |
(...skipping 13 matching lines...) Expand all Loading... |
109 // ConstantPrimitive<> wraps a primitive type. | 111 // ConstantPrimitive<> wraps a primitive type. |
110 template <typename T, Operand::OperandKind K> | 112 template <typename T, Operand::OperandKind K> |
111 class ConstantPrimitive : public Constant { | 113 class ConstantPrimitive : public Constant { |
112 public: | 114 public: |
113 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value, | 115 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value, |
114 uint32_t PoolEntryID) { | 116 uint32_t PoolEntryID) { |
115 return new (Ctx->allocate<ConstantPrimitive>()) | 117 return new (Ctx->allocate<ConstantPrimitive>()) |
116 ConstantPrimitive(Ty, Value, PoolEntryID); | 118 ConstantPrimitive(Ty, Value, PoolEntryID); |
117 } | 119 } |
118 T getValue() const { return Value; } | 120 T getValue() const { return Value; } |
119 virtual void emit(const Cfg *Func) const { | 121 using Constant::emit; |
120 Ostream &Str = Func->getContext()->getStrEmit(); | 122 virtual void emit(GlobalContext *Ctx) const { |
| 123 Ostream &Str = Ctx->getStrEmit(); |
121 Str << getValue(); | 124 Str << getValue(); |
122 } | 125 } |
123 virtual void dump(const Cfg *Func) const { | 126 using Constant::dump; |
124 Ostream &Str = Func->getContext()->getStrDump(); | 127 virtual void dump(GlobalContext *Ctx) const { |
| 128 Ostream &Str = Ctx->getStrDump(); |
125 Str << getValue(); | 129 Str << getValue(); |
126 } | 130 } |
127 | 131 |
128 static bool classof(const Operand *Operand) { | 132 static bool classof(const Operand *Operand) { |
129 return Operand->getKind() == K; | 133 return Operand->getKind() == K; |
130 } | 134 } |
131 | 135 |
132 private: | 136 private: |
133 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID) | 137 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID) |
134 : Constant(K, Ty, PoolEntryID), Value(Value) {} | 138 : Constant(K, Ty, PoolEntryID), Value(Value) {} |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, | 175 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, |
172 const RelocatableTuple &Tuple, | 176 const RelocatableTuple &Tuple, |
173 uint32_t PoolEntryID) { | 177 uint32_t PoolEntryID) { |
174 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( | 178 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( |
175 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); | 179 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); |
176 } | 180 } |
177 int64_t getOffset() const { return Offset; } | 181 int64_t getOffset() const { return Offset; } |
178 IceString getName() const { return Name; } | 182 IceString getName() const { return Name; } |
179 void setSuppressMangling(bool Value) { SuppressMangling = Value; } | 183 void setSuppressMangling(bool Value) { SuppressMangling = Value; } |
180 bool getSuppressMangling() const { return SuppressMangling; } | 184 bool getSuppressMangling() const { return SuppressMangling; } |
181 virtual void emit(const Cfg *Func) const; | 185 using Constant::emit; |
182 virtual void dump(const Cfg *Func) const; | 186 using Constant::dump; |
| 187 virtual void emit(GlobalContext *Ctx) const; |
| 188 virtual void dump(GlobalContext *Ctx) const; |
183 | 189 |
184 static bool classof(const Operand *Operand) { | 190 static bool classof(const Operand *Operand) { |
185 OperandKind Kind = Operand->getKind(); | 191 OperandKind Kind = Operand->getKind(); |
186 return Kind == kConstRelocatable; | 192 return Kind == kConstRelocatable; |
187 } | 193 } |
188 | 194 |
189 private: | 195 private: |
190 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name, | 196 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name, |
191 bool SuppressMangling, uint32_t PoolEntryID) | 197 bool SuppressMangling, uint32_t PoolEntryID) |
192 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), | 198 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), |
(...skipping 28 matching lines...) Expand all Loading... |
221 bool isInf() const { return Weight == Inf; } | 227 bool isInf() const { return Weight == Inf; } |
222 | 228 |
223 private: | 229 private: |
224 uint32_t Weight; | 230 uint32_t Weight; |
225 }; | 231 }; |
226 Ostream &operator<<(Ostream &Str, const RegWeight &W); | 232 Ostream &operator<<(Ostream &Str, const RegWeight &W); |
227 bool operator<(const RegWeight &A, const RegWeight &B); | 233 bool operator<(const RegWeight &A, const RegWeight &B); |
228 bool operator<=(const RegWeight &A, const RegWeight &B); | 234 bool operator<=(const RegWeight &A, const RegWeight &B); |
229 bool operator==(const RegWeight &A, const RegWeight &B); | 235 bool operator==(const RegWeight &A, const RegWeight &B); |
230 | 236 |
| 237 // LiveRange is a set of instruction number intervals representing |
| 238 // a variable's live range. Generally there is one interval per basic |
| 239 // block where the variable is live, but adjacent intervals get |
| 240 // coalesced into a single interval. LiveRange also includes a |
| 241 // weight, in case e.g. we want a live range to have higher weight |
| 242 // inside a loop. |
| 243 class LiveRange { |
| 244 public: |
| 245 LiveRange() : Weight(0) {} |
| 246 |
| 247 void reset() { |
| 248 Range.clear(); |
| 249 Weight.setWeight(0); |
| 250 } |
| 251 void addSegment(int32_t Start, int32_t End); |
| 252 |
| 253 bool endsBefore(const LiveRange &Other) const; |
| 254 bool overlaps(const LiveRange &Other) const; |
| 255 bool containsValue(int32_t Value) const; |
| 256 bool isEmpty() const { return Range.empty(); } |
| 257 int32_t getStart() const { return Range.empty() ? -1 : Range.begin()->first; } |
| 258 |
| 259 RegWeight getWeight() const { return Weight; } |
| 260 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; } |
| 261 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); } |
| 262 void dump(Ostream &Str) const; |
| 263 |
| 264 // Defining USE_SET uses std::set to hold the segments instead of |
| 265 // std::list. Using std::list will be slightly faster, but is more |
| 266 // restrictive because new segments cannot be added in the middle. |
| 267 |
| 268 //#define USE_SET |
| 269 |
| 270 private: |
| 271 typedef std::pair<int32_t, int32_t> RangeElementType; |
| 272 #ifdef USE_SET |
| 273 typedef std::set<RangeElementType> RangeType; |
| 274 #else |
| 275 typedef std::list<RangeElementType> RangeType; |
| 276 #endif |
| 277 RangeType Range; |
| 278 RegWeight Weight; |
| 279 }; |
| 280 |
| 281 Ostream &operator<<(Ostream &Str, const LiveRange &L); |
| 282 |
231 // Variable represents an operand that is register-allocated or | 283 // Variable represents an operand that is register-allocated or |
232 // stack-allocated. If it is register-allocated, it will ultimately | 284 // stack-allocated. If it is register-allocated, it will ultimately |
233 // have a non-negative RegNum field. | 285 // have a non-negative RegNum field. |
234 class Variable : public Operand { | 286 class Variable : public Operand { |
235 public: | 287 public: |
236 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, | 288 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, |
237 const IceString &Name) { | 289 const IceString &Name) { |
238 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name); | 290 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name); |
239 } | 291 } |
240 | 292 |
(...skipping 15 matching lines...) Expand all Loading... |
256 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 308 void setStackOffset(int32_t Offset) { StackOffset = Offset; } |
257 | 309 |
258 static const int32_t NoRegister = -1; | 310 static const int32_t NoRegister = -1; |
259 bool hasReg() const { return getRegNum() != NoRegister; } | 311 bool hasReg() const { return getRegNum() != NoRegister; } |
260 int32_t getRegNum() const { return RegNum; } | 312 int32_t getRegNum() const { return RegNum; } |
261 void setRegNum(int32_t NewRegNum) { | 313 void setRegNum(int32_t NewRegNum) { |
262 // Regnum shouldn't be set more than once. | 314 // Regnum shouldn't be set more than once. |
263 assert(!hasReg() || RegNum == NewRegNum); | 315 assert(!hasReg() || RegNum == NewRegNum); |
264 RegNum = NewRegNum; | 316 RegNum = NewRegNum; |
265 } | 317 } |
| 318 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } |
| 319 int32_t getRegNumTmp() const { return RegNumTmp; } |
| 320 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } |
266 | 321 |
267 RegWeight getWeight() const { return Weight; } | 322 RegWeight getWeight() const { return Weight; } |
268 void setWeight(uint32_t NewWeight) { Weight = NewWeight; } | 323 void setWeight(uint32_t NewWeight) { Weight = NewWeight; } |
269 void setWeightInfinite() { Weight = RegWeight::Inf; } | 324 void setWeightInfinite() { Weight = RegWeight::Inf; } |
270 | 325 |
271 Variable *getPreferredRegister() const { return RegisterPreference; } | 326 Variable *getPreferredRegister() const { return RegisterPreference; } |
272 bool getRegisterOverlap() const { return AllowRegisterOverlap; } | 327 bool getRegisterOverlap() const { return AllowRegisterOverlap; } |
273 void setPreferredRegister(Variable *Prefer, bool Overlap) { | 328 void setPreferredRegister(Variable *Prefer, bool Overlap) { |
274 RegisterPreference = Prefer; | 329 RegisterPreference = Prefer; |
275 AllowRegisterOverlap = Overlap; | 330 AllowRegisterOverlap = Overlap; |
276 } | 331 } |
277 | 332 |
| 333 const LiveRange &getLiveRange() const { return Live; } |
| 334 void setLiveRange(const LiveRange &Range) { Live = Range; } |
| 335 void resetLiveRange() { Live.reset(); } |
| 336 void addLiveRange(int32_t Start, int32_t End, uint32_t WeightDelta) { |
| 337 assert(WeightDelta != RegWeight::Inf); |
| 338 Live.addSegment(Start, End); |
| 339 if (Weight.isInf()) |
| 340 Live.setWeight(RegWeight::Inf); |
| 341 else |
| 342 Live.addWeight(WeightDelta * Weight.getWeight()); |
| 343 } |
| 344 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); } |
| 345 |
278 Variable *getLo() const { return LoVar; } | 346 Variable *getLo() const { return LoVar; } |
279 Variable *getHi() const { return HiVar; } | 347 Variable *getHi() const { return HiVar; } |
280 void setLoHi(Variable *Lo, Variable *Hi) { | 348 void setLoHi(Variable *Lo, Variable *Hi) { |
281 assert(LoVar == NULL); | 349 assert(LoVar == NULL); |
282 assert(HiVar == NULL); | 350 assert(HiVar == NULL); |
283 LoVar = Lo; | 351 LoVar = Lo; |
284 HiVar = Hi; | 352 HiVar = Hi; |
285 } | 353 } |
286 // Creates a temporary copy of the variable with a different type. | 354 // Creates a temporary copy of the variable with a different type. |
287 // Used primarily for syntactic correctness of textual assembly | 355 // Used primarily for syntactic correctness of textual assembly |
288 // emission. Note that only basic information is copied, in | 356 // emission. Note that only basic information is copied, in |
289 // particular not DefInst, IsArgument, Weight, RegisterPreference, | 357 // particular not DefInst, IsArgument, Weight, RegisterPreference, |
290 // AllowRegisterOverlap, LoVar, HiVar, VarsReal. | 358 // AllowRegisterOverlap, LoVar, HiVar, VarsReal. |
291 Variable asType(Type Ty); | 359 Variable asType(Type Ty); |
292 | 360 |
293 virtual void emit(const Cfg *Func) const; | 361 virtual void emit(const Cfg *Func) const; |
294 virtual void dump(const Cfg *Func) const; | 362 virtual void dump(const Cfg *Func) const; |
295 | 363 |
296 static bool classof(const Operand *Operand) { | 364 static bool classof(const Operand *Operand) { |
297 return Operand->getKind() == kVariable; | 365 return Operand->getKind() == kVariable; |
298 } | 366 } |
299 | 367 |
300 // The destructor is public because of the asType() method. | 368 // The destructor is public because of the asType() method. |
301 virtual ~Variable() {} | 369 virtual ~Variable() {} |
302 | 370 |
303 private: | 371 private: |
304 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name) | 372 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name) |
305 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL), | 373 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL), |
306 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister), | 374 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister), |
307 Weight(1), RegisterPreference(NULL), AllowRegisterOverlap(false), | 375 RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL), |
308 LoVar(NULL), HiVar(NULL) { | 376 AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) { |
309 Vars = VarsReal; | 377 Vars = VarsReal; |
310 Vars[0] = this; | 378 Vars[0] = this; |
311 NumVars = 1; | 379 NumVars = 1; |
312 } | 380 } |
313 Variable(const Variable &) LLVM_DELETED_FUNCTION; | 381 Variable(const Variable &) LLVM_DELETED_FUNCTION; |
314 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; | 382 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; |
315 // Number is unique across all variables, and is used as a | 383 // Number is unique across all variables, and is used as a |
316 // (bit)vector index for liveness analysis. | 384 // (bit)vector index for liveness analysis. |
317 const SizeT Number; | 385 const SizeT Number; |
318 // Name is optional. | 386 // Name is optional. |
319 const IceString Name; | 387 const IceString Name; |
320 // DefInst is the instruction that produces this variable as its | 388 // DefInst is the instruction that produces this variable as its |
321 // dest. | 389 // dest. |
322 Inst *DefInst; | 390 Inst *DefInst; |
323 // DefNode is the node where this variable was produced, and is | 391 // DefNode is the node where this variable was produced, and is |
324 // reset to NULL if it is used outside that node. This is used for | 392 // reset to NULL if it is used outside that node. This is used for |
325 // detecting isMultiblockLife(). TODO: Collapse this to a single | 393 // detecting isMultiblockLife(). TODO: Collapse this to a single |
326 // bit and use a separate pass to calculate the values across the | 394 // bit and use a separate pass to calculate the values across the |
327 // Cfg. This saves space in the Variable, and removes the fragility | 395 // Cfg. This saves space in the Variable, and removes the fragility |
328 // of incrementally computing and maintaining the information. | 396 // of incrementally computing and maintaining the information. |
329 const CfgNode *DefNode; | 397 const CfgNode *DefNode; |
330 bool IsArgument; | 398 bool IsArgument; |
331 // StackOffset is the canonical location on stack (only if | 399 // StackOffset is the canonical location on stack (only if |
332 // RegNum<0 || IsArgument). | 400 // RegNum<0 || IsArgument). |
333 int32_t StackOffset; | 401 int32_t StackOffset; |
334 // RegNum is the allocated register, or NoRegister if it isn't | 402 // RegNum is the allocated register, or NoRegister if it isn't |
335 // register-allocated. | 403 // register-allocated. |
336 int32_t RegNum; | 404 int32_t RegNum; |
| 405 // RegNumTmp is the tentative assignment during register allocation. |
| 406 int32_t RegNumTmp; |
337 RegWeight Weight; // Register allocation priority | 407 RegWeight Weight; // Register allocation priority |
338 // RegisterPreference says that if possible, the register allocator | 408 // RegisterPreference says that if possible, the register allocator |
339 // should prefer the register that was assigned to this linked | 409 // should prefer the register that was assigned to this linked |
340 // variable. It also allows a spill slot to share its stack | 410 // variable. It also allows a spill slot to share its stack |
341 // location with another variable, if that variable does not get | 411 // location with another variable, if that variable does not get |
342 // register-allocated and therefore has a stack location. | 412 // register-allocated and therefore has a stack location. |
343 Variable *RegisterPreference; | 413 Variable *RegisterPreference; |
344 // AllowRegisterOverlap says that it is OK to honor | 414 // AllowRegisterOverlap says that it is OK to honor |
345 // RegisterPreference and "share" a register even if the two live | 415 // RegisterPreference and "share" a register even if the two live |
346 // ranges overlap. | 416 // ranges overlap. |
347 bool AllowRegisterOverlap; | 417 bool AllowRegisterOverlap; |
| 418 LiveRange Live; |
348 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When | 419 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When |
349 // lowering from I64 to I32 on a 32-bit architecture, we split the | 420 // lowering from I64 to I32 on a 32-bit architecture, we split the |
350 // variable into two machine-size pieces. LoVar is the low-order | 421 // variable into two machine-size pieces. LoVar is the low-order |
351 // machine-size portion, and HiVar is the remaining high-order | 422 // machine-size portion, and HiVar is the remaining high-order |
352 // portion. TODO: It's wasteful to penalize all variables on all | 423 // portion. TODO: It's wasteful to penalize all variables on all |
353 // targets this way; use a sparser representation. It's also | 424 // targets this way; use a sparser representation. It's also |
354 // wasteful for a 64-bit target. | 425 // wasteful for a 64-bit target. |
355 Variable *LoVar; | 426 Variable *LoVar; |
356 Variable *HiVar; | 427 Variable *HiVar; |
357 // VarsReal (and Operand::Vars) are set up such that Vars[0] == | 428 // VarsReal (and Operand::Vars) are set up such that Vars[0] == |
358 // this. | 429 // this. |
359 Variable *VarsReal[1]; | 430 Variable *VarsReal[1]; |
360 }; | 431 }; |
361 | 432 |
362 } // end of namespace Ice | 433 } // end of namespace Ice |
363 | 434 |
364 #endif // SUBZERO_SRC_ICEOPERAND_H | 435 #endif // SUBZERO_SRC_ICEOPERAND_H |
OLD | NEW |