Chromium Code Reviews| 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 |