| 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 |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 case TARGET_LOWERING_CLASS_FOR(X): \ | 904 case TARGET_LOWERING_CLASS_FOR(X): \ |
| 939 return ::X::createTargetHeaderLowering(Ctx); | 905 return ::X::createTargetHeaderLowering(Ctx); |
| 940 #include "SZTargets.def" | 906 #include "SZTargets.def" |
| 941 #undef SUBZERO_TARGET | 907 #undef SUBZERO_TARGET |
| 942 } | 908 } |
| 943 } | 909 } |
| 944 | 910 |
| 945 TargetHeaderLowering::~TargetHeaderLowering() = default; | 911 TargetHeaderLowering::~TargetHeaderLowering() = default; |
| 946 | 912 |
| 947 } // end of namespace Ice | 913 } // end of namespace Ice |
| OLD | NEW |