| 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 | 
|---|