| OLD | NEW |
| 1 //===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===// | 1 //===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===// |
| 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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 Dest = Source; | 558 Dest = Source; |
| 559 // Instead of std::sort, we could do a bucket sort with log2(alignment) as | 559 // Instead of std::sort, we could do a bucket sort with log2(alignment) as |
| 560 // the buckets, if performance is an issue. | 560 // the buckets, if performance is an issue. |
| 561 std::sort(Dest.begin(), Dest.end(), | 561 std::sort(Dest.begin(), Dest.end(), |
| 562 [this](const Variable *V1, const Variable *V2) { | 562 [this](const Variable *V1, const Variable *V2) { |
| 563 return typeWidthInBytesOnStack(V1->getType()) > | 563 return typeWidthInBytesOnStack(V1->getType()) > |
| 564 typeWidthInBytesOnStack(V2->getType()); | 564 typeWidthInBytesOnStack(V2->getType()); |
| 565 }); | 565 }); |
| 566 } | 566 } |
| 567 | 567 |
| 568 namespace { | |
| 569 bool mightHaveStackSlot(const Variable *Var, const BitVector &IsVarReferenced) { | |
| 570 if (!IsVarReferenced[Var->getIndex()]) | |
| 571 return false; | |
| 572 if (Var->hasReg()) | |
| 573 return false; | |
| 574 return true; | |
| 575 } | |
| 576 } // end of anonymous namespace | |
| 577 | |
| 578 void TargetLowering::getVarStackSlotParams( | 568 void TargetLowering::getVarStackSlotParams( |
| 579 VarList &SortedSpilledVariables, SmallBitVector &RegsUsed, | 569 VarList &SortedSpilledVariables, SmallBitVector &RegsUsed, |
| 580 size_t *GlobalsSize, size_t *SpillAreaSizeBytes, | 570 size_t *GlobalsSize, size_t *SpillAreaSizeBytes, |
| 581 uint32_t *SpillAreaAlignmentBytes, uint32_t *LocalsSlotsAlignmentBytes, | 571 uint32_t *SpillAreaAlignmentBytes, uint32_t *LocalsSlotsAlignmentBytes, |
| 582 std::function<bool(Variable *)> TargetVarHook) { | 572 std::function<bool(Variable *)> TargetVarHook) { |
| 583 const VariablesMetadata *VMetadata = Func->getVMetadata(); | 573 const VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 584 BitVector IsVarReferenced(Func->getNumVariables()); | 574 BitVector IsVarReferenced(Func->getNumVariables()); |
| 585 for (CfgNode *Node : Func->getNodes()) { | 575 for (CfgNode *Node : Func->getNodes()) { |
| 586 for (Inst &Instr : Node->getInsts()) { | 576 for (Inst &Instr : Node->getInsts()) { |
| 587 if (Instr.isDeleted()) | 577 if (Instr.isDeleted()) |
| 588 continue; | 578 continue; |
| 589 if (const Variable *Var = Instr.getDest()) | 579 if (const Variable *Var = Instr.getDest()) |
| 590 IsVarReferenced[Var->getIndex()] = true; | 580 IsVarReferenced[Var->getIndex()] = true; |
| 591 FOREACH_VAR_IN_INST(Var, Instr) { | 581 FOREACH_VAR_IN_INST(Var, Instr) { |
| 592 IsVarReferenced[Var->getIndex()] = true; | 582 IsVarReferenced[Var->getIndex()] = true; |
| 593 } | 583 } |
| 594 } | 584 } |
| 595 } | 585 } |
| 596 | 586 |
| 597 // Find each variable Var where: | |
| 598 // - Var is actively referenced | |
| 599 // - Var does not have a register | |
| 600 // - Var's furthest ancestor through LinkedTo: Root | |
| 601 // - Root has no active references, or has a register | |
| 602 // | |
| 603 // When any such Var is found, rotate the LinkedTo tree by swapping | |
| 604 // Var->LinkedTo and Root->LinkedTo. This ensures that when Var needs a stack | |
| 605 // slot, either its LinkedTo field is nullptr, or Var->getLinkedToRoot() | |
| 606 // returns a variable with a stack slot. | |
| 607 for (Variable *Var : Func->getVariables()) { | |
| 608 if (!mightHaveStackSlot(Var, IsVarReferenced)) | |
| 609 continue; | |
| 610 if (Variable *Root = Var->getLinkedToRoot()) { | |
| 611 assert(Root->getLinkedTo() == nullptr); | |
| 612 if (mightHaveStackSlot(Root, IsVarReferenced)) { | |
| 613 // Found a "safe" root, no need to rotate the tree. | |
| 614 continue; | |
| 615 } | |
| 616 Var->setLinkedTo(nullptr); | |
| 617 Root->setLinkedTo(Var); | |
| 618 } | |
| 619 } | |
| 620 | |
| 621 // If SimpleCoalescing is false, each variable without a register gets its | 587 // If SimpleCoalescing is false, each variable without a register gets its |
| 622 // own unique stack slot, which leads to large stack frames. If | 588 // own unique stack slot, which leads to large stack frames. If |
| 623 // SimpleCoalescing is true, then each "global" variable without a register | 589 // SimpleCoalescing is true, then each "global" variable without a register |
| 624 // gets its own slot, but "local" variable slots are reused across basic | 590 // gets its own slot, but "local" variable slots are reused across basic |
| 625 // blocks. E.g., if A and B are local to block 1 and C is local to block 2, | 591 // blocks. E.g., if A and B are local to block 1 and C is local to block 2, |
| 626 // then C may share a slot with A or B. | 592 // then C may share a slot with A or B. |
| 627 // | 593 // |
| 628 // We cannot coalesce stack slots if this function calls a "returns twice" | 594 // We cannot coalesce stack slots if this function calls a "returns twice" |
| 629 // function. In that case, basic blocks may be revisited, and variables local | 595 // function. In that case, basic blocks may be revisited, and variables local |
| 630 // to those basic blocks are actually live until after the called function | 596 // to those basic blocks are actually live until after the called function |
| 631 // returns a second time. | 597 // returns a second time. |
| 632 const bool SimpleCoalescing = !callsReturnsTwice(); | 598 const bool SimpleCoalescing = !callsReturnsTwice(); |
| 633 | 599 |
| 634 CfgVector<size_t> LocalsSize(Func->getNumNodes()); | 600 CfgVector<size_t> LocalsSize(Func->getNumNodes()); |
| 635 const VarList &Variables = Func->getVariables(); | 601 const VarList &Variables = Func->getVariables(); |
| 636 VarList SpilledVariables; | 602 VarList SpilledVariables; |
| 637 for (Variable *Var : Variables) { | 603 for (Variable *Var : Variables) { |
| 638 if (Var->hasReg()) { | 604 if (Var->hasReg()) { |
| 639 // Don't consider a rematerializable variable to be an actual register use | 605 // Don't consider a rematerializable variable to be an actual register use |
| 640 // (specifically of the frame pointer). Otherwise, the prolog may decide | 606 // (specifically of the frame pointer). Otherwise, the prolog may decide |
| 641 // to save the frame pointer twice - once because of the explicit need for | 607 // to save the frame pointer twice - once because of the explicit need for |
| 642 // a frame pointer, and once because of an active use of a callee-save | 608 // a frame pointer, and once because of an active use of a callee-save |
| 643 // register. | 609 // register. |
| 644 if (!Var->isRematerializable()) | 610 if (!Var->isRematerializable()) |
| 645 RegsUsed[Var->getRegNum()] = true; | 611 RegsUsed[Var->getRegNum()] = true; |
| 646 continue; | 612 continue; |
| 647 } | 613 } |
| 648 // An argument either does not need a stack slot (if passed in a register) | 614 // An argument either does not need a stack slot (if passed in a register) |
| 649 // or already has one (if passed on the stack). | 615 // or already has one (if passed on the stack). |
| 650 if (Var->getIsArg()) | 616 if (Var->getIsArg()) { |
| 617 if (!Var->hasReg()) { |
| 618 assert(!Var->hasStackOffset()); |
| 619 Var->setHasStackOffset(); |
| 620 } |
| 651 continue; | 621 continue; |
| 622 } |
| 652 // An unreferenced variable doesn't need a stack slot. | 623 // An unreferenced variable doesn't need a stack slot. |
| 653 if (!IsVarReferenced[Var->getIndex()]) | 624 if (!IsVarReferenced[Var->getIndex()]) |
| 654 continue; | 625 continue; |
| 655 // Check a target-specific variable (it may end up sharing stack slots) and | 626 // Check a target-specific variable (it may end up sharing stack slots) and |
| 656 // not need accounting here. | 627 // not need accounting here. |
| 657 if (TargetVarHook(Var)) | 628 if (TargetVarHook(Var)) |
| 658 continue; | 629 continue; |
| 630 assert(!Var->hasStackOffset()); |
| 631 Var->setHasStackOffset(); |
| 659 SpilledVariables.push_back(Var); | 632 SpilledVariables.push_back(Var); |
| 660 } | 633 } |
| 661 | 634 |
| 662 SortedSpilledVariables.reserve(SpilledVariables.size()); | 635 SortedSpilledVariables.reserve(SpilledVariables.size()); |
| 663 sortVarsByAlignment(SortedSpilledVariables, SpilledVariables); | 636 sortVarsByAlignment(SortedSpilledVariables, SpilledVariables); |
| 664 | 637 |
| 665 for (Variable *Var : SortedSpilledVariables) { | 638 for (Variable *Var : SortedSpilledVariables) { |
| 666 size_t Increment = typeWidthInBytesOnStack(Var->getType()); | 639 size_t Increment = typeWidthInBytesOnStack(Var->getType()); |
| 667 // We have sorted by alignment, so the first variable we encounter that is | 640 // We have sorted by alignment, so the first variable we encounter that is |
| 668 // located in each area determines the max alignment for the area. | 641 // located in each area determines the max alignment for the area. |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 case TARGET_LOWERING_CLASS_FOR(X): \ | 911 case TARGET_LOWERING_CLASS_FOR(X): \ |
| 939 return ::X::createTargetHeaderLowering(Ctx); | 912 return ::X::createTargetHeaderLowering(Ctx); |
| 940 #include "SZTargets.def" | 913 #include "SZTargets.def" |
| 941 #undef SUBZERO_TARGET | 914 #undef SUBZERO_TARGET |
| 942 } | 915 } |
| 943 } | 916 } |
| 944 | 917 |
| 945 TargetHeaderLowering::~TargetHeaderLowering() = default; | 918 TargetHeaderLowering::~TargetHeaderLowering() = default; |
| 946 | 919 |
| 947 } // end of namespace Ice | 920 } // end of namespace Ice |
| OLD | NEW |