Chromium Code Reviews| 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 /// \file | 10 /// \file |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 325 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register | 325 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register |
| 326 void addWeight(uint32_t Delta) { | 326 void addWeight(uint32_t Delta) { |
| 327 if (Delta == Inf) | 327 if (Delta == Inf) |
| 328 Weight = Inf; | 328 Weight = Inf; |
| 329 else if (Weight != Inf) | 329 else if (Weight != Inf) |
| 330 Weight += Delta; | 330 Weight += Delta; |
| 331 } | 331 } |
| 332 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); } | 332 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); } |
| 333 void setWeight(uint32_t Val) { Weight = Val; } | 333 void setWeight(uint32_t Val) { Weight = Val; } |
| 334 uint32_t getWeight() const { return Weight; } | 334 uint32_t getWeight() const { return Weight; } |
| 335 bool isInf() const { return Weight == Inf; } | |
| 336 bool isZero() const { return Weight == Zero; } | |
| 337 | 335 |
| 338 private: | 336 private: |
| 339 uint32_t Weight = 0; | 337 uint32_t Weight = 0; |
| 340 }; | 338 }; |
| 341 Ostream &operator<<(Ostream &Str, const RegWeight &W); | 339 Ostream &operator<<(Ostream &Str, const RegWeight &W); |
| 342 bool operator<(const RegWeight &A, const RegWeight &B); | 340 bool operator<(const RegWeight &A, const RegWeight &B); |
| 343 bool operator<=(const RegWeight &A, const RegWeight &B); | 341 bool operator<=(const RegWeight &A, const RegWeight &B); |
| 344 bool operator==(const RegWeight &A, const RegWeight &B); | 342 bool operator==(const RegWeight &A, const RegWeight &B); |
| 345 | 343 |
| 346 /// LiveRange is a set of instruction number intervals representing | 344 /// LiveRange is a set of instruction number intervals representing |
| 347 /// a variable's live range. Generally there is one interval per basic | 345 /// a variable's live range. Generally there is one interval per basic |
| 348 /// block where the variable is live, but adjacent intervals get | 346 /// block where the variable is live, but adjacent intervals get |
| 349 /// coalesced into a single interval. LiveRange also includes a | 347 /// coalesced into a single interval. |
| 350 /// weight, in case e.g. we want a live range to have higher weight | |
| 351 /// inside a loop. | |
| 352 class LiveRange { | 348 class LiveRange { |
| 353 public: | 349 public: |
| 354 LiveRange() = default; | 350 LiveRange() = default; |
| 355 /// Special constructor for building a kill set. The advantage is | 351 /// Special constructor for building a kill set. The advantage is |
| 356 /// that we can reserve the right amount of space in advance. | 352 /// that we can reserve the right amount of space in advance. |
| 357 explicit LiveRange(const std::vector<InstNumberT> &Kills) { | 353 explicit LiveRange(const std::vector<InstNumberT> &Kills) { |
| 358 Range.reserve(Kills.size()); | 354 Range.reserve(Kills.size()); |
| 359 for (InstNumberT I : Kills) | 355 for (InstNumberT I : Kills) |
| 360 addSegment(I, I); | 356 addSegment(I, I); |
| 361 } | 357 } |
| 362 LiveRange(const LiveRange &) = default; | 358 LiveRange(const LiveRange &) = default; |
| 363 LiveRange &operator=(const LiveRange &) = default; | 359 LiveRange &operator=(const LiveRange &) = default; |
| 364 | 360 |
| 365 void reset() { | 361 void reset() { |
| 366 Range.clear(); | 362 Range.clear(); |
| 367 Weight.setWeight(0); | |
| 368 untrim(); | 363 untrim(); |
| 369 } | 364 } |
| 370 void addSegment(InstNumberT Start, InstNumberT End); | 365 void addSegment(InstNumberT Start, InstNumberT End); |
| 371 | 366 |
| 372 bool endsBefore(const LiveRange &Other) const; | 367 bool endsBefore(const LiveRange &Other) const; |
| 373 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const; | 368 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const; |
| 374 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const; | 369 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const; |
| 375 bool containsValue(InstNumberT Value, bool IsDest) const; | 370 bool containsValue(InstNumberT Value, bool IsDest) const; |
| 376 bool isEmpty() const { return Range.empty(); } | 371 bool isEmpty() const { return Range.empty(); } |
| 377 InstNumberT getStart() const { | 372 InstNumberT getStart() const { |
| 378 return Range.empty() ? -1 : Range.begin()->first; | 373 return Range.empty() ? -1 : Range.begin()->first; |
| 379 } | 374 } |
| 380 InstNumberT getEnd() const { | 375 InstNumberT getEnd() const { |
| 381 return Range.empty() ? -1 : Range.rbegin()->second; | 376 return Range.empty() ? -1 : Range.rbegin()->second; |
| 382 } | 377 } |
| 383 | 378 |
| 384 void untrim() { TrimmedBegin = Range.begin(); } | 379 void untrim() { TrimmedBegin = Range.begin(); } |
| 385 void trim(InstNumberT Lower); | 380 void trim(InstNumberT Lower); |
| 386 | 381 |
| 387 RegWeight getWeight() const { return Weight; } | |
| 388 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; } | |
| 389 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); } | |
| 390 void dump(Ostream &Str) const; | 382 void dump(Ostream &Str) const; |
| 391 | 383 |
| 392 private: | 384 private: |
| 393 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; | 385 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; |
| 394 /// RangeType is arena-allocated from the Cfg's allocator. | 386 /// RangeType is arena-allocated from the Cfg's allocator. |
| 395 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>> | 387 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>> |
| 396 RangeType; | 388 RangeType; |
| 397 RangeType Range; | 389 RangeType Range; |
| 398 RegWeight Weight = RegWeight(0); | |
| 399 /// TrimmedBegin is an optimization for the overlaps() computation. | 390 /// TrimmedBegin is an optimization for the overlaps() computation. |
| 400 /// Since the linear-scan algorithm always calls it as overlaps(Cur) | 391 /// Since the linear-scan algorithm always calls it as overlaps(Cur) |
| 401 /// and Cur advances monotonically according to live range start, we | 392 /// and Cur advances monotonically according to live range start, we |
| 402 /// can optimize overlaps() by ignoring all segments that end before | 393 /// can optimize overlaps() by ignoring all segments that end before |
| 403 /// the start of Cur's range. The linear-scan code enables this by | 394 /// the start of Cur's range. The linear-scan code enables this by |
| 404 /// calling trim() on the ranges of interest as Cur advances. Note | 395 /// calling trim() on the ranges of interest as Cur advances. Note |
| 405 /// that linear-scan also has to initialize TrimmedBegin at the | 396 /// that linear-scan also has to initialize TrimmedBegin at the |
| 406 /// beginning by calling untrim(). | 397 /// beginning by calling untrim(). |
| 407 RangeType::const_iterator TrimmedBegin; | 398 RangeType::const_iterator TrimmedBegin; |
| 408 }; | 399 }; |
| 409 | 400 |
| 410 Ostream &operator<<(Ostream &Str, const LiveRange &L); | 401 Ostream &operator<<(Ostream &Str, const LiveRange &L); |
| 411 | 402 |
| 412 /// Variable represents an operand that is register-allocated or | 403 /// Variable represents an operand that is register-allocated or |
| 413 /// stack-allocated. If it is register-allocated, it will ultimately | 404 /// stack-allocated. If it is register-allocated, it will ultimately |
| 414 /// have a non-negative RegNum field. | 405 /// have a non-negative RegNum field. |
| 415 class Variable : public Operand { | 406 class Variable : public Operand { |
| 416 Variable() = delete; | 407 Variable() = delete; |
| 417 Variable(const Variable &) = delete; | 408 Variable(const Variable &) = delete; |
| 418 Variable &operator=(const Variable &) = delete; | 409 Variable &operator=(const Variable &) = delete; |
| 419 | 410 |
| 411 enum RegRequirement { | |
| 412 ShouldHaveRegister, | |
| 413 MustHaveRegister, | |
| 414 MustNotHaveRegister, | |
| 415 }; | |
| 416 | |
| 420 public: | 417 public: |
| 421 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { | 418 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { |
| 422 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); | 419 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); |
| 423 } | 420 } |
| 424 | 421 |
| 425 SizeT getIndex() const { return Number; } | 422 SizeT getIndex() const { return Number; } |
| 426 IceString getName(const Cfg *Func) const; | 423 IceString getName(const Cfg *Func) const; |
| 427 void setName(Cfg *Func, const IceString &NewName) { | 424 void setName(Cfg *Func, const IceString &NewName) { |
| 428 // Make sure that the name can only be set once. | 425 // Make sure that the name can only be set once. |
| 429 assert(NameIndex == Cfg::IdentifierIndexInvalid); | 426 assert(NameIndex == Cfg::IdentifierIndexInvalid); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 447 int32_t getRegNum() const { return RegNum; } | 444 int32_t getRegNum() const { return RegNum; } |
| 448 void setRegNum(int32_t NewRegNum) { | 445 void setRegNum(int32_t NewRegNum) { |
| 449 // Regnum shouldn't be set more than once. | 446 // Regnum shouldn't be set more than once. |
| 450 assert(!hasReg() || RegNum == NewRegNum); | 447 assert(!hasReg() || RegNum == NewRegNum); |
| 451 RegNum = NewRegNum; | 448 RegNum = NewRegNum; |
| 452 } | 449 } |
| 453 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } | 450 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } |
| 454 int32_t getRegNumTmp() const { return RegNumTmp; } | 451 int32_t getRegNumTmp() const { return RegNumTmp; } |
| 455 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } | 452 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } |
| 456 | 453 |
| 457 RegWeight getWeight() const { return Weight; } | 454 RegWeight getWeight() const { |
| 458 void setWeight(uint32_t NewWeight) { Weight = RegWeight(NewWeight); } | 455 return RegWeight(mustHaveReg() ? RegWeight::Inf : mustNotHaveReg() |
| 459 void setWeightInfinite() { setWeight(RegWeight::Inf); } | 456 ? RegWeight::Zero |
| 457 : Weight); | |
| 458 } | |
| 459 void resetUses() { Weight = 0; } | |
| 460 void addUse(uint32_t Weight) { Weight += Weight; } | |
|
jvoung (off chromium)
2015/08/26 22:35:16
I'm a bit worried about the variable shadowing her
ascull
2015/08/26 22:53:49
Done.
| |
| 461 | |
| 462 void setMustHaveReg() { RegRequirement = MustHaveRegister; } | |
| 463 bool mustHaveReg() const { return RegRequirement == MustHaveRegister; } | |
| 464 void setMustNotHaveReg() { RegRequirement = MustNotHaveRegister; } | |
| 465 bool mustNotHaveReg() const { return RegRequirement == MustNotHaveRegister; } | |
| 460 | 466 |
| 461 LiveRange &getLiveRange() { return Live; } | 467 LiveRange &getLiveRange() { return Live; } |
| 462 const LiveRange &getLiveRange() const { return Live; } | 468 const LiveRange &getLiveRange() const { return Live; } |
| 463 void setLiveRange(const LiveRange &Range) { Live = Range; } | 469 void setLiveRange(const LiveRange &Range) { Live = Range; } |
| 464 void resetLiveRange() { Live.reset(); } | 470 void resetLiveRange() { |
| 465 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { | 471 Live.reset(); |
| 472 resetUses(); | |
| 473 } | |
| 474 void addLiveRange(InstNumberT Start, InstNumberT End) { | |
| 466 assert(!getIgnoreLiveness()); | 475 assert(!getIgnoreLiveness()); |
| 467 assert(WeightDelta != RegWeight::Inf); | |
| 468 Live.addSegment(Start, End); | 476 Live.addSegment(Start, End); |
| 469 if (Weight.isInf()) | |
| 470 Live.setWeight(RegWeight(RegWeight::Inf)); | |
| 471 else | |
| 472 Live.addWeight(WeightDelta * Weight.getWeight()); | |
| 473 } | |
| 474 void setLiveRangeInfiniteWeight() { | |
| 475 Live.setWeight(RegWeight(RegWeight::Inf)); | |
| 476 } | 477 } |
| 477 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } | 478 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } |
| 478 void untrimLiveRange() { Live.untrim(); } | 479 void untrimLiveRange() { Live.untrim(); } |
| 479 bool rangeEndsBefore(const Variable *Other) const { | 480 bool rangeEndsBefore(const Variable *Other) const { |
| 480 return Live.endsBefore(Other->Live); | 481 return Live.endsBefore(Other->Live); |
| 481 } | 482 } |
| 482 bool rangeOverlaps(const Variable *Other) const { | 483 bool rangeOverlaps(const Variable *Other) const { |
| 483 const bool UseTrimmed = true; | 484 const bool UseTrimmed = true; |
| 484 return Live.overlaps(Other->Live, UseTrimmed); | 485 return Live.overlaps(Other->Live, UseTrimmed); |
| 485 } | 486 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 533 /// reserved for the stack pointer. | 534 /// reserved for the stack pointer. |
| 534 bool IgnoreLiveness = false; | 535 bool IgnoreLiveness = false; |
| 535 /// StackOffset is the canonical location on stack (only if | 536 /// StackOffset is the canonical location on stack (only if |
| 536 /// RegNum==NoRegister || IsArgument). | 537 /// RegNum==NoRegister || IsArgument). |
| 537 int32_t StackOffset = 0; | 538 int32_t StackOffset = 0; |
| 538 /// RegNum is the allocated register, or NoRegister if it isn't | 539 /// RegNum is the allocated register, or NoRegister if it isn't |
| 539 /// register-allocated. | 540 /// register-allocated. |
| 540 int32_t RegNum = NoRegister; | 541 int32_t RegNum = NoRegister; |
| 541 /// RegNumTmp is the tentative assignment during register allocation. | 542 /// RegNumTmp is the tentative assignment during register allocation. |
| 542 int32_t RegNumTmp = NoRegister; | 543 int32_t RegNumTmp = NoRegister; |
| 543 RegWeight Weight = RegWeight(1); // Register allocation priority | 544 /// \name Register allocation priority |
| 545 /// @{ | |
| 546 uint32_t Weight = 0; /// Calculated by use count and loop nest depth. | |
| 547 RegRequirement RegRequirement = ShouldHaveRegister; | |
| 548 /// @} | |
| 544 LiveRange Live; | 549 LiveRange Live; |
| 545 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When | 550 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When |
| 546 // lowering from I64 to I32 on a 32-bit architecture, we split the | 551 // lowering from I64 to I32 on a 32-bit architecture, we split the |
| 547 // variable into two machine-size pieces. LoVar is the low-order | 552 // variable into two machine-size pieces. LoVar is the low-order |
| 548 // machine-size portion, and HiVar is the remaining high-order | 553 // machine-size portion, and HiVar is the remaining high-order |
| 549 // portion. TODO: It's wasteful to penalize all variables on all | 554 // portion. TODO: It's wasteful to penalize all variables on all |
| 550 // targets this way; use a sparser representation. It's also | 555 // targets this way; use a sparser representation. It's also |
| 551 // wasteful for a 64-bit target. | 556 // wasteful for a 64-bit target. |
| 552 Variable *LoVar = nullptr; | 557 Variable *LoVar = nullptr; |
| 553 Variable *HiVar = nullptr; | 558 Variable *HiVar = nullptr; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 private: | 661 private: |
| 657 const Cfg *Func; | 662 const Cfg *Func; |
| 658 MetadataKind Kind; | 663 MetadataKind Kind; |
| 659 std::vector<VariableTracking> Metadata; | 664 std::vector<VariableTracking> Metadata; |
| 660 const static InstDefList NoDefinitions; | 665 const static InstDefList NoDefinitions; |
| 661 }; | 666 }; |
| 662 | 667 |
| 663 } // end of namespace Ice | 668 } // end of namespace Ice |
| 664 | 669 |
| 665 #endif // SUBZERO_SRC_ICEOPERAND_H | 670 #endif // SUBZERO_SRC_ICEOPERAND_H |
| OLD | NEW |