| 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 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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.) |
| 628 bool CfgNode::liveness(Liveness *Liveness) { | 628 bool CfgNode::liveness(Liveness *Liveness) { |
| 629 SizeT NumVars = Liveness->getNumVarsInNode(this); | 629 const SizeT NumVars = Liveness->getNumVarsInNode(this); |
| 630 LivenessBV Live(NumVars); | 630 const SizeT NumGlobalVars = Liveness->getNumGlobalVars(); |
| 631 LivenessBV &Live = Liveness->getScratchBV(); |
| 632 Live.clear(); |
| 633 |
| 631 LiveBeginEndMap *LiveBegin = nullptr; | 634 LiveBeginEndMap *LiveBegin = nullptr; |
| 632 LiveBeginEndMap *LiveEnd = nullptr; | 635 LiveBeginEndMap *LiveEnd = nullptr; |
| 633 // Mark the beginning and ending of each variable's live range with the | 636 // Mark the beginning and ending of each variable's live range with the |
| 634 // sentinel instruction number 0. | 637 // sentinel instruction number 0. |
| 635 if (Liveness->getMode() == Liveness_Intervals) { | 638 if (Liveness->getMode() == Liveness_Intervals) { |
| 636 LiveBegin = Liveness->getLiveBegin(this); | 639 LiveBegin = Liveness->getLiveBegin(this); |
| 637 LiveEnd = Liveness->getLiveEnd(this); | 640 LiveEnd = Liveness->getLiveEnd(this); |
| 638 LiveBegin->clear(); | 641 LiveBegin->clear(); |
| 639 LiveEnd->clear(); | 642 LiveEnd->clear(); |
| 640 // Guess that the number of live ranges beginning is roughly the number of | 643 // Guess that the number of live ranges beginning is roughly the number of |
| 641 // instructions, and same for live ranges ending. | 644 // instructions, and same for live ranges ending. |
| 642 LiveBegin->reserve(getInstCountEstimate()); | 645 LiveBegin->reserve(getInstCountEstimate()); |
| 643 LiveEnd->reserve(getInstCountEstimate()); | 646 LiveEnd->reserve(getInstCountEstimate()); |
| 644 } | 647 } |
| 648 |
| 645 // Initialize Live to be the union of all successors' LiveIn. | 649 // Initialize Live to be the union of all successors' LiveIn. |
| 646 for (CfgNode *Succ : OutEdges) { | 650 for (CfgNode *Succ : OutEdges) { |
| 647 Live |= Liveness->getLiveIn(Succ); | 651 const LivenessBV &LiveIn = Liveness->getLiveIn(Succ); |
| 652 assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars); |
| 653 Live |= LiveIn; |
| 648 // Mark corresponding argument of phis in successor as live. | 654 // Mark corresponding argument of phis in successor as live. |
| 649 for (Inst &I : Succ->Phis) { | 655 for (Inst &I : Succ->Phis) { |
| 650 if (I.isDeleted()) | 656 if (I.isDeleted()) |
| 651 continue; | 657 continue; |
| 652 auto *Phi = llvm::dyn_cast<InstPhi>(&I); | 658 auto *Phi = llvm::cast<InstPhi>(&I); |
| 653 Phi->livenessPhiOperand(Live, this, Liveness); | 659 Phi->livenessPhiOperand(Live, this, Liveness); |
| 654 } | 660 } |
| 655 } | 661 } |
| 662 assert(Live.empty() || Live.size() == NumGlobalVars); |
| 656 Liveness->getLiveOut(this) = Live; | 663 Liveness->getLiveOut(this) = Live; |
| 657 | 664 |
| 665 // Expand Live so it can hold locals in addition to globals. |
| 666 Live.resize(NumVars); |
| 658 // Process regular instructions in reverse order. | 667 // Process regular instructions in reverse order. |
| 659 for (Inst &I : reverse_range(Insts)) { | 668 for (Inst &I : reverse_range(Insts)) { |
| 660 if (I.isDeleted()) | 669 if (I.isDeleted()) |
| 661 continue; | 670 continue; |
| 662 I.liveness(I.getNumber(), Live, Liveness, LiveBegin, LiveEnd); | 671 I.liveness(I.getNumber(), Live, Liveness, LiveBegin, LiveEnd); |
| 663 } | 672 } |
| 664 // Process phis in forward order so that we can override the instruction | 673 // 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. | 674 // number to be that of the earliest phi instruction in the block. |
| 666 SizeT NumNonDeadPhis = 0; | 675 SizeT NumNonDeadPhis = 0; |
| 667 InstNumberT FirstPhiNumber = Inst::NumberSentinel; | 676 InstNumberT FirstPhiNumber = Inst::NumberSentinel; |
| 668 for (Inst &I : Phis) { | 677 for (Inst &I : Phis) { |
| 669 if (I.isDeleted()) | 678 if (I.isDeleted()) |
| 670 continue; | 679 continue; |
| 671 if (FirstPhiNumber == Inst::NumberSentinel) | 680 if (FirstPhiNumber == Inst::NumberSentinel) |
| 672 FirstPhiNumber = I.getNumber(); | 681 FirstPhiNumber = I.getNumber(); |
| 673 if (I.liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd)) | 682 if (I.liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd)) |
| 674 ++NumNonDeadPhis; | 683 ++NumNonDeadPhis; |
| 675 } | 684 } |
| 676 | 685 |
| 677 // When using the sparse representation, after traversing the instructions in | 686 // When using the sparse representation, after traversing the instructions in |
| 678 // the block, the Live bitvector should only contain set bits for global | 687 // 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 | 688 // 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 | 689 // the Live bitvector. |
| 681 // required, but the validation is not.) | 690 if (Live.find_next(NumGlobalVars) != -1) { |
| 682 LivenessBV LiveOrig = Live; | |
| 683 Live.resize(Liveness->getNumGlobalVars()); | |
| 684 if (Live != LiveOrig) { | |
| 685 if (BuildDefs::dump()) { | 691 if (BuildDefs::dump()) { |
| 686 // This is a fatal liveness consistency error. Print some diagnostics and | 692 // This is a fatal liveness consistency error. Print some diagnostics and |
| 687 // abort. | 693 // abort. |
| 688 Ostream &Str = Func->getContext()->getStrDump(); | 694 Ostream &Str = Func->getContext()->getStrDump(); |
| 689 Func->resetCurrentNode(); | 695 Func->resetCurrentNode(); |
| 690 Str << "LiveOrig-Live ="; | 696 Str << "Invalid Live ="; |
| 691 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) { | 697 for (SizeT i = NumGlobalVars; i < Live.size(); ++i) { |
| 692 if (LiveOrig.test(i)) { | 698 if (Live.test(i)) { |
| 693 Str << " "; | 699 Str << " "; |
| 694 Liveness->getVariable(i, this)->dump(Func); | 700 Liveness->getVariable(i, this)->dump(Func); |
| 695 } | 701 } |
| 696 } | 702 } |
| 697 Str << "\n"; | 703 Str << "\n"; |
| 698 } | 704 } |
| 699 llvm::report_fatal_error("Fatal inconsistency in liveness analysis"); | 705 llvm::report_fatal_error("Fatal inconsistency in liveness analysis"); |
| 700 } | 706 } |
| 707 // Now truncate Live to prevent LiveIn from growing. |
| 708 Live.resize(NumGlobalVars); |
| 701 | 709 |
| 702 bool Changed = false; | 710 bool Changed = false; |
| 703 LivenessBV &LiveIn = Liveness->getLiveIn(this); | 711 LivenessBV &LiveIn = Liveness->getLiveIn(this); |
| 712 assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars); |
| 704 // Add in current LiveIn | 713 // Add in current LiveIn |
| 705 Live |= LiveIn; | 714 Live |= LiveIn; |
| 706 // Check result, set LiveIn=Live | 715 // Check result, set LiveIn=Live |
| 707 SizeT &PrevNumNonDeadPhis = Liveness->getNumNonDeadPhis(this); | 716 SizeT &PrevNumNonDeadPhis = Liveness->getNumNonDeadPhis(this); |
| 708 bool LiveInChanged = (Live != LiveIn); | 717 bool LiveInChanged = (Live != LiveIn); |
| 709 Changed = (NumNonDeadPhis != PrevNumNonDeadPhis || LiveInChanged); | 718 Changed = (NumNonDeadPhis != PrevNumNonDeadPhis || LiveInChanged); |
| 710 if (LiveInChanged) | 719 if (LiveInChanged) |
| 711 LiveIn = Live; | 720 LiveIn = Live; |
| 712 PrevNumNonDeadPhis = NumNonDeadPhis; | 721 PrevNumNonDeadPhis = NumNonDeadPhis; |
| 713 return Changed; | 722 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 | 780 // 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 | 781 // 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 | 782 // 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 | 783 // 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 | 784 // different basic block, and there is a single read that ends the live in the |
| 776 // basic block that contained the actual phi instruction. | 785 // basic block that contained the actual phi instruction. |
| 777 void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, | 786 void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, |
| 778 InstNumberT LastInstNum) { | 787 InstNumberT LastInstNum) { |
| 779 TimerMarker T1(TimerStack::TT_liveRange, Func); | 788 TimerMarker T1(TimerStack::TT_liveRange, Func); |
| 780 | 789 |
| 781 SizeT NumVars = Liveness->getNumVarsInNode(this); | 790 const SizeT NumVars = Liveness->getNumVarsInNode(this); |
| 782 LivenessBV &LiveIn = Liveness->getLiveIn(this); | 791 const LivenessBV &LiveIn = Liveness->getLiveIn(this); |
| 783 LivenessBV &LiveOut = Liveness->getLiveOut(this); | 792 const LivenessBV &LiveOut = Liveness->getLiveOut(this); |
| 784 LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this); | 793 LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this); |
| 785 LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this); | 794 LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this); |
| 786 std::sort(MapBegin.begin(), MapBegin.end()); | 795 std::sort(MapBegin.begin(), MapBegin.end()); |
| 787 std::sort(MapEnd.begin(), MapEnd.end()); | 796 std::sort(MapEnd.begin(), MapEnd.end()); |
| 788 | 797 |
| 789 if (!livenessValidateIntervals(Liveness)) { | 798 if (!livenessValidateIntervals(Liveness)) { |
| 790 llvm::report_fatal_error("livenessAddIntervals: Liveness error"); | 799 llvm::report_fatal_error("livenessAddIntervals: Liveness error"); |
| 791 return; | 800 return; |
| 792 } | 801 } |
| 793 | 802 |
| 794 LivenessBV LiveInAndOut = LiveIn; | 803 LivenessBV &LiveInAndOut = Liveness->getScratchBV(); |
| 804 LiveInAndOut = LiveIn; |
| 795 LiveInAndOut &= LiveOut; | 805 LiveInAndOut &= LiveOut; |
| 796 | 806 |
| 797 // Iterate in parallel across the sorted MapBegin[] and MapEnd[]. | 807 // Iterate in parallel across the sorted MapBegin[] and MapEnd[]. |
| 798 auto IBB = MapBegin.begin(), IEB = MapEnd.begin(); | 808 auto IBB = MapBegin.begin(), IEB = MapEnd.begin(); |
| 799 auto IBE = MapBegin.end(), IEE = MapEnd.end(); | 809 auto IBE = MapBegin.end(), IEE = MapEnd.end(); |
| 800 while (IBB != IBE || IEB != IEE) { | 810 while (IBB != IBE || IEB != IEE) { |
| 801 SizeT i1 = IBB == IBE ? NumVars : IBB->first; | 811 SizeT i1 = IBB == IBE ? NumVars : IBB->first; |
| 802 SizeT i2 = IEB == IEE ? NumVars : IEB->first; | 812 SizeT i2 = IEB == IEE ? NumVars : IEB->first; |
| 803 SizeT i = std::min(i1, i2); | 813 SizeT i = std::min(i1, i2); |
| 804 // i1 is the Variable number of the next MapBegin entry, and i2 is the | 814 // i1 is the Variable number of the next MapBegin entry, and i2 is the |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 bool First = true; | 1353 bool First = true; |
| 1344 for (CfgNode *I : InEdges) { | 1354 for (CfgNode *I : InEdges) { |
| 1345 if (!First) | 1355 if (!First) |
| 1346 Str << ", "; | 1356 Str << ", "; |
| 1347 First = false; | 1357 First = false; |
| 1348 Str << "%" << I->getName(); | 1358 Str << "%" << I->getName(); |
| 1349 } | 1359 } |
| 1350 Str << "\n"; | 1360 Str << "\n"; |
| 1351 } | 1361 } |
| 1352 // Dump the live-in variables. | 1362 // Dump the live-in variables. |
| 1353 LivenessBV LiveIn; | 1363 if (Func->isVerbose(IceV_Liveness)) { |
| 1354 if (Liveness) | 1364 if (Liveness != nullptr && !Liveness->getLiveIn(this).empty()) { |
| 1355 LiveIn = Liveness->getLiveIn(this); | 1365 const LivenessBV &LiveIn = Liveness->getLiveIn(this); |
| 1356 if (Func->isVerbose(IceV_Liveness) && !LiveIn.empty()) { | 1366 Str << " // LiveIn:"; |
| 1357 Str << " // LiveIn:"; | 1367 for (SizeT i = 0; i < LiveIn.size(); ++i) { |
| 1358 for (SizeT i = 0; i < LiveIn.size(); ++i) { | 1368 if (LiveIn[i]) { |
| 1359 if (LiveIn[i]) { | 1369 Variable *Var = Liveness->getVariable(i, this); |
| 1360 Variable *Var = Liveness->getVariable(i, this); | 1370 Str << " %" << Var->getName(Func); |
| 1361 Str << " %" << Var->getName(Func); | 1371 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { |
| 1362 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { | 1372 Str << ":" |
| 1363 Str << ":" | 1373 << Func->getTarget()->getRegName(Var->getRegNum(), |
| 1364 << Func->getTarget()->getRegName(Var->getRegNum(), | 1374 Var->getType()); |
| 1365 Var->getType()); | 1375 } |
| 1366 } | 1376 } |
| 1367 } | 1377 } |
| 1378 Str << "\n"; |
| 1368 } | 1379 } |
| 1369 Str << "\n"; | |
| 1370 } | 1380 } |
| 1371 // Dump each instruction. | 1381 // Dump each instruction. |
| 1372 if (Func->isVerbose(IceV_Instructions)) { | 1382 if (Func->isVerbose(IceV_Instructions)) { |
| 1373 for (const Inst &I : Phis) | 1383 for (const Inst &I : Phis) |
| 1374 I.dumpDecorated(Func); | 1384 I.dumpDecorated(Func); |
| 1375 for (const Inst &I : Insts) | 1385 for (const Inst &I : Insts) |
| 1376 I.dumpDecorated(Func); | 1386 I.dumpDecorated(Func); |
| 1377 } | 1387 } |
| 1378 // Dump the live-out variables. | 1388 // Dump the live-out variables. |
| 1379 LivenessBV LiveOut; | 1389 if (Func->isVerbose(IceV_Liveness)) { |
| 1380 if (Liveness) | 1390 if (Liveness != nullptr && !Liveness->getLiveOut(this).empty()) { |
| 1381 LiveOut = Liveness->getLiveOut(this); | 1391 const LivenessBV &LiveOut = Liveness->getLiveOut(this); |
| 1382 if (Func->isVerbose(IceV_Liveness) && !LiveOut.empty()) { | 1392 Str << " // LiveOut:"; |
| 1383 Str << " // LiveOut:"; | 1393 for (SizeT i = 0; i < LiveOut.size(); ++i) { |
| 1384 for (SizeT i = 0; i < LiveOut.size(); ++i) { | 1394 if (LiveOut[i]) { |
| 1385 if (LiveOut[i]) { | 1395 Variable *Var = Liveness->getVariable(i, this); |
| 1386 Variable *Var = Liveness->getVariable(i, this); | 1396 Str << " %" << Var->getName(Func); |
| 1387 Str << " %" << Var->getName(Func); | 1397 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { |
| 1388 if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) { | 1398 Str << ":" |
| 1389 Str << ":" | 1399 << Func->getTarget()->getRegName(Var->getRegNum(), |
| 1390 << Func->getTarget()->getRegName(Var->getRegNum(), | 1400 Var->getType()); |
| 1391 Var->getType()); | 1401 } |
| 1392 } | 1402 } |
| 1393 } | 1403 } |
| 1404 Str << "\n"; |
| 1394 } | 1405 } |
| 1395 Str << "\n"; | |
| 1396 } | 1406 } |
| 1397 // Dump list of successor nodes. | 1407 // Dump list of successor nodes. |
| 1398 if (Func->isVerbose(IceV_Succs)) { | 1408 if (Func->isVerbose(IceV_Succs)) { |
| 1399 Str << " // succs = "; | 1409 Str << " // succs = "; |
| 1400 bool First = true; | 1410 bool First = true; |
| 1401 for (CfgNode *I : OutEdges) { | 1411 for (CfgNode *I : OutEdges) { |
| 1402 if (!First) | 1412 if (!First) |
| 1403 Str << ", "; | 1413 Str << ", "; |
| 1404 First = false; | 1414 First = false; |
| 1405 Str << "%" << I->getName(); | 1415 Str << "%" << I->getName(); |
| (...skipping 26 matching lines...) Expand all 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 |