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 RR_MayHaveRegister, | |
| 413 RR_MustHaveRegister, | |
| 414 RR_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 Cfg *Func) const; |
| 458 void setWeight(uint32_t NewWeight) { Weight = RegWeight(NewWeight); } | 455 |
| 459 void setWeightInfinite() { setWeight(RegWeight::Inf); } | 456 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; } |
| 457 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; } | |
| 458 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; } | |
| 459 bool mustNotHaveReg() const { | |
| 460 return RegRequirement == RR_MustNotHaveRegister; | |
| 461 } | |
| 460 | 462 |
| 461 LiveRange &getLiveRange() { return Live; } | 463 LiveRange &getLiveRange() { return Live; } |
| 462 const LiveRange &getLiveRange() const { return Live; } | 464 const LiveRange &getLiveRange() const { return Live; } |
| 463 void setLiveRange(const LiveRange &Range) { Live = Range; } | 465 void setLiveRange(const LiveRange &Range) { Live = Range; } |
| 464 void resetLiveRange() { Live.reset(); } | 466 void resetLiveRange() { Live.reset(); } |
| 465 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { | 467 void addLiveRange(InstNumberT Start, InstNumberT End) { |
| 466 assert(!getIgnoreLiveness()); | 468 assert(!getIgnoreLiveness()); |
| 467 assert(WeightDelta != RegWeight::Inf); | |
| 468 Live.addSegment(Start, End); | 469 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 } | 470 } |
| 477 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } | 471 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } |
| 478 void untrimLiveRange() { Live.untrim(); } | 472 void untrimLiveRange() { Live.untrim(); } |
| 479 bool rangeEndsBefore(const Variable *Other) const { | 473 bool rangeEndsBefore(const Variable *Other) const { |
| 480 return Live.endsBefore(Other->Live); | 474 return Live.endsBefore(Other->Live); |
| 481 } | 475 } |
| 482 bool rangeOverlaps(const Variable *Other) const { | 476 bool rangeOverlaps(const Variable *Other) const { |
| 483 const bool UseTrimmed = true; | 477 const bool UseTrimmed = true; |
| 484 return Live.overlaps(Other->Live, UseTrimmed); | 478 return Live.overlaps(Other->Live, UseTrimmed); |
| 485 } | 479 } |
| 486 bool rangeOverlapsStart(const Variable *Other) const { | 480 bool rangeOverlapsStart(const Variable *Other) const { |
| 487 const bool UseTrimmed = true; | 481 const bool UseTrimmed = true; |
| 488 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); | 482 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); |
| 489 } | 483 } |
| 490 | 484 |
| 491 Variable *getLo() const { return LoVar; } | 485 Variable *getLo() const { return LoVar; } |
| 492 Variable *getHi() const { return HiVar; } | 486 Variable *getHi() const { return HiVar; } |
| 493 void setLoHi(Variable *Lo, Variable *Hi) { | 487 void setLoHi(Variable *Lo, Variable *Hi) { |
| 494 assert(LoVar == nullptr); | 488 assert(LoVar == nullptr); |
| 495 assert(HiVar == nullptr); | 489 assert(HiVar == nullptr); |
| 496 LoVar = Lo; | 490 LoVar = Lo; |
| 497 HiVar = Hi; | 491 HiVar = Hi; |
| 498 } | 492 } |
| 499 /// Creates a temporary copy of the variable with a different type. | 493 /// Creates a temporary copy of the variable with a different type. |
| 500 /// Used primarily for syntactic correctness of textual assembly | 494 /// Used primarily for syntactic correctness of textual assembly |
| 501 /// emission. Note that only basic information is copied, in | 495 /// emission. Note that only basic information is copied, in |
| 502 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness, | 496 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness, |
| 503 /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. | 497 /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. |
|
jvoung (off chromium)
2015/08/28 20:31:45
can remove Weight field comment too
ascull
2015/08/28 21:22:36
Done.
| |
| 504 Variable *asType(Type Ty); | 498 Variable *asType(Type Ty); |
| 505 | 499 |
| 506 void emit(const Cfg *Func) const override; | 500 void emit(const Cfg *Func) const override; |
| 507 using Operand::dump; | 501 using Operand::dump; |
| 508 void dump(const Cfg *Func, Ostream &Str) const override; | 502 void dump(const Cfg *Func, Ostream &Str) const override; |
| 509 | 503 |
| 510 /// Return reg num of base register, if different from stack/frame register. | 504 /// Return reg num of base register, if different from stack/frame register. |
| 511 virtual int32_t getBaseRegNum() const { return NoRegister; } | 505 virtual int32_t getBaseRegNum() const { return NoRegister; } |
| 512 | 506 |
| 513 static bool classof(const Operand *Operand) { | 507 static bool classof(const Operand *Operand) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 533 /// reserved for the stack pointer. | 527 /// reserved for the stack pointer. |
| 534 bool IgnoreLiveness = false; | 528 bool IgnoreLiveness = false; |
| 535 /// StackOffset is the canonical location on stack (only if | 529 /// StackOffset is the canonical location on stack (only if |
| 536 /// RegNum==NoRegister || IsArgument). | 530 /// RegNum==NoRegister || IsArgument). |
| 537 int32_t StackOffset = 0; | 531 int32_t StackOffset = 0; |
| 538 /// RegNum is the allocated register, or NoRegister if it isn't | 532 /// RegNum is the allocated register, or NoRegister if it isn't |
| 539 /// register-allocated. | 533 /// register-allocated. |
| 540 int32_t RegNum = NoRegister; | 534 int32_t RegNum = NoRegister; |
| 541 /// RegNumTmp is the tentative assignment during register allocation. | 535 /// RegNumTmp is the tentative assignment during register allocation. |
| 542 int32_t RegNumTmp = NoRegister; | 536 int32_t RegNumTmp = NoRegister; |
| 543 RegWeight Weight = RegWeight(1); // Register allocation priority | 537 /// \name Register allocation priority |
| 538 /// @{ | |
| 539 RegRequirement RegRequirement = RR_MayHaveRegister; | |
| 540 /// @} | |
| 544 LiveRange Live; | 541 LiveRange Live; |
| 545 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When | 542 // 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 | 543 // 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 | 544 // variable into two machine-size pieces. LoVar is the low-order |
| 548 // machine-size portion, and HiVar is the remaining high-order | 545 // machine-size portion, and HiVar is the remaining high-order |
| 549 // portion. TODO: It's wasteful to penalize all variables on all | 546 // portion. TODO: It's wasteful to penalize all variables on all |
| 550 // targets this way; use a sparser representation. It's also | 547 // targets this way; use a sparser representation. It's also |
| 551 // wasteful for a 64-bit target. | 548 // wasteful for a 64-bit target. |
| 552 Variable *LoVar = nullptr; | 549 Variable *LoVar = nullptr; |
| 553 Variable *HiVar = nullptr; | 550 Variable *HiVar = nullptr; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 578 }; | 575 }; |
| 579 enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock }; | 576 enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock }; |
| 580 VariableTracking() = default; | 577 VariableTracking() = default; |
| 581 VariableTracking(const VariableTracking &) = default; | 578 VariableTracking(const VariableTracking &) = default; |
| 582 MultiDefState getMultiDef() const { return MultiDef; } | 579 MultiDefState getMultiDef() const { return MultiDef; } |
| 583 MultiBlockState getMultiBlock() const { return MultiBlock; } | 580 MultiBlockState getMultiBlock() const { return MultiBlock; } |
| 584 const Inst *getFirstDefinition() const; | 581 const Inst *getFirstDefinition() const; |
| 585 const Inst *getSingleDefinition() const; | 582 const Inst *getSingleDefinition() const; |
| 586 const InstDefList &getLatterDefinitions() const { return Definitions; } | 583 const InstDefList &getLatterDefinitions() const { return Definitions; } |
| 587 CfgNode *getNode() const { return SingleUseNode; } | 584 CfgNode *getNode() const { return SingleUseNode; } |
| 585 uint32_t getUseWeight() const { return UseWeight; } | |
| 588 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node, | 586 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node, |
| 589 bool IsImplicit); | 587 bool IsImplicit); |
| 590 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node); | 588 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node); |
| 591 | 589 |
| 592 private: | 590 private: |
| 593 MultiDefState MultiDef = MDS_Unknown; | 591 MultiDefState MultiDef = MDS_Unknown; |
| 594 MultiBlockState MultiBlock = MBS_Unknown; | 592 MultiBlockState MultiBlock = MBS_Unknown; |
| 595 CfgNode *SingleUseNode = nullptr; | 593 CfgNode *SingleUseNode = nullptr; |
| 596 CfgNode *SingleDefNode = nullptr; | 594 CfgNode *SingleDefNode = nullptr; |
| 597 /// All definitions of the variable are collected here, in increasing | 595 /// All definitions of the variable are collected here, in increasing |
| 598 /// order of instruction number. | 596 /// order of instruction number. |
| 599 InstDefList Definitions; /// Only used if Kind==VMK_All | 597 InstDefList Definitions; /// Only used if Kind==VMK_All |
| 600 const Inst *FirstOrSingleDefinition = | 598 const Inst *FirstOrSingleDefinition = |
| 601 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All | 599 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All |
| 600 uint32_t UseWeight = 0; | |
| 602 }; | 601 }; |
| 603 | 602 |
| 604 /// VariablesMetadata analyzes and summarizes the metadata for the | 603 /// VariablesMetadata analyzes and summarizes the metadata for the complete set |
| 605 /// complete set of Variables. | 604 /// of Variables. |
| 606 class VariablesMetadata { | 605 class VariablesMetadata { |
| 607 VariablesMetadata() = delete; | 606 VariablesMetadata() = delete; |
| 608 VariablesMetadata(const VariablesMetadata &) = delete; | 607 VariablesMetadata(const VariablesMetadata &) = delete; |
| 609 VariablesMetadata &operator=(const VariablesMetadata &) = delete; | 608 VariablesMetadata &operator=(const VariablesMetadata &) = delete; |
| 610 | 609 |
| 611 public: | 610 public: |
| 612 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {} | 611 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {} |
| 613 /// Initialize the state by traversing all instructions/variables in | 612 /// Initialize the state by traversing all instructions/variables in |
| 614 /// the CFG. | 613 /// the CFG. |
| 615 void init(MetadataKind TrackingKind); | 614 void init(MetadataKind TrackingKind); |
| 616 /// Add a single node. This is called by init(), and can be called | 615 /// Add a single node. This is called by init(), and can be called |
| 617 /// incrementally from elsewhere, e.g. after edge-splitting. | 616 /// incrementally from elsewhere, e.g. after edge-splitting. |
| 618 void addNode(CfgNode *Node); | 617 void addNode(CfgNode *Node); |
| 619 /// Returns whether the given Variable is tracked in this object. It | 618 /// Returns whether the given Variable is tracked in this object. It should |
| 620 /// should only return false if changes were made to the CFG after | 619 /// only return false if changes were made to the CFG after running init(), in |
| 621 /// running init(), in which case the state is stale and the results | 620 /// which case the state is stale and the results shouldn't be trusted (but it |
| 622 /// shouldn't be trusted (but it may be OK e.g. for dumping). | 621 /// may be OK e.g. for dumping). |
| 623 bool isTracked(const Variable *Var) const { | 622 bool isTracked(const Variable *Var) const { |
| 624 return Var->getIndex() < Metadata.size(); | 623 return Var->getIndex() < Metadata.size(); |
| 625 } | 624 } |
| 626 | 625 |
| 627 /// Returns whether the given Variable has multiple definitions. | 626 /// Returns whether the given Variable has multiple definitions. |
| 628 bool isMultiDef(const Variable *Var) const; | 627 bool isMultiDef(const Variable *Var) const; |
| 629 /// Returns the first definition instruction of the given Variable. | 628 /// Returns the first definition instruction of the given Variable. This is |
| 630 /// This is only valid for variables whose definitions are all within | 629 /// only valid for variables whose definitions are all within the same block, |
| 631 /// the same block, e.g. T after the lowered sequence "T=B; T+=C; | 630 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which |
| 632 /// A=T", for which getFirstDefinition(T) would return the "T=B" | 631 /// getFirstDefinition(T) would return the "T=B" instruction. For variables |
| 633 /// instruction. For variables with definitions span multiple | 632 /// with definitions span multiple blocks, nullptr is returned. |
| 634 /// blocks, nullptr is returned. | |
| 635 const Inst *getFirstDefinition(const Variable *Var) const; | 633 const Inst *getFirstDefinition(const Variable *Var) const; |
| 636 /// Returns the definition instruction of the given Variable, when | 634 /// Returns the definition instruction of the given Variable, when |
| 637 /// the variable has exactly one definition. Otherwise, nullptr is | 635 /// the variable has exactly one definition. Otherwise, nullptr is |
| 638 /// returned. | 636 /// returned. |
| 639 const Inst *getSingleDefinition(const Variable *Var) const; | 637 const Inst *getSingleDefinition(const Variable *Var) const; |
| 640 /// Returns the list of all definition instructions of the given | 638 /// Returns the list of all definition instructions of the given Variable. |
| 641 /// Variable. | |
| 642 const InstDefList &getLatterDefinitions(const Variable *Var) const; | 639 const InstDefList &getLatterDefinitions(const Variable *Var) const; |
| 643 | 640 |
| 644 /// Returns whether the given Variable is live across multiple | 641 /// Returns whether the given Variable is live across multiple |
| 645 /// blocks. Mainly, this is used to partition Variables into | 642 /// blocks. Mainly, this is used to partition Variables into |
| 646 /// single-block versus multi-block sets for leveraging sparsity in | 643 /// single-block versus multi-block sets for leveraging sparsity in |
| 647 /// liveness analysis, and for implementing simple stack slot | 644 /// liveness analysis, and for implementing simple stack slot |
| 648 /// coalescing. As a special case, function arguments are always | 645 /// coalescing. As a special case, function arguments are always |
| 649 /// considered multi-block because they are live coming into the | 646 /// considered multi-block because they are live coming into the |
| 650 /// entry block. | 647 /// entry block. |
| 651 bool isMultiBlock(const Variable *Var) const; | 648 bool isMultiBlock(const Variable *Var) const; |
| 652 /// Returns the node that the given Variable is used in, assuming | 649 /// Returns the node that the given Variable is used in, assuming |
| 653 /// isMultiBlock() returns false. Otherwise, nullptr is returned. | 650 /// isMultiBlock() returns false. Otherwise, nullptr is returned. |
| 654 CfgNode *getLocalUseNode(const Variable *Var) const; | 651 CfgNode *getLocalUseNode(const Variable *Var) const; |
| 655 | 652 |
| 653 /// Returns the total use weight computed as the sum of uses multiplied by a | |
| 654 /// loop nest depth facter for each use. | |
|
jvoung (off chromium)
2015/08/28 20:31:45
facter -> factor
ascull
2015/08/28 21:22:36
Done.
| |
| 655 uint32_t getUseWeight(const Variable *Var) const; | |
| 656 | |
| 656 private: | 657 private: |
| 657 const Cfg *Func; | 658 const Cfg *Func; |
| 658 MetadataKind Kind; | 659 MetadataKind Kind; |
| 659 std::vector<VariableTracking> Metadata; | 660 std::vector<VariableTracking> Metadata; |
| 660 const static InstDefList NoDefinitions; | 661 const static InstDefList NoDefinitions; |
| 661 }; | 662 }; |
| 662 | 663 |
| 663 } // end of namespace Ice | 664 } // end of namespace Ice |
| 664 | 665 |
| 665 #endif // SUBZERO_SRC_ICEOPERAND_H | 666 #endif // SUBZERO_SRC_ICEOPERAND_H |
| OLD | NEW |