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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 // coalesced into a single interval. LiveRange also includes a | 296 // coalesced into a single interval. LiveRange also includes a |
297 // weight, in case e.g. we want a live range to have higher weight | 297 // weight, in case e.g. we want a live range to have higher weight |
298 // inside a loop. | 298 // inside a loop. |
299 class LiveRange { | 299 class LiveRange { |
300 public: | 300 public: |
301 LiveRange() : Weight(0), IsNonpoints(false) {} | 301 LiveRange() : Weight(0), IsNonpoints(false) {} |
302 | 302 |
303 void reset() { | 303 void reset() { |
304 Range.clear(); | 304 Range.clear(); |
305 Weight.setWeight(0); | 305 Weight.setWeight(0); |
| 306 untrim(); |
306 IsNonpoints = false; | 307 IsNonpoints = false; |
307 } | 308 } |
308 void addSegment(InstNumberT Start, InstNumberT End); | 309 void addSegment(InstNumberT Start, InstNumberT End); |
309 | 310 |
310 bool endsBefore(const LiveRange &Other) const; | 311 bool endsBefore(const LiveRange &Other) const; |
311 bool overlaps(const LiveRange &Other) const; | 312 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const; |
312 bool overlaps(InstNumberT OtherBegin) const; | 313 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const; |
313 bool containsValue(InstNumberT Value) const; | 314 bool containsValue(InstNumberT Value) const; |
314 bool isEmpty() const { return Range.empty(); } | 315 bool isEmpty() const { return Range.empty(); } |
| 316 bool isNonpoints() const { return IsNonpoints; } |
315 InstNumberT getStart() const { | 317 InstNumberT getStart() const { |
316 return Range.empty() ? -1 : Range.begin()->first; | 318 return Range.empty() ? -1 : Range.begin()->first; |
317 } | 319 } |
318 | 320 |
| 321 void untrim() { TrimmedBegin = Range.begin(); } |
| 322 void trim(InstNumberT Lower); |
| 323 |
319 RegWeight getWeight() const { return Weight; } | 324 RegWeight getWeight() const { return Weight; } |
320 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; } | 325 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; } |
321 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); } | 326 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); } |
322 void dump(Ostream &Str) const; | 327 void dump(Ostream &Str) const; |
323 | 328 |
324 // Defining USE_SET uses std::set to hold the segments instead of | 329 // Defining USE_SET uses std::set to hold the segments instead of |
325 // std::list. Using std::list will be slightly faster, but is more | 330 // std::list. Using std::list will be slightly faster, but is more |
326 // restrictive because new segments cannot be added in the middle. | 331 // restrictive because new segments cannot be added in the middle. |
327 | 332 |
328 //#define USE_SET | 333 //#define USE_SET |
329 | 334 |
330 private: | 335 private: |
331 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; | 336 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; |
332 #ifdef USE_SET | 337 #ifdef USE_SET |
333 typedef std::set<RangeElementType> RangeType; | 338 typedef std::set<RangeElementType> RangeType; |
334 #else | 339 #else |
335 typedef std::list<RangeElementType> RangeType; | 340 typedef std::list<RangeElementType> RangeType; |
336 #endif | 341 #endif |
337 RangeType Range; | 342 RangeType Range; |
338 RegWeight Weight; | 343 RegWeight Weight; |
| 344 // TrimmedBegin is an optimization for the overlaps() computation. |
| 345 // Since the linear-scan algorithm always calls it as overlaps(Cur) |
| 346 // and Cur advances monotonically according to live range start, we |
| 347 // can optimize overlaps() by ignoring all segments that end before |
| 348 // the start of Cur's range. The linear-scan code enables this by |
| 349 // calling trim() on the ranges of interest as Cur advances. Note |
| 350 // that linear-scan also has to initialize TrimmedBegin at the |
| 351 // beginning by calling untrim(). |
| 352 RangeType::const_iterator TrimmedBegin; |
339 // IsNonpoints keeps track of whether the live range contains at | 353 // IsNonpoints keeps track of whether the live range contains at |
340 // least one interval where Start!=End. If it is empty or has the | 354 // least one interval where Start!=End. If it is empty or has the |
341 // form [x,x),[y,y),...,[z,z), then overlaps(InstNumberT) is | 355 // form [x,x),[y,y),...,[z,z), then overlaps(InstNumberT) is |
342 // trivially false. | 356 // trivially false. |
343 bool IsNonpoints; | 357 bool IsNonpoints; |
344 }; | 358 }; |
345 | 359 |
346 Ostream &operator<<(Ostream &Str, const LiveRange &L); | 360 Ostream &operator<<(Ostream &Str, const LiveRange &L); |
347 | 361 |
348 // Variable represents an operand that is register-allocated or | 362 // Variable represents an operand that is register-allocated or |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 void resetLiveRange() { Live.reset(); } | 411 void resetLiveRange() { Live.reset(); } |
398 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { | 412 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { |
399 assert(WeightDelta != RegWeight::Inf); | 413 assert(WeightDelta != RegWeight::Inf); |
400 Live.addSegment(Start, End); | 414 Live.addSegment(Start, End); |
401 if (Weight.isInf()) | 415 if (Weight.isInf()) |
402 Live.setWeight(RegWeight::Inf); | 416 Live.setWeight(RegWeight::Inf); |
403 else | 417 else |
404 Live.addWeight(WeightDelta * Weight.getWeight()); | 418 Live.addWeight(WeightDelta * Weight.getWeight()); |
405 } | 419 } |
406 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); } | 420 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); } |
| 421 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } |
| 422 void untrimLiveRange() { Live.untrim(); } |
407 | 423 |
408 Variable *getLo() const { return LoVar; } | 424 Variable *getLo() const { return LoVar; } |
409 Variable *getHi() const { return HiVar; } | 425 Variable *getHi() const { return HiVar; } |
410 void setLoHi(Variable *Lo, Variable *Hi) { | 426 void setLoHi(Variable *Lo, Variable *Hi) { |
411 assert(LoVar == NULL); | 427 assert(LoVar == NULL); |
412 assert(HiVar == NULL); | 428 assert(HiVar == NULL); |
413 LoVar = Lo; | 429 LoVar = Lo; |
414 HiVar = Hi; | 430 HiVar = Hi; |
415 } | 431 } |
416 // Creates a temporary copy of the variable with a different type. | 432 // Creates a temporary copy of the variable with a different type. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef, | 518 void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef, |
503 bool IsImplicit); | 519 bool IsImplicit); |
504 void markDef(const Inst *Instr, const CfgNode *Node); | 520 void markDef(const Inst *Instr, const CfgNode *Node); |
505 | 521 |
506 private: | 522 private: |
507 VariableTracking &operator=(const VariableTracking &) = delete; | 523 VariableTracking &operator=(const VariableTracking &) = delete; |
508 MultiDefState MultiDef; | 524 MultiDefState MultiDef; |
509 MultiBlockState MultiBlock; | 525 MultiBlockState MultiBlock; |
510 const CfgNode *SingleUseNode; | 526 const CfgNode *SingleUseNode; |
511 const CfgNode *SingleDefNode; | 527 const CfgNode *SingleDefNode; |
512 // All definitions of the variable are collected here, in the order | 528 // All definitions of the variable are collected here, in increasing |
513 // encountered. Definitions in the same basic block are in | 529 // order of instruction number. |
514 // instruction order, but there's no guarantee for the basic block | |
515 // order. | |
516 InstDefList Definitions; | 530 InstDefList Definitions; |
517 }; | 531 }; |
518 | 532 |
519 // VariablesMetadata analyzes and summarizes the metadata for the | 533 // VariablesMetadata analyzes and summarizes the metadata for the |
520 // complete set of Variables. | 534 // complete set of Variables. |
521 class VariablesMetadata { | 535 class VariablesMetadata { |
522 public: | 536 public: |
523 VariablesMetadata(const Cfg *Func) : Func(Func) {} | 537 VariablesMetadata(const Cfg *Func) : Func(Func) {} |
524 // Initialize the state by traversing all instructions/variables in | 538 // Initialize the state by traversing all instructions/variables in |
525 // the CFG. | 539 // the CFG. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 const Cfg *Func; | 579 const Cfg *Func; |
566 std::vector<VariableTracking> Metadata; | 580 std::vector<VariableTracking> Metadata; |
567 const static InstDefList NoDefinitions; | 581 const static InstDefList NoDefinitions; |
568 VariablesMetadata(const VariablesMetadata &) = delete; | 582 VariablesMetadata(const VariablesMetadata &) = delete; |
569 VariablesMetadata &operator=(const VariablesMetadata &) = delete; | 583 VariablesMetadata &operator=(const VariablesMetadata &) = delete; |
570 }; | 584 }; |
571 | 585 |
572 } // end of namespace Ice | 586 } // end of namespace Ice |
573 | 587 |
574 #endif // SUBZERO_SRC_ICEOPERAND_H | 588 #endif // SUBZERO_SRC_ICEOPERAND_H |
OLD | NEW |