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 "IceOperand.h" | 27 #include "IceOperand.h" |
28 #include "IceRegAlloc.h" | 28 #include "IceRegAlloc.h" |
29 #include "IceLiveness.h" | |
Jim Stichnoth
2016/07/29 17:04:07
sort
manasijm
2016/08/01 22:20:04
Done.
| |
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 |
37 // anywhere outside their own files. To create target-specific objects | 38 // anywhere outside their own files. To create target-specific objects |
38 // (TargetLowering, TargetDataLowering, and TargetHeaderLowering) we use the | 39 // (TargetLowering, TargetDataLowering, and TargetHeaderLowering) we use the |
(...skipping 465 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().getGlobalSplitting()) | |
516 postRegallocSplitting(LinearScan, RegMask); | |
517 } | |
Jim Stichnoth
2016/07/29 19:14:31
blank line after this
manasijm
2016/08/01 22:20:04
Done.
| |
518 namespace { | |
519 CfgVector<Inst *> GetInstructionsInRange(CfgNode *Node, InstNumberT Start, | |
Jim Stichnoth
2016/07/29 19:14:31
Does this function assume that instruction numbers
Jim Stichnoth
2016/07/29 19:14:31
lowercase getInstructionsInRange per coding style
manasijm
2016/08/01 22:20:04
Done.
| |
520 InstNumberT End) { | |
521 CfgVector<Inst *> Result; | |
522 bool Started = false; | |
523 auto Process = [&](InstList &Insts) { | |
524 for (auto &Inst : Insts) { | |
Jim Stichnoth
2016/07/29 19:14:32
Name this Instr instead of Inst which is a type na
manasijm
2016/08/01 22:20:04
Done.
| |
525 if (!Started) { | |
Jim Stichnoth
2016/07/29 19:14:31
Restructure as "if (Started) ... else ..."
manasijm
2016/08/01 22:20:05
Acknowledged.
| |
526 if (Inst.getNumber() == Start) { | |
527 if (!Inst.isDeleted()) { | |
528 Result.push_back(&Inst); | |
529 } | |
530 Started = true; | |
531 } else { | |
Jim Stichnoth
2016/07/29 19:14:31
Is the "else continue" necessary? It doesn't look
manasijm
2016/08/01 22:20:04
Acknowledged.
| |
532 continue; | |
533 } | |
534 } else { | |
535 if (Inst.getNumber() == End) { | |
536 break; | |
537 } else { | |
538 if (!Inst.isDeleted()) { | |
539 Result.push_back(&Inst); | |
540 } | |
541 } | |
542 } | |
543 } | |
544 }; | |
545 Process(Node->getPhis()); | |
546 Process(Node->getInsts()); | |
547 return Result; | |
548 } | |
549 } | |
550 void TargetLowering::postRegallocSplitting(LinearScan &RegAllocator, | |
Jim Stichnoth
2016/07/29 17:04:07
These days we avoid passing by non-const ref, so m
manasijm
2016/08/01 22:20:04
Not passing a LinearScan object anymore.
| |
551 const SmallBitVector &RegMask) { | |
552 TimerMarker T(TimerStack::TT_globalSplitting, Func->getContext()); | |
Jim Stichnoth
2016/07/29 19:14:31
Newer Subzero style is to name this "_" instead of
manasijm
2016/08/01 22:20:04
Done.
| |
553 CfgSet<Variable *> SplitCandidates; | |
554 for (Variable *Var : Func->getVariables()) { | |
Jim Stichnoth
2016/07/29 19:14:31
Please add some documentation in the code as to wh
manasijm
2016/08/01 22:20:05
Done.
| |
555 if (!Var->mustNotHaveReg() && !Var->hasReg()) { | |
556 if (Var->getLiveRange().getNumSegments() > 1) | |
557 SplitCandidates.insert(Var); | |
558 } | |
559 } | |
560 if (SplitCandidates.empty()) | |
561 return; | |
562 | |
563 CfgSet<Variable *> ExtraVars; | |
564 | |
565 struct UseInfo { | |
566 Variable *Replacing = nullptr; | |
567 Inst *FirstUse = nullptr; | |
568 Inst *LastDef = nullptr; | |
569 SizeT UseCount = 0; | |
570 }; | |
571 CfgUnorderedMap<Variable *, UseInfo> VarInfo; | |
572 for (auto *Var : SplitCandidates) { | |
573 for (auto &Segment : Var->getLiveRange().getSegments()) { | |
574 UseInfo Info; | |
575 Info.Replacing = Var; | |
576 auto *Node = Var->getLiveRange().getNodeForSegment(Segment.first); | |
577 | |
578 for (auto *Instr : | |
579 GetInstructionsInRange(Node, Segment.first, Segment.second)) { | |
Jim Stichnoth
2016/07/29 19:14:32
(This might be too much to ask for an initial feat
manasijm
2016/08/01 22:20:04
Acknowledged.
| |
580 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { | |
581 for (SizeT j = 0; j < Instr->getSrc(i)->getNumVars(); ++j) { | |
582 auto *Var = Instr->getSrc(i)->getVar(j); | |
583 if (Var == Info.Replacing) { | |
584 if (Info.FirstUse == nullptr && !llvm::isa<InstPhi>(Instr)) { | |
585 Info.FirstUse = Instr; | |
586 } | |
587 Info.UseCount++; | |
588 } | |
589 } | |
590 } | |
591 if (Instr->getDest() == Info.Replacing && !llvm::isa<InstPhi>(Instr)) { | |
592 Info.LastDef = Instr; | |
593 } | |
594 } | |
595 if (Info.UseCount < 3) | |
Jim Stichnoth
2016/07/29 19:14:31
Use a static constexpr variable to self-document t
manasijm
2016/08/01 22:20:04
Done.
| |
596 continue; | |
597 | |
598 if (!Info.FirstUse && !Info.LastDef) { | |
599 continue; | |
600 } | |
601 | |
602 LiveRange LR; | |
603 LR.addSegment(Segment); | |
604 Variable *NewVar = Variable::create( | |
605 Func, Var->getType(), Func->getNumVariables() + ExtraVars.size()); | |
606 NewVar->setLiveRange(LR); | |
607 | |
608 VarInfo[NewVar] = Info; | |
609 | |
610 ExtraVars.insert(NewVar); | |
611 } | |
612 } | |
613 RegAllocator.init(RAK_Global, ExtraVars, SplitCandidates); | |
614 RegAllocator.setSplittingMode(); | |
615 RegAllocator.scan(RegMask, getFlags().getRandomizeRegisterAllocation()); | |
616 | |
617 for (auto *ExtraVar : ExtraVars) { | |
618 if (ExtraVar->hasReg()) { | |
Jim Stichnoth
2016/07/29 19:14:31
how about:
if (!ExtraVar->hasReg())
continu
manasijm
2016/08/01 22:20:05
Done.
| |
619 Func->addVariable(ExtraVar); | |
Jim Stichnoth
2016/07/29 19:14:31
I'm not thrilled about how these extra variables a
manasijm
2016/08/01 22:20:04
Done.
| |
620 | |
621 auto &Info = VarInfo[ExtraVar]; | |
622 | |
623 assert(ExtraVar->getLiveRange().getSegments().size() == 1); | |
624 auto Segment = ExtraVar->getLiveRange().getSegments()[0]; | |
625 | |
626 auto *Node = | |
627 Info.Replacing->getLiveRange().getNodeForSegment(Segment.first); | |
628 | |
629 auto RelevantInsts = | |
630 GetInstructionsInRange(Node, Segment.first, Segment.second); | |
631 | |
632 if (RelevantInsts.empty()) | |
633 continue; | |
634 | |
635 for (auto *Instr : RelevantInsts) { | |
636 if (llvm::isa<InstPhi>(Instr)) | |
637 continue; | |
638 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { | |
Jim Stichnoth
2016/07/29 19:14:31
Document that it's safe to iterate over the top-le
manasijm
2016/08/01 22:20:05
Copied this as is. :)
| |
639 if (auto *Var = llvm::dyn_cast<Variable>(Instr->getSrc(i))) { | |
640 if (Var == Info.Replacing) { | |
641 Instr->replaceSource(i, ExtraVar); | |
642 } | |
643 } | |
644 } | |
645 if (Instr->getDest() == Info.Replacing) { | |
646 Instr->replaceDest(ExtraVar); | |
647 } | |
648 } | |
649 | |
650 assert(Info.FirstUse != Info.LastDef); | |
651 assert(Info.FirstUse || Info.LastDef); | |
652 | |
653 if (Info.FirstUse != nullptr) { | |
654 auto *NewInst = | |
655 Func->getTarget()->createLoweredMove(ExtraVar, Info.Replacing); | |
656 Node->getInsts().insert(instToIterator(Info.FirstUse), NewInst); | |
657 } | |
658 if (Info.LastDef != nullptr) { | |
659 auto *NewInst = | |
660 Func->getTarget()->createLoweredMove(Info.Replacing, ExtraVar); | |
661 Node->getInsts().insertAfter(instToIterator(Info.LastDef), NewInst); | |
662 } | |
663 } | |
664 } | |
514 } | 665 } |
515 | 666 |
516 void TargetLowering::markRedefinitions() { | 667 void TargetLowering::markRedefinitions() { |
517 // Find (non-SSA) instructions where the Dest variable appears in some source | 668 // Find (non-SSA) instructions where the Dest variable appears in some source |
518 // operand, and set the IsDestRedefined flag to keep liveness analysis | 669 // operand, and set the IsDestRedefined flag to keep liveness analysis |
519 // consistent. | 670 // consistent. |
520 for (auto Instr = Context.getCur(), E = Context.getNext(); Instr != E; | 671 for (auto Instr = Context.getCur(), E = Context.getNext(); Instr != E; |
521 ++Instr) { | 672 ++Instr) { |
522 if (Instr->isDeleted()) | 673 if (Instr->isDeleted()) |
523 continue; | 674 continue; |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
938 case TARGET_LOWERING_CLASS_FOR(X): \ | 1089 case TARGET_LOWERING_CLASS_FOR(X): \ |
939 return ::X::createTargetHeaderLowering(Ctx); | 1090 return ::X::createTargetHeaderLowering(Ctx); |
940 #include "SZTargets.def" | 1091 #include "SZTargets.def" |
941 #undef SUBZERO_TARGET | 1092 #undef SUBZERO_TARGET |
942 } | 1093 } |
943 } | 1094 } |
944 | 1095 |
945 TargetHeaderLowering::~TargetHeaderLowering() = default; | 1096 TargetHeaderLowering::~TargetHeaderLowering() = default; |
946 | 1097 |
947 } // end of namespace Ice | 1098 } // end of namespace Ice |
OLD | NEW |