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 |
11 /// \brief Implements the skeleton of the TargetLowering class. | 11 /// \brief Implements the skeleton of the TargetLowering class. |
12 /// | 12 /// |
13 /// Specifically this invokes the appropriate lowering method for a given | 13 /// Specifically this invokes the appropriate lowering method for a given |
14 /// instruction kind and driving global register allocation. It also implements | 14 /// instruction kind and driving global register allocation. It also implements |
15 /// the non-deleted instruction iteration in LoweringContext. | 15 /// the non-deleted instruction iteration in LoweringContext. |
16 /// | 16 /// |
17 //===----------------------------------------------------------------------===// | 17 //===----------------------------------------------------------------------===// |
18 | 18 |
19 #include "IceTargetLowering.h" | 19 #include "IceTargetLowering.h" |
20 | 20 |
21 #include "IceBitVector.h" | 21 #include "IceBitVector.h" |
22 #include "IceCfg.h" // setError() | 22 #include "IceCfg.h" // setError() |
23 #include "IceCfgNode.h" | 23 #include "IceCfgNode.h" |
24 #include "IceGlobalContext.h" | 24 #include "IceGlobalContext.h" |
25 #include "IceGlobalInits.h" | 25 #include "IceGlobalInits.h" |
26 #include "IceInstVarIter.h" | 26 #include "IceInstVarIter.h" |
27 #include "IceLiveness.h" | |
27 #include "IceOperand.h" | 28 #include "IceOperand.h" |
28 #include "IceRegAlloc.h" | 29 #include "IceRegAlloc.h" |
29 | 30 |
30 #include <string> | 31 #include <string> |
31 #include <vector> | 32 #include <vector> |
32 | 33 |
33 #define TARGET_LOWERING_CLASS_FOR(t) Target_##t | 34 #define TARGET_LOWERING_CLASS_FOR(t) Target_##t |
34 | 35 |
35 // We prevent target-specific implementation details from leaking outside their | 36 // We prevent target-specific implementation details from leaking outside their |
36 // implementations by forbidding #include of target-specific header files | 37 // implementations by forbidding #include of target-specific header files |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 LinearScan.scan(RegMask, getFlags().getRandomizeRegisterAllocation()); | 505 LinearScan.scan(RegMask, getFlags().getRandomizeRegisterAllocation()); |
505 if (!LinearScan.hasEvictions()) | 506 if (!LinearScan.hasEvictions()) |
506 Repeat = false; | 507 Repeat = false; |
507 Kind = RAK_SecondChance; | 508 Kind = RAK_SecondChance; |
508 } while (Repeat); | 509 } while (Repeat); |
509 // TODO(stichnot): Run the register allocator one more time to do stack slot | 510 // TODO(stichnot): Run the register allocator one more time to do stack slot |
510 // coalescing. The idea would be to initialize the Unhandled list with the | 511 // coalescing. The idea would be to initialize the Unhandled list with the |
511 // set of Variables that have no register and a non-empty live range, and | 512 // set of Variables that have no register and a non-empty live range, and |
512 // model an infinite number of registers. Maybe use the register aliasing | 513 // model an infinite number of registers. Maybe use the register aliasing |
513 // mechanism to get better packing of narrower slots. | 514 // mechanism to get better packing of narrower slots. |
515 if (getFlags().getSplitGlobalVars()) | |
516 postRegallocSplitting(RegMask); | |
517 } | |
518 | |
519 namespace { | |
520 CfgVector<Inst *> getInstructionsInRange(CfgNode *Node, InstNumberT Start, | |
521 InstNumberT End) { | |
522 CfgVector<Inst *> Result; | |
523 bool Started = false; | |
524 auto Process = [&](InstList &Insts) { | |
525 for (auto &Instr : Insts) { | |
526 if (Instr.isDeleted()) { | |
527 continue; | |
528 } | |
529 if (Instr.getNumber() == Start) { | |
530 Started = true; | |
531 } | |
532 if (Started) { | |
533 Result.push_back(&Instr); | |
Jim Stichnoth
2016/08/02 05:57:50
emplace_back ?
manasijm
2016/08/02 21:41:59
Done.
| |
534 } | |
535 if (Instr.getNumber() == End) { | |
Jim Stichnoth
2016/08/02 05:57:50
Can this be ">=", just to be safe? just in case t
manasijm
2016/08/02 21:41:59
That seems to result in missing a lot of opportuni
| |
536 break; | |
537 } | |
538 } | |
539 }; | |
540 Process(Node->getPhis()); | |
541 Process(Node->getInsts()); | |
542 return Result; | |
543 } | |
544 } | |
Jim Stichnoth
2016/08/02 05:57:50
add blank line afterwards
manasijm
2016/08/02 21:41:59
Done.
| |
545 void TargetLowering::postRegallocSplitting(const SmallBitVector &RegMask) { | |
546 // Splits the live ranges of global(/multi block) variables and runs the | |
547 // register allocator to find registers for as many of the new variables as | |
548 // possible. | |
549 // TODO(manasijm): Merge the small liveranges back into multi-block ones when | |
550 // the variables get the same register. This will reduce the amount of new | |
551 // instructions inserted. This might involve a full dataflow analysis. | |
552 // Also, modify the preference mechanism in the register allocator to match. | |
553 | |
554 TimerMarker _(TimerStack::TT_splitGlobalVars, Func); | |
555 CfgSet<Variable *> SplitCandidates; | |
556 | |
557 // Find variables that does not have registers but are allowed to. Also skip | |
Jim Stichnoth
2016/08/02 05:57:50
that do not
manasijm
2016/08/02 21:41:59
Done.
| |
558 // variables with single segment live ranges as they are not split further in | |
559 // this function. | |
560 for (Variable *Var : Func->getVariables()) { | |
561 if (!Var->mustNotHaveReg() && !Var->hasReg()) { | |
562 if (Var->getLiveRange().getNumSegments() > 1) | |
563 SplitCandidates.insert(Var); | |
564 } | |
565 } | |
566 if (SplitCandidates.empty()) | |
567 return; | |
568 | |
569 CfgSet<Variable *> ExtraVars; | |
570 | |
571 struct UseInfo { | |
572 Variable *Replacing = nullptr; | |
573 Inst *FirstUse = nullptr; | |
574 Inst *LastDef = nullptr; | |
575 SizeT UseCount = 0; | |
576 }; | |
577 CfgUnorderedMap<Variable *, UseInfo> VarInfo; | |
578 // Split the live ranges of the viable variables by node. | |
579 // Compute metadata (UseInfo) for each of the resulting variables. | |
580 for (auto *Var : SplitCandidates) { | |
581 for (auto &Segment : Var->getLiveRange().getSegments()) { | |
582 UseInfo Info; | |
583 Info.Replacing = Var; | |
584 auto *Node = Var->getLiveRange().getNodeForSegment(Segment.first); | |
585 | |
586 for (auto *Instr : | |
587 getInstructionsInRange(Node, Segment.first, Segment.second)) { | |
588 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { | |
589 for (SizeT j = 0; j < Instr->getSrc(i)->getNumVars(); ++j) { | |
Jim Stichnoth
2016/08/02 05:57:50
For local variable splitting, I made the assumptio
manasijm
2016/08/02 21:41:59
Done.
| |
590 auto *Var = Instr->getSrc(i)->getVar(j); | |
591 if (Var == Info.Replacing) { | |
592 if (Info.FirstUse == nullptr && !llvm::isa<InstPhi>(Instr)) { | |
593 Info.FirstUse = Instr; | |
594 } | |
595 Info.UseCount++; | |
596 } | |
597 } | |
598 } | |
599 if (Instr->getDest() == Info.Replacing && !llvm::isa<InstPhi>(Instr)) { | |
Jim Stichnoth
2016/08/02 05:57:50
It looks like Phi instructions are not considered
manasijm
2016/08/02 21:41:59
Done.
Jim Stichnoth
2016/08/04 01:59:17
I don't see any new comment or TODO on this issue?
| |
600 Info.LastDef = Instr; | |
601 } | |
602 } | |
603 | |
604 static constexpr SizeT MinUseThreshold = 3; | |
605 // Skip if variable has less than `MinUseThreshold` uses in the segment. | |
606 if (Info.UseCount < MinUseThreshold) | |
607 continue; | |
608 | |
609 if (!Info.FirstUse && !Info.LastDef) { | |
610 continue; | |
611 } | |
612 | |
613 LiveRange LR; | |
614 LR.addSegment(Segment); | |
615 Variable *NewVar = Func->makeVariable(Var->getType()); | |
616 | |
617 NewVar->setLiveRange(LR); | |
618 | |
619 VarInfo[NewVar] = Info; | |
620 | |
621 ExtraVars.insert(NewVar); | |
622 } | |
623 } | |
624 // Run the register allocator with all these new variables included | |
625 LinearScan RegAlloc(Func); | |
626 RegAlloc.init(RAK_Global, SplitCandidates); | |
627 RegAlloc.scan(RegMask, getFlags().getRandomizeRegisterAllocation()); | |
628 | |
629 // Modify the Cfg to use the new variables that now now have registers. | |
Jim Stichnoth
2016/08/02 05:57:50
now now
manasijm
2016/08/02 21:41:59
Done.
| |
630 for (auto *ExtraVar : ExtraVars) { | |
631 if (!ExtraVar->hasReg()) { | |
632 continue; | |
633 } | |
634 | |
635 auto &Info = VarInfo[ExtraVar]; | |
636 | |
637 assert(ExtraVar->getLiveRange().getSegments().size() == 1); | |
638 auto Segment = ExtraVar->getLiveRange().getSegments()[0]; | |
639 | |
640 auto *Node = | |
641 Info.Replacing->getLiveRange().getNodeForSegment(Segment.first); | |
642 | |
643 auto RelevantInsts = | |
644 getInstructionsInRange(Node, Segment.first, Segment.second); | |
645 | |
646 if (RelevantInsts.empty()) | |
647 continue; | |
648 | |
649 // Replace old variables | |
650 for (auto *Instr : RelevantInsts) { | |
651 if (llvm::isa<InstPhi>(Instr)) | |
652 continue; | |
653 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { | |
654 // It's safe to iterate over the top-level src operands rather than | |
655 // using | |
656 // FOREACH_VAR_IN_INST(), because any variables inside e.g. mem operands | |
657 // should already have registers. | |
658 if (auto *Var = llvm::dyn_cast<Variable>(Instr->getSrc(i))) { | |
659 if (Var == Info.Replacing) { | |
660 Instr->replaceSource(i, ExtraVar); | |
661 } | |
662 } | |
663 } | |
664 if (Instr->getDest() == Info.Replacing) { | |
665 Instr->replaceDest(ExtraVar); | |
666 } | |
667 } | |
668 | |
669 assert(Info.FirstUse != Info.LastDef); | |
670 assert(Info.FirstUse || Info.LastDef); | |
671 | |
672 // Insert spill code | |
673 if (Info.FirstUse != nullptr) { | |
674 auto *NewInst = | |
675 Func->getTarget()->createLoweredMove(ExtraVar, Info.Replacing); | |
676 Node->getInsts().insert(instToIterator(Info.FirstUse), NewInst); | |
677 } | |
678 if (Info.LastDef != nullptr) { | |
679 auto *NewInst = | |
680 Func->getTarget()->createLoweredMove(Info.Replacing, ExtraVar); | |
681 Node->getInsts().insertAfter(instToIterator(Info.LastDef), NewInst); | |
682 } | |
683 } | |
514 } | 684 } |
515 | 685 |
516 void TargetLowering::markRedefinitions() { | 686 void TargetLowering::markRedefinitions() { |
517 // Find (non-SSA) instructions where the Dest variable appears in some source | 687 // Find (non-SSA) instructions where the Dest variable appears in some source |
518 // operand, and set the IsDestRedefined flag to keep liveness analysis | 688 // operand, and set the IsDestRedefined flag to keep liveness analysis |
519 // consistent. | 689 // consistent. |
520 for (auto Instr = Context.getCur(), E = Context.getNext(); Instr != E; | 690 for (auto Instr = Context.getCur(), E = Context.getNext(); Instr != E; |
521 ++Instr) { | 691 ++Instr) { |
522 if (Instr->isDeleted()) | 692 if (Instr->isDeleted()) |
523 continue; | 693 continue; |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
938 case TARGET_LOWERING_CLASS_FOR(X): \ | 1108 case TARGET_LOWERING_CLASS_FOR(X): \ |
939 return ::X::createTargetHeaderLowering(Ctx); | 1109 return ::X::createTargetHeaderLowering(Ctx); |
940 #include "SZTargets.def" | 1110 #include "SZTargets.def" |
941 #undef SUBZERO_TARGET | 1111 #undef SUBZERO_TARGET |
942 } | 1112 } |
943 } | 1113 } |
944 | 1114 |
945 TargetHeaderLowering::~TargetHeaderLowering() = default; | 1115 TargetHeaderLowering::~TargetHeaderLowering() = default; |
946 | 1116 |
947 } // end of namespace Ice | 1117 } // end of namespace Ice |
OLD | NEW |