OLD | NEW |
---|---|
1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// | 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) 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 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
617 } | 617 } |
618 for (Inst &I : Phis) { | 618 for (Inst &I : Phis) { |
619 if (I.isDeleted()) | 619 if (I.isDeleted()) |
620 continue; | 620 continue; |
621 I.livenessLightweight(Func, Live); | 621 I.livenessLightweight(Func, Live); |
622 } | 622 } |
623 } | 623 } |
624 | 624 |
625 // Performs liveness analysis on the block. Returns true if the incoming | 625 // Performs liveness analysis on the block. Returns true if the incoming |
626 // liveness changed from before, false if it stayed the same. (If it changes, | 626 // liveness changed from before, false if it stayed the same. (If it changes, |
627 // the node's predecessors need to be processed again.) | 627 // the node's predecessors need to be processed again.) The ScratchBV is |
John
2016/02/29 15:12:31
Really, ScratchBV should not be part of the interf
Jim Stichnoth
2016/02/29 22:58:26
Done.
| |
628 bool CfgNode::liveness(Liveness *Liveness) { | 628 // allocated by the caller and reused across successive calls to avoid |
629 SizeT NumVars = Liveness->getNumVarsInNode(this); | 629 // unnecessary memory allocation. |
630 LivenessBV Live(NumVars); | 630 bool CfgNode::liveness(Liveness *Liveness, LivenessBV *ScratchBV) { |
631 const SizeT NumVars = Liveness->getNumVarsInNode(this); | |
632 const SizeT NumGlobalVars = Liveness->getNumGlobalVars(); | |
633 LivenessBV &Live = *ScratchBV; | |
John
2016/02/29 15:12:31
Why are you incurring the extra memory de-referenc
Jim Stichnoth
2016/02/29 22:58:26
I don't think that's an actual dereference happeni
| |
634 Live.reserve(NumVars); | |
635 Live.clear(); | |
636 | |
631 LiveBeginEndMap *LiveBegin = nullptr; | 637 LiveBeginEndMap *LiveBegin = nullptr; |
632 LiveBeginEndMap *LiveEnd = nullptr; | 638 LiveBeginEndMap *LiveEnd = nullptr; |
633 // Mark the beginning and ending of each variable's live range with the | 639 // Mark the beginning and ending of each variable's live range with the |
634 // sentinel instruction number 0. | 640 // sentinel instruction number 0. |
635 if (Liveness->getMode() == Liveness_Intervals) { | 641 if (Liveness->getMode() == Liveness_Intervals) { |
636 LiveBegin = Liveness->getLiveBegin(this); | 642 LiveBegin = Liveness->getLiveBegin(this); |
637 LiveEnd = Liveness->getLiveEnd(this); | 643 LiveEnd = Liveness->getLiveEnd(this); |
638 LiveBegin->clear(); | 644 LiveBegin->clear(); |
639 LiveEnd->clear(); | 645 LiveEnd->clear(); |
640 // Guess that the number of live ranges beginning is roughly the number of | 646 // Guess that the number of live ranges beginning is roughly the number of |
641 // instructions, and same for live ranges ending. | 647 // instructions, and same for live ranges ending. |
642 LiveBegin->reserve(getInstCountEstimate()); | 648 LiveBegin->reserve(getInstCountEstimate()); |
643 LiveEnd->reserve(getInstCountEstimate()); | 649 LiveEnd->reserve(getInstCountEstimate()); |
644 } | 650 } |
651 | |
645 // Initialize Live to be the union of all successors' LiveIn. | 652 // Initialize Live to be the union of all successors' LiveIn. |
646 for (CfgNode *Succ : OutEdges) { | 653 for (CfgNode *Succ : OutEdges) { |
647 Live |= Liveness->getLiveIn(Succ); | 654 const LivenessBV &LiveIn = Liveness->getLiveIn(Succ); |
John
2016/02/29 15:12:31
auto?
Jim Stichnoth
2016/02/29 22:58:26
I'd kinda rather not in this case.
I'd be happier
| |
655 assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars); | |
656 Live |= LiveIn; | |
648 // Mark corresponding argument of phis in successor as live. | 657 // Mark corresponding argument of phis in successor as live. |
649 for (Inst &I : Succ->Phis) { | 658 for (Inst &I : Succ->Phis) { |
650 if (I.isDeleted()) | 659 if (I.isDeleted()) |
651 continue; | 660 continue; |
652 auto *Phi = llvm::dyn_cast<InstPhi>(&I); | 661 auto *Phi = llvm::dyn_cast<InstPhi>(&I); |
653 Phi->livenessPhiOperand(Live, this, Liveness); | 662 Phi->livenessPhiOperand(Live, this, Liveness); |
654 } | 663 } |
655 } | 664 } |
665 assert(Live.empty() || Live.size() == NumGlobalVars); | |
656 Liveness->getLiveOut(this) = Live; | 666 Liveness->getLiveOut(this) = Live; |
657 | 667 |
668 // Expand Live so it can hold locals in addition to globals. | |
669 Live.resize(NumVars); | |
658 // Process regular instructions in reverse order. | 670 // Process regular instructions in reverse order. |
659 for (Inst &I : reverse_range(Insts)) { | 671 for (Inst &I : reverse_range(Insts)) { |
660 if (I.isDeleted()) | 672 if (I.isDeleted()) |
661 continue; | 673 continue; |
662 I.liveness(I.getNumber(), Live, Liveness, LiveBegin, LiveEnd); | 674 I.liveness(I.getNumber(), Live, Liveness, LiveBegin, LiveEnd); |
663 } | 675 } |
664 // Process phis in forward order so that we can override the instruction | 676 // Process phis in forward order so that we can override the instruction |
665 // number to be that of the earliest phi instruction in the block. | 677 // number to be that of the earliest phi instruction in the block. |
666 SizeT NumNonDeadPhis = 0; | 678 SizeT NumNonDeadPhis = 0; |
667 InstNumberT FirstPhiNumber = Inst::NumberSentinel; | 679 InstNumberT FirstPhiNumber = Inst::NumberSentinel; |
668 for (Inst &I : Phis) { | 680 for (Inst &I : Phis) { |
669 if (I.isDeleted()) | 681 if (I.isDeleted()) |
670 continue; | 682 continue; |
671 if (FirstPhiNumber == Inst::NumberSentinel) | 683 if (FirstPhiNumber == Inst::NumberSentinel) |
672 FirstPhiNumber = I.getNumber(); | 684 FirstPhiNumber = I.getNumber(); |
673 if (I.liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd)) | 685 if (I.liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd)) |
674 ++NumNonDeadPhis; | 686 ++NumNonDeadPhis; |
675 } | 687 } |
676 | 688 |
677 // When using the sparse representation, after traversing the instructions in | 689 // When using the sparse representation, after traversing the instructions in |
678 // the block, the Live bitvector should only contain set bits for global | 690 // the block, the Live bitvector should only contain set bits for global |
679 // variables upon block entry. We validate this by shrinking the Live vector | 691 // variables upon block entry. We validate this by testing the upper bits of |
680 // and then testing it against the pre-shrunk version. (The shrinking is | 692 // the Live bitvector. |
681 // required, but the validation is not.) | 693 if (Live.find_next(NumGlobalVars) != -1) { |
682 LivenessBV LiveOrig = Live; | |
683 Live.resize(Liveness->getNumGlobalVars()); | |
684 if (Live != LiveOrig) { | |
685 if (BuildDefs::dump()) { | 694 if (BuildDefs::dump()) { |
686 // This is a fatal liveness consistency error. Print some diagnostics and | 695 // This is a fatal liveness consistency error. Print some diagnostics and |
687 // abort. | 696 // abort. |
688 Ostream &Str = Func->getContext()->getStrDump(); | 697 Ostream &Str = Func->getContext()->getStrDump(); |
689 Func->resetCurrentNode(); | 698 Func->resetCurrentNode(); |
690 Str << "LiveOrig-Live ="; | 699 Str << "Invalid Live ="; |
691 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) { | 700 for (SizeT i = NumGlobalVars; i < Live.size(); ++i) { |
692 if (LiveOrig.test(i)) { | 701 if (Live.test(i)) { |
693 Str << " "; | 702 Str << " "; |
694 Liveness->getVariable(i, this)->dump(Func); | 703 Liveness->getVariable(i, this)->dump(Func); |
695 } | 704 } |
696 } | 705 } |
697 Str << "\n"; | 706 Str << "\n"; |
698 } | 707 } |
699 llvm::report_fatal_error("Fatal inconsistency in liveness analysis"); | 708 llvm::report_fatal_error("Fatal inconsistency in liveness analysis"); |
700 } | 709 } |
710 // Now truncate Live to prevent LiveIn from growing. | |
711 Live.resize(NumGlobalVars); | |
701 | 712 |
702 bool Changed = false; | 713 bool Changed = false; |
703 LivenessBV &LiveIn = Liveness->getLiveIn(this); | 714 LivenessBV &LiveIn = Liveness->getLiveIn(this); |
715 assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars); | |
704 // Add in current LiveIn | 716 // Add in current LiveIn |
705 Live |= LiveIn; | 717 Live |= LiveIn; |
706 // Check result, set LiveIn=Live | 718 // Check result, set LiveIn=Live |
707 SizeT &PrevNumNonDeadPhis = Liveness->getNumNonDeadPhis(this); | 719 SizeT &PrevNumNonDeadPhis = Liveness->getNumNonDeadPhis(this); |
708 bool LiveInChanged = (Live != LiveIn); | 720 bool LiveInChanged = (Live != LiveIn); |
709 Changed = (NumNonDeadPhis != PrevNumNonDeadPhis || LiveInChanged); | 721 Changed = (NumNonDeadPhis != PrevNumNonDeadPhis || LiveInChanged); |
710 if (LiveInChanged) | 722 if (LiveInChanged) |
711 LiveIn = Live; | 723 LiveIn = Live; |
712 PrevNumNonDeadPhis = NumNonDeadPhis; | 724 PrevNumNonDeadPhis = NumNonDeadPhis; |
713 return Changed; | 725 return Changed; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
771 // Once basic liveness is complete, compute actual live ranges. It is assumed | 783 // Once basic liveness is complete, compute actual live ranges. It is assumed |
772 // that within a single basic block, a live range begins at most once and ends | 784 // that within a single basic block, a live range begins at most once and ends |
773 // at most once. This is certainly true for pure SSA form. It is also true once | 785 // at most once. This is certainly true for pure SSA form. It is also true once |
774 // phis are lowered, since each assignment to the phi-based temporary is in a | 786 // phis are lowered, since each assignment to the phi-based temporary is in a |
775 // different basic block, and there is a single read that ends the live in the | 787 // different basic block, and there is a single read that ends the live in the |
776 // basic block that contained the actual phi instruction. | 788 // basic block that contained the actual phi instruction. |
777 void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, | 789 void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, |
778 InstNumberT LastInstNum) { | 790 InstNumberT LastInstNum) { |
779 TimerMarker T1(TimerStack::TT_liveRange, Func); | 791 TimerMarker T1(TimerStack::TT_liveRange, Func); |
780 | 792 |
781 SizeT NumVars = Liveness->getNumVarsInNode(this); | 793 const SizeT NumVars = Liveness->getNumVarsInNode(this); |
782 LivenessBV &LiveIn = Liveness->getLiveIn(this); | 794 const LivenessBV &LiveIn = Liveness->getLiveIn(this); |
783 LivenessBV &LiveOut = Liveness->getLiveOut(this); | 795 const LivenessBV &LiveOut = Liveness->getLiveOut(this); |
784 LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this); | 796 LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this); |
785 LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this); | 797 LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this); |
786 std::sort(MapBegin.begin(), MapBegin.end()); | 798 std::sort(MapBegin.begin(), MapBegin.end()); |
787 std::sort(MapEnd.begin(), MapEnd.end()); | 799 std::sort(MapEnd.begin(), MapEnd.end()); |
788 | 800 |
789 if (!livenessValidateIntervals(Liveness)) { | 801 if (!livenessValidateIntervals(Liveness)) { |
790 llvm::report_fatal_error("livenessAddIntervals: Liveness error"); | 802 llvm::report_fatal_error("livenessAddIntervals: Liveness error"); |
791 return; | 803 return; |
792 } | 804 } |
793 | 805 |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1343 bool First = true; | 1355 bool First = true; |
1344 for (CfgNode *I : InEdges) { | 1356 for (CfgNode *I : InEdges) { |
1345 if (!First) | 1357 if (!First) |
1346 Str << ", "; | 1358 Str << ", "; |
1347 First = false; | 1359 First = false; |
1348 Str << "%" << I->getName(); | 1360 Str << "%" << I->getName(); |
1349 } | 1361 } |
1350 Str << "\n"; | 1362 Str << "\n"; |
1351 } | 1363 } |
1352 // Dump the live-in variables. | 1364 // Dump the live-in variables. |
1353 LivenessBV LiveIn; | 1365 if (Func->isVerbose(IceV_Liveness) && Liveness != nullptr && |
John
2016/02/29 15:12:31
this test is testing different things. it is (to m
Jim Stichnoth
2016/02/29 22:58:26
Done.
| |
1354 if (Liveness) | 1366 !Liveness->getLiveIn(this).empty()) { |
1355 LiveIn = Liveness->getLiveIn(this); | 1367 const LivenessBV &LiveIn = Liveness->getLiveIn(this); |
1356 if (Func->isVerbose(IceV_Liveness) && !LiveIn.empty()) { | |
1357 Str << " // LiveIn:"; | 1368 Str << " // LiveIn:"; |
1358 for (SizeT i = 0; i < LiveIn.size(); ++i) { | 1369 for (SizeT i = 0; i < LiveIn.size(); ++i) { |
1359 if (LiveIn[i]) { | 1370 if (LiveIn[i]) { |
1360 Variable *Var = Liveness->getVariable(i, this); | 1371 Variable *Var = Liveness->getVariable(i, this); |
1361 Str << " %" << Var->getName(Func); | 1372 Str << " %" << Var->getName(Func); |
1362 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { | 1373 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { |
1363 Str << ":" | 1374 Str << ":" |
1364 << Func->getTarget()->getRegName(Var->getRegNum(), | 1375 << Func->getTarget()->getRegName(Var->getRegNum(), |
1365 Var->getType()); | 1376 Var->getType()); |
1366 } | 1377 } |
1367 } | 1378 } |
1368 } | 1379 } |
1369 Str << "\n"; | 1380 Str << "\n"; |
1370 } | 1381 } |
1371 // Dump each instruction. | 1382 // Dump each instruction. |
1372 if (Func->isVerbose(IceV_Instructions)) { | 1383 if (Func->isVerbose(IceV_Instructions)) { |
1373 for (const Inst &I : Phis) | 1384 for (const Inst &I : Phis) |
1374 I.dumpDecorated(Func); | 1385 I.dumpDecorated(Func); |
1375 for (const Inst &I : Insts) | 1386 for (const Inst &I : Insts) |
1376 I.dumpDecorated(Func); | 1387 I.dumpDecorated(Func); |
1377 } | 1388 } |
1378 // Dump the live-out variables. | 1389 // Dump the live-out variables. |
1379 LivenessBV LiveOut; | 1390 if (Func->isVerbose(IceV_Liveness) && Liveness != nullptr && |
1380 if (Liveness) | 1391 !Liveness->getLiveOut(this).empty()) { |
1381 LiveOut = Liveness->getLiveOut(this); | 1392 const LivenessBV &LiveOut = Liveness->getLiveOut(this); |
1382 if (Func->isVerbose(IceV_Liveness) && !LiveOut.empty()) { | |
1383 Str << " // LiveOut:"; | 1393 Str << " // LiveOut:"; |
1384 for (SizeT i = 0; i < LiveOut.size(); ++i) { | 1394 for (SizeT i = 0; i < LiveOut.size(); ++i) { |
1385 if (LiveOut[i]) { | 1395 if (LiveOut[i]) { |
1386 Variable *Var = Liveness->getVariable(i, this); | 1396 Variable *Var = Liveness->getVariable(i, this); |
1387 Str << " %" << Var->getName(Func); | 1397 Str << " %" << Var->getName(Func); |
1388 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { | 1398 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { |
1389 Str << ":" | 1399 Str << ":" |
1390 << Func->getTarget()->getRegName(Var->getRegNum(), | 1400 << Func->getTarget()->getRegName(Var->getRegNum(), |
1391 Var->getType()); | 1401 Var->getType()); |
1392 } | 1402 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1432 auto *Instr = InstIntrinsicCall::create( | 1442 auto *Instr = InstIntrinsicCall::create( |
1433 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); | 1443 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); |
1434 Instr->addArg(AtomicRMWOp); | 1444 Instr->addArg(AtomicRMWOp); |
1435 Instr->addArg(Counter); | 1445 Instr->addArg(Counter); |
1436 Instr->addArg(One); | 1446 Instr->addArg(One); |
1437 Instr->addArg(OrderAcquireRelease); | 1447 Instr->addArg(OrderAcquireRelease); |
1438 Insts.push_front(Instr); | 1448 Insts.push_front(Instr); |
1439 } | 1449 } |
1440 | 1450 |
1441 } // end of namespace Ice | 1451 } // end of namespace Ice |
OLD | NEW |