Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Side by Side Diff: src/IceTargetLowering.cpp

Issue 2172313002: Subzero : Live Range Splitting after initial Register Allocation (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Cleanup Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698