void RegisterOperands::detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS) { SlotIndex SlotIdx = LIS.getInstructionIndex(MI); for (auto RI = Defs.begin(); RI != Defs.end(); /*empty*/) { unsigned Reg = RI->RegUnit; const LiveRange *LR = getLiveRange(LIS, Reg); if (LR != nullptr) { LiveQueryResult LRQ = LR->Query(SlotIdx); if (LRQ.isDeadDef()) { // LiveIntervals knows this is a dead even though it's MachineOperand is // not flagged as such. DeadDefs.push_back(*RI); RI = Defs.erase(RI); continue; } } ++RI; } }
/// Record the upward impact of a single instruction on current register /// pressure. Unlike the advance/recede pressure tracking interface, this does /// not discover live in/outs. /// /// This is intended for speculative queries. It leaves pressure inconsistent /// with the current position, so must be restored by the caller. void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) { assert(!MI->isDebugValue() && "Expect a nondebug instruction."); // Account for register pressure similar to RegPressureTracker::recede(). RegisterOperands RegOpers(TRI, MRI, /*IgnoreDead=*/true); collectOperands(MI, RegOpers); // Boost max pressure for all dead defs together. // Since CurrSetPressure and MaxSetPressure increaseRegPressure(RegOpers.DeadDefs); decreaseRegPressure(RegOpers.DeadDefs); // Kill liveness at live defs. for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) { unsigned Reg = RegOpers.Defs[i]; bool DeadDef = false; if (RequireIntervals) { const LiveRange *LR = getLiveRange(Reg); if (LR) { SlotIndex SlotIdx = LIS->getInstructionIndex(MI); LiveQueryResult LRQ = LR->Query(SlotIdx); DeadDef = LRQ.isDeadDef(); } } if (!DeadDef) { if (!containsReg(RegOpers.Uses, Reg)) decreaseRegPressure(Reg); } } // Generate liveness for uses. for (unsigned i = 0, e = RegOpers.Uses.size(); i < e; ++i) { unsigned Reg = RegOpers.Uses[i]; if (!LiveRegs.contains(Reg)) increaseRegPressure(Reg); } }
/// Recede across the previous instruction. If LiveUses is provided, record any /// RegUnits that are made live by the current instruction's uses. This includes /// registers that are both defined and used by the instruction. If a pressure /// difference pointer is provided record the changes is pressure caused by this /// instruction independent of liveness. bool RegPressureTracker::recede(SmallVectorImpl<unsigned> *LiveUses, PressureDiff *PDiff) { // Check for the top of the analyzable region. if (CurrPos == MBB->begin()) { closeRegion(); return false; } if (!isBottomClosed()) closeBottom(); // Open the top of the region using block iterators. if (!RequireIntervals && isTopClosed()) static_cast<RegionPressure&>(P).openTop(CurrPos); // Find the previous instruction. do --CurrPos; while (CurrPos != MBB->begin() && CurrPos->isDebugValue()); if (CurrPos->isDebugValue()) { closeRegion(); return false; } SlotIndex SlotIdx; if (RequireIntervals) SlotIdx = LIS->getInstructionIndex(CurrPos).getRegSlot(); // Open the top of the region using slot indexes. if (RequireIntervals && isTopClosed()) static_cast<IntervalPressure&>(P).openTop(SlotIdx); RegisterOperands RegOpers(TRI, MRI); collectOperands(CurrPos, RegOpers); if (PDiff) collectPDiff(*PDiff, RegOpers, MRI); // Boost pressure for all dead defs together. increaseRegPressure(RegOpers.DeadDefs); decreaseRegPressure(RegOpers.DeadDefs); // Kill liveness at live defs. // TODO: consider earlyclobbers? for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) { unsigned Reg = RegOpers.Defs[i]; bool DeadDef = false; if (RequireIntervals) { const LiveRange *LR = getLiveRange(Reg); if (LR) { LiveQueryResult LRQ = LR->Query(SlotIdx); DeadDef = LRQ.isDeadDef(); } } if (DeadDef) { // LiveIntervals knows this is a dead even though it's MachineOperand is // not flagged as such. Since this register will not be recorded as // live-out, increase its PDiff value to avoid underflowing pressure. if (PDiff) PDiff->addPressureChange(Reg, false, MRI); } else { if (LiveRegs.erase(Reg)) decreaseRegPressure(Reg); else discoverLiveOut(Reg); } } // Generate liveness for uses. for (unsigned i = 0, e = RegOpers.Uses.size(); i < e; ++i) { unsigned Reg = RegOpers.Uses[i]; if (!LiveRegs.contains(Reg)) { // Adjust liveouts if LiveIntervals are available. if (RequireIntervals) { const LiveRange *LR = getLiveRange(Reg); if (LR) { LiveQueryResult LRQ = LR->Query(SlotIdx); if (!LRQ.isKill() && !LRQ.valueDefined()) discoverLiveOut(Reg); } } increaseRegPressure(Reg); LiveRegs.insert(Reg); if (LiveUses && !containsReg(*LiveUses, Reg)) LiveUses->push_back(Reg); } } if (TrackUntiedDefs) { for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) { unsigned Reg = RegOpers.Defs[i]; if (TargetRegisterInfo::isVirtualRegister(Reg) && !LiveRegs.contains(Reg)) UntiedDefs.insert(Reg); } } return true; }