void UserValue::computeIntervals(MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, LiveIntervals &LIS, MachineDominatorTree &MDT, UserValueScopes &UVS) { SmallVector<std::pair<SlotIndex, unsigned>, 16> Defs; // Collect all defs to be extended (Skipping undefs). for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) if (I.value() != ~0u) Defs.push_back(std::make_pair(I.start(), I.value())); // Extend all defs, and possibly add new ones along the way. for (unsigned i = 0; i != Defs.size(); ++i) { SlotIndex Idx = Defs[i].first; unsigned LocNo = Defs[i].second; const MachineOperand &Loc = locations[LocNo]; if (!Loc.isReg()) { extendDef(Idx, LocNo, nullptr, nullptr, nullptr, LIS, MDT, UVS); continue; } // Register locations are constrained to where the register value is live. if (TargetRegisterInfo::isVirtualRegister(Loc.getReg())) { LiveInterval *LI = nullptr; const VNInfo *VNI = nullptr; if (LIS.hasInterval(Loc.getReg())) { LI = &LIS.getInterval(Loc.getReg()); VNI = LI->getVNInfoAt(Idx); } SmallVector<SlotIndex, 16> Kills; extendDef(Idx, LocNo, LI, VNI, &Kills, LIS, MDT, UVS); if (LI) addDefsFromCopies(LI, LocNo, Kills, Defs, MRI, LIS); continue; } // For physregs, use the live range of the first regunit as a guide. unsigned Unit = *MCRegUnitIterator(Loc.getReg(), &TRI); LiveRange *LR = &LIS.getRegUnit(Unit); const VNInfo *VNI = LR->getVNInfoAt(Idx); // Don't track copies from physregs, it is too expensive. extendDef(Idx, LocNo, LR, VNI, nullptr, LIS, MDT, UVS); } // Finally, erase all the undefs. for (LocMap::iterator I = locInts.begin(); I.valid();) if (I.value() == ~0u) I.erase(); else ++I; }
/// MergeRangesInAsValue - Merge all of the intervals in RHS into this live /// interval as the specified value number. The LiveRanges in RHS are /// allowed to overlap with LiveRanges in the current interval, but only if /// the overlapping LiveRanges have the specified value number. void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo) { // TODO: Make this more efficient. iterator InsertPos = begin(); for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { // Map the valno in the other live range to the current live range. LiveRange Tmp = *I; Tmp.valno = LHSValNo; InsertPos = addRangeFrom(Tmp, InsertPos); } }
/// MergeValueInAsValue - Merge all of the live ranges of a specific val# /// in RHS into this live interval as the specified value number. /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the /// current interval, it will replace the value numbers of the overlaped /// live ranges with the specified value number. void LiveInterval::MergeValueInAsValue( const LiveInterval &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo) { SmallVector<VNInfo*, 4> ReplacedValNos; iterator IP = begin(); for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { assert(I->valno == RHS.getValNumInfo(I->valno->id) && "Bad VNInfo"); if (I->valno != RHSValNo) continue; SlotIndex Start = I->start, End = I->end; IP = std::upper_bound(IP, end(), Start); // If the start of this range overlaps with an existing liverange, trim it. if (IP != begin() && IP[-1].end > Start) { if (IP[-1].valno != LHSValNo) { ReplacedValNos.push_back(IP[-1].valno); IP[-1].valno = LHSValNo; // Update val#. } Start = IP[-1].end; // Trimmed away the whole range? if (Start >= End) continue; } // If the end of this range overlaps with an existing liverange, trim it. if (IP != end() && End > IP->start) { if (IP->valno != LHSValNo) { ReplacedValNos.push_back(IP->valno); IP->valno = LHSValNo; // Update val#. } End = IP->start; // If this trimmed away the whole range, ignore it. if (Start == End) continue; } // Map the valno in the other live range to the current live range. IP = addRangeFrom(LiveRange(Start, End, LHSValNo), IP); } SmallSet<VNInfo*, 4> Seen; for (unsigned i = 0, e = ReplacedValNos.size(); i != e; ++i) { VNInfo *V1 = ReplacedValNos[i]; if (Seen.insert(V1)) { bool isDead = true; for (const_iterator I = begin(), E = end(); I != E; ++I) if (I->valno == V1) { isDead = false; break; } if (isDead) { // Now that V1 is dead, remove it. markValNoForDeletion(V1); } } } }
bool LiveIntervals::checkRegMaskInterference(LiveInterval &LI, BitVector &UsableRegs) { if (LI.empty()) return false; LiveInterval::iterator LiveI = LI.begin(), LiveE = LI.end(); // Use a smaller arrays for local live ranges. ArrayRef<SlotIndex> Slots; ArrayRef<const uint32_t*> Bits; if (MachineBasicBlock *MBB = intervalIsInOneMBB(LI)) { Slots = getRegMaskSlotsInBlock(MBB->getNumber()); Bits = getRegMaskBitsInBlock(MBB->getNumber()); } else { Slots = getRegMaskSlots(); Bits = getRegMaskBits(); } // We are going to enumerate all the register mask slots contained in LI. // Start with a binary search of RegMaskSlots to find a starting point. ArrayRef<SlotIndex>::iterator SlotI = std::lower_bound(Slots.begin(), Slots.end(), LiveI->start); ArrayRef<SlotIndex>::iterator SlotE = Slots.end(); // No slots in range, LI begins after the last call. if (SlotI == SlotE) return false; bool Found = false; for (;;) { assert(*SlotI >= LiveI->start); // Loop over all slots overlapping this segment. while (*SlotI < LiveI->end) { // *SlotI overlaps LI. Collect mask bits. if (!Found) { // This is the first overlap. Initialize UsableRegs to all ones. UsableRegs.clear(); UsableRegs.resize(TRI->getNumRegs(), true); Found = true; } // Remove usable registers clobbered by this mask. UsableRegs.clearBitsNotInMask(Bits[SlotI-Slots.begin()]); if (++SlotI == SlotE) return Found; } // *SlotI is beyond the current LI segment. LiveI = LI.advanceTo(LiveI, *SlotI); if (LiveI == LiveE) return Found; // Advance SlotI until it overlaps. while (*SlotI < LiveI->start) if (++SlotI == SlotE) return Found; } }
bool LiveRegMatrix::checkRegUnitInterference(LiveInterval &VirtReg, unsigned PhysReg) { if (VirtReg.empty()) return false; CoalescerPair CP(VirtReg.reg, PhysReg, *TRI); for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { const LiveRange &UnitRange = LIS->getRegUnit(*Units); if (VirtReg.overlaps(UnitRange, CP, *LIS->getSlotIndexes())) return true; } return false; }
bool HexagonExpandCondsets::isIntraBlocks(LiveInterval &LI) { for (LiveInterval::iterator I = LI.begin(), E = LI.end(); I != E; ++I) { LiveRange::Segment &LR = *I; // Range must start at a register... if (!LR.start.isRegister()) return false; // ...and end in a register or in a dead slot. if (!LR.end.isRegister() && !LR.end.isDead()) return false; } return true; }
/// insertSpill - Insert a spill of NewLI.reg after MI. void InlineSpiller::insertSpill(LiveInterval &NewLI, const LiveInterval &OldLI, SlotIndex Idx, MachineBasicBlock::iterator MI) { MachineBasicBlock &MBB = *MI->getParent(); TII.storeRegToStackSlot(MBB, ++MI, NewLI.reg, true, StackSlot, MRI.getRegClass(NewLI.reg), &TRI); --MI; // Point to store instruction. SlotIndex StoreIdx = LIS.InsertMachineInstrInMaps(MI).getRegSlot(); DEBUG(dbgs() << "\tspilled: " << StoreIdx << '\t' << *MI); VNInfo *StoreVNI = NewLI.getNextValue(Idx, LIS.getVNInfoAllocator()); NewLI.addRange(LiveRange(Idx, StoreIdx, StoreVNI)); ++NumSpills; }
/// rewrite - after all the new live ranges have been created, rewrite /// instructions using curli to use the new intervals. void SplitEditor::rewrite() { assert(!openli_ && "Previous LI not closed before rewrite"); const LiveInterval *curli = sa_.getCurLI(); for (MachineRegisterInfo::reg_iterator RI = mri_.reg_begin(curli->reg), RE = mri_.reg_end(); RI != RE;) { MachineOperand &MO = RI.getOperand(); MachineInstr *MI = MO.getParent(); ++RI; if (MI->isDebugValue()) { DEBUG(dbgs() << "Zapping " << *MI); // FIXME: We can do much better with debug values. MO.setReg(0); continue; } SlotIndex Idx = lis_.getInstructionIndex(MI); Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex(); LiveInterval *LI = dupli_; for (unsigned i = firstInterval, e = intervals_.size(); i != e; ++i) { LiveInterval *testli = intervals_[i]; if (testli->liveAt(Idx)) { LI = testli; break; } } if (LI) { MO.setReg(LI->reg); sa_.removeUse(MI); DEBUG(dbgs() << " rewrite " << Idx << '\t' << *MI); } } // dupli_ goes in last, after rewriting. if (dupli_) { if (dupli_->empty()) { DEBUG(dbgs() << " dupli became empty?\n"); lis_.removeInterval(dupli_->reg); dupli_ = 0; } else { dupli_->RenumberValues(lis_); intervals_.push_back(dupli_); } } // Calculate spill weight and allocation hints for new intervals. VirtRegAuxInfo vrai(vrm_.getMachineFunction(), lis_, sa_.loops_); for (unsigned i = firstInterval, e = intervals_.size(); i != e; ++i) { LiveInterval &li = *intervals_[i]; vrai.CalculateRegClass(li.reg); vrai.CalculateWeightAndHint(li); DEBUG(dbgs() << " new interval " << mri_.getRegClass(li.reg)->getName() << ":" << li << '\n'); } }
// Check if all values in LI are rematerializable static bool isRematerializable(const LiveInterval &LI, const LiveIntervals &LIS, VirtRegMap *VRM, const TargetInstrInfo &TII) { unsigned Reg = LI.reg; unsigned Original = VRM ? VRM->getOriginal(Reg) : 0; for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end(); I != E; ++I) { const VNInfo *VNI = *I; if (VNI->isUnused()) continue; if (VNI->isPHIDef()) return false; MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def); assert(MI && "Dead valno in interval"); // Trace copies introduced by live range splitting. The inline // spiller can rematerialize through these copies, so the spill // weight must reflect this. if (VRM) { while (MI->isFullCopy()) { // The copy destination must match the interval register. if (MI->getOperand(0).getReg() != Reg) return false; // Get the source register. Reg = MI->getOperand(1).getReg(); // If the original (pre-splitting) registers match this // copy came from a split. if (!TargetRegisterInfo::isVirtualRegister(Reg) || VRM->getOriginal(Reg) != Original) return false; // Follow the copy live-in value. const LiveInterval &SrcLI = LIS.getInterval(Reg); LiveQueryResult SrcQ = SrcLI.Query(VNI->def); VNI = SrcQ.valueIn(); assert(VNI && "Copy from non-existing value"); if (VNI->isPHIDef()) return false; MI = LIS.getInstructionFromIndex(VNI->def); assert(MI && "Dead valno in interval"); } } if (!TII.isTriviallyReMaterializable(*MI, LIS.getAliasAnalysis())) return false; } return true; }
/// insertSpill - Insert a spill of NewLI.reg after MI. void InlineSpiller::insertSpill(LiveInterval &NewLI, MachineBasicBlock::iterator MI) { MachineBasicBlock &MBB = *MI->getParent(); SlotIndex Idx = lis_.getInstructionIndex(MI).getDefIndex(); tii_.storeRegToStackSlot(MBB, ++MI, NewLI.reg, true, stackSlot_, rc_, &tri_); --MI; // Point to store instruction. SlotIndex StoreIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex(); vrm_.addSpillSlotUse(stackSlot_, MI); DEBUG(dbgs() << "\tspilled: " << StoreIdx << '\t' << *MI); VNInfo *StoreVNI = NewLI.getNextValue(Idx, 0, true, lis_.getVNInfoAllocator()); NewLI.addRange(LiveRange(Idx, StoreIdx, StoreVNI)); }
/// insertReload - Insert a reload of NewLI.reg before MI. void InlineSpiller::insertReload(LiveInterval &NewLI, MachineBasicBlock::iterator MI) { MachineBasicBlock &MBB = *MI->getParent(); SlotIndex Idx = lis_.getInstructionIndex(MI).getDefIndex(); tii_.loadRegFromStackSlot(MBB, MI, NewLI.reg, stackSlot_, rc_, &tri_); --MI; // Point to load instruction. SlotIndex LoadIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex(); vrm_.addSpillSlotUse(stackSlot_, MI); DEBUG(dbgs() << "\treload: " << LoadIdx << '\t' << *MI); VNInfo *LoadVNI = NewLI.getNextValue(LoadIdx, 0, true, lis_.getVNInfoAllocator()); NewLI.addRange(LiveRange(LoadIdx, Idx, LoadVNI)); }
/// computeVirtRegInterval - Compute the live interval of a virtual register, /// based on defs and uses. void LiveIntervals::computeVirtRegInterval(LiveInterval &LI) { assert(LRCalc && "LRCalc not initialized."); assert(LI.empty() && "Should only compute empty intervals."); LRCalc->reset(MF, getSlotIndexes(), DomTree, &getVNInfoAllocator()); LRCalc->createDeadDefs(LI); LRCalc->extendToUses(LI); }
/// join - Join two live intervals (this, and other) together. This operation /// is the result of a copy instruction in the source program, that occurs at /// index 'CopyIdx' that copies from 'Other' to 'this'. void LiveInterval::join(LiveInterval &Other, unsigned CopyIdx) { const LiveRange *SourceLR = Other.getLiveRangeContaining(CopyIdx-1); const LiveRange *DestLR = getLiveRangeContaining(CopyIdx); assert(SourceLR && DestLR && "Not joining due to a copy?"); unsigned MergedSrcValIdx = SourceLR->ValId; unsigned MergedDstValIdx = DestLR->ValId; // Try to do the least amount of work possible. In particular, if there are // more liverange chunks in the other set than there are in the 'this' set, // swap sets to merge the fewest chunks in possible. if (Other.ranges.size() > ranges.size()) { std::swap(MergedSrcValIdx, MergedDstValIdx); std::swap(ranges, Other.ranges); std::swap(NumValues, Other.NumValues); } // Join the ranges of other into the ranges of this interval. Ranges::iterator InsertPos = ranges.begin(); std::map<unsigned, unsigned> Dst2SrcIdxMap; for (Ranges::iterator I = Other.ranges.begin(), E = Other.ranges.end(); I != E; ++I) { // Map the ValId in the other live range to the current live range. if (I->ValId == MergedSrcValIdx) I->ValId = MergedDstValIdx; else { unsigned &NV = Dst2SrcIdxMap[I->ValId]; if (NV == 0) NV = getNextValue(); I->ValId = NV; } InsertPos = addRangeFrom(*I, InsertPos); } weight += Other.weight; }
void LiveInterval::Copy(const LiveInterval &RHS, BumpPtrAllocator &VNInfoAllocator) { ranges.clear(); valnos.clear(); preference = RHS.preference; weight = RHS.weight; for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) { const VNInfo *VNI = RHS.getValNumInfo(i); VNInfo *NewVNI = getNextValue(~0U, 0, VNInfoAllocator); copyValNumInfo(NewVNI, VNI); } for (unsigned i = 0, e = RHS.ranges.size(); i != e; ++i) { const LiveRange &LR = RHS.ranges[i]; addRange(LiveRange(LR.start, LR.end, getValNumInfo(LR.valno->id))); } }
static bool subRangeLiveAt(const LiveInterval &LI, SlotIndex Pos) { for (const LiveInterval::SubRange &SR : LI.subranges()) { if (SR.liveAt(Pos)) return true; } return false; }
// Merge a LiveInterval's segments. Guarantee no overlaps. void LiveIntervalUnion::unify(LiveInterval &VirtReg) { if (VirtReg.empty()) return; // Insert each of the virtual register's live segments into the map. LiveInterval::iterator RegPos = VirtReg.begin(); LiveInterval::iterator RegEnd = VirtReg.end(); SegmentIter SegPos = Segments.find(RegPos->start); for (;;) { SegPos.insert(RegPos->start, RegPos->end, &VirtReg); if (++RegPos == RegEnd) return; SegPos.advanceTo(RegPos->start); } }
/// computeVirtRegInterval - Compute the live interval of a virtual register, /// based on defs and uses. void LiveIntervals::computeVirtRegInterval(LiveInterval &LI) { assert(LRCalc && "LRCalc not initialized."); assert(LI.empty() && "Should only compute empty intervals."); LRCalc->reset(MF, getSlotIndexes(), DomTree, &getVNInfoAllocator()); LRCalc->calculate(LI); computeDeadValues(LI, nullptr); }
void StackColoring::removeInvalidSlotRanges() { MachineFunction::const_iterator BB, BBE; MachineBasicBlock::const_iterator I, IE; for (BB = MF->begin(), BBE = MF->end(); BB != BBE; ++BB) for (I = BB->begin(), IE = BB->end(); I != IE; ++I) { if (I->getOpcode() == TargetOpcode::LIFETIME_START || I->getOpcode() == TargetOpcode::LIFETIME_END || I->isDebugValue()) continue; // Some intervals are suspicious! In some cases we find address // calculations outside of the lifetime zone, but not actual memory // read or write. Memory accesses outside of the lifetime zone are a clear // violation, but address calculations are okay. This can happen when // GEPs are hoisted outside of the lifetime zone. // So, in here we only check instructions which can read or write memory. if (!I->mayLoad() && !I->mayStore()) continue; // Check all of the machine operands. for (unsigned i = 0 ; i < I->getNumOperands(); ++i) { const MachineOperand &MO = I->getOperand(i); if (!MO.isFI()) continue; int Slot = MO.getIndex(); if (Slot<0) continue; if (Intervals[Slot]->empty()) continue; // Check that the used slot is inside the calculated lifetime range. // If it is not, warn about it and invalidate the range. LiveInterval *Interval = Intervals[Slot]; SlotIndex Index = Indexes->getInstructionIndex(I); if (Interval->find(Index) == Interval->end()) { Intervals[Slot]->clear(); DEBUG(dbgs()<<"Invalidating range #"<<Slot<<"\n"); EscapedAllocas++; } } } }
/// insertReload - Insert a reload of NewLI.reg before MI. void InlineSpiller::insertReload(LiveInterval &NewLI, SlotIndex Idx, MachineBasicBlock::iterator MI) { MachineBasicBlock &MBB = *MI->getParent(); TII.loadRegFromStackSlot(MBB, MI, NewLI.reg, StackSlot, MRI.getRegClass(NewLI.reg), &TRI); --MI; // Point to load instruction. SlotIndex LoadIdx = LIS.InsertMachineInstrInMaps(MI).getRegSlot(); // Some (out-of-tree) targets have EC reload instructions. if (MachineOperand *MO = MI->findRegisterDefOperand(NewLI.reg)) if (MO->isEarlyClobber()) LoadIdx = LoadIdx.getRegSlot(true); DEBUG(dbgs() << "\treload: " << LoadIdx << '\t' << *MI); VNInfo *LoadVNI = NewLI.getNextValue(LoadIdx, LIS.getVNInfoAllocator()); NewLI.addRange(LiveRange(LoadIdx, Idx, LoadVNI)); ++NumReloads; }
/// Given an updated live interval LI for register Reg, update the kill flags /// in instructions using Reg to reflect the liveness changes. void HexagonExpandCondsets::updateKillFlags(unsigned Reg, LiveInterval &LI) { MRI->clearKillFlags(Reg); for (LiveInterval::iterator I = LI.begin(), E = LI.end(); I != E; ++I) { SlotIndex EX = I->end; if (!EX.isRegister()) continue; MachineInstr *MI = LIS->getInstructionFromIndex(EX); for (auto &Op : MI->operands()) { if (!Op.isReg() || !Op.isUse() || Op.getReg() != Reg) continue; // Only set the kill flag on the first encountered use of Reg in this // instruction. Op.setIsKill(true); break; } } }
void LiveInterval::Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI, VNInfo::Allocator &VNInfoAllocator) { ranges.clear(); valnos.clear(); std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(RHS.reg); MRI->setRegAllocationHint(reg, Hint.first, Hint.second); weight = RHS.weight; for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) { const VNInfo *VNI = RHS.getValNumInfo(i); createValueCopy(VNI, VNInfoAllocator); } for (unsigned i = 0, e = RHS.ranges.size(); i != e; ++i) { const LiveRange &LR = RHS.ranges[i]; addRange(LiveRange(LR.start, LR.end, getValNumInfo(LR.valno->id))); } }
bool LiveIntervals::hasPHIKill(const LiveInterval &LI, const VNInfo *VNI) const { for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end(); I != E; ++I) { const VNInfo *PHI = *I; if (PHI->isUnused() || !PHI->isPHIDef()) continue; const MachineBasicBlock *PHIMBB = getMBBFromIndex(PHI->def); // Conservatively return true instead of scanning huge predecessor lists. if (PHIMBB->pred_size() > 100) return true; for (MachineBasicBlock::const_pred_iterator PI = PHIMBB->pred_begin(), PE = PHIMBB->pred_end(); PI != PE; ++PI) if (VNI == LI.getVNInfoBefore(Indexes->getMBBEndIdx(*PI))) return true; } return false; }
void VirtRegRewriter::addLiveInsForSubRanges(const LiveInterval &LI, unsigned PhysReg) const { assert(!LI.empty()); assert(LI.hasSubRanges()); using SubRangeIteratorPair = std::pair<const LiveInterval::SubRange *, LiveInterval::const_iterator>; SmallVector<SubRangeIteratorPair, 4> SubRanges; SlotIndex First; SlotIndex Last; for (const LiveInterval::SubRange &SR : LI.subranges()) { SubRanges.push_back(std::make_pair(&SR, SR.begin())); if (!First.isValid() || SR.segments.front().start < First) First = SR.segments.front().start; if (!Last.isValid() || SR.segments.back().end > Last) Last = SR.segments.back().end; } // Check all mbb start positions between First and Last while // simulatenously advancing an iterator for each subrange. for (SlotIndexes::MBBIndexIterator MBBI = Indexes->findMBBIndex(First); MBBI != Indexes->MBBIndexEnd() && MBBI->first <= Last; ++MBBI) { SlotIndex MBBBegin = MBBI->first; // Advance all subrange iterators so that their end position is just // behind MBBBegin (or the iterator is at the end). LaneBitmask LaneMask; for (auto &RangeIterPair : SubRanges) { const LiveInterval::SubRange *SR = RangeIterPair.first; LiveInterval::const_iterator &SRI = RangeIterPair.second; while (SRI != SR->end() && SRI->end <= MBBBegin) ++SRI; if (SRI == SR->end()) continue; if (SRI->start <= MBBBegin) LaneMask |= SR->LaneMask; } if (LaneMask.none()) continue; MachineBasicBlock *MBB = MBBI->second; MBB->addLiveIn(PhysReg, LaneMask); } }
void RegAllocPBQP::findVRegIntervalsToAlloc() { // Iterate over all live ranges. for (unsigned i = 0, e = mri->getNumVirtRegs(); i != e; ++i) { unsigned Reg = TargetRegisterInfo::index2VirtReg(i); if (mri->reg_nodbg_empty(Reg)) continue; LiveInterval *li = &lis->getInterval(Reg); // If this live interval is non-empty we will use pbqp to allocate it. // Empty intervals we allocate in a simple post-processing stage in // finalizeAlloc. if (!li->empty()) { vregsToAlloc.insert(li->reg); } else { emptyIntervalVRegs.insert(li->reg); } } }
void SplitEditor::removeBackCopies(SmallVectorImpl<VNInfo*> &Copies) { LiveInterval *LI = Edit->get(0); DEBUG(dbgs() << "Removing " << Copies.size() << " back-copies.\n"); RegAssignMap::iterator AssignI; AssignI.setMap(RegAssign); for (unsigned i = 0, e = Copies.size(); i != e; ++i) { VNInfo *VNI = Copies[i]; SlotIndex Def = VNI->def; MachineInstr *MI = LIS.getInstructionFromIndex(Def); assert(MI && "No instruction for back-copy"); MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::iterator MBBI(MI); bool AtBegin; do AtBegin = MBBI == MBB->begin(); while (!AtBegin && (--MBBI)->isDebugValue()); DEBUG(dbgs() << "Removing " << Def << '\t' << *MI); LI->removeValNo(VNI); LIS.RemoveMachineInstrFromMaps(MI); MI->eraseFromParent(); // Adjust RegAssign if a register assignment is killed at VNI->def. We // want to avoid calculating the live range of the source register if // possible. AssignI.find(VNI->def.getPrevSlot()); if (!AssignI.valid() || AssignI.start() >= Def) continue; // If MI doesn't kill the assigned register, just leave it. if (AssignI.stop() != Def) continue; unsigned RegIdx = AssignI.value(); if (AtBegin || !MBBI->readsVirtualRegister(Edit->getReg())) { DEBUG(dbgs() << " cannot find simple kill of RegIdx " << RegIdx << '\n'); forceRecompute(RegIdx, Edit->getParent().getVNInfoAt(Def)); } else { SlotIndex Kill = LIS.getInstructionIndex(MBBI).getDefIndex(); DEBUG(dbgs() << " move kill to " << Kill << '\t' << *MBBI); AssignI.setStop(Kill); } } }
// Check if all values in LI are rematerializable static bool isRematerializable(const LiveInterval &LI, const LiveIntervals &LIS, const TargetInstrInfo &TII) { for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end(); I != E; ++I) { const VNInfo *VNI = *I; if (VNI->isUnused()) continue; if (VNI->isPHIDef()) return false; MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def); assert(MI && "Dead valno in interval"); if (!TII.isTriviallyReMaterializable(MI, LIS.getAliasAnalysis())) return false; } return true; }
bool RenameIndependentSubregs::findComponents(IntEqClasses &Classes, SmallVectorImpl<RenameIndependentSubregs::SubRangeInfo> &SubRangeInfos, LiveInterval &LI) const { // First step: Create connected components for the VNInfos inside the // subranges and count the global number of such components. unsigned NumComponents = 0; for (LiveInterval::SubRange &SR : LI.subranges()) { SubRangeInfos.push_back(SubRangeInfo(*LIS, SR, NumComponents)); ConnectedVNInfoEqClasses &ConEQ = SubRangeInfos.back().ConEQ; unsigned NumSubComponents = ConEQ.Classify(SR); NumComponents += NumSubComponents; } // Shortcut: With only 1 subrange, the normal separate component tests are // enough and we do not need to perform the union-find on the subregister // segments. if (SubRangeInfos.size() < 2) return false; // Next step: Build union-find structure over all subranges and merge classes // across subranges when they are affected by the same MachineOperand. const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo(); Classes.grow(NumComponents); unsigned Reg = LI.reg; for (const MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) { if (!MO.isDef() && !MO.readsReg()) continue; unsigned SubRegIdx = MO.getSubReg(); LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubRegIdx); unsigned MergedID = ~0u; for (RenameIndependentSubregs::SubRangeInfo &SRInfo : SubRangeInfos) { const LiveInterval::SubRange &SR = *SRInfo.SR; if ((SR.LaneMask & LaneMask) == 0) continue; SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent()); Pos = MO.isDef() ? Pos.getRegSlot(MO.isEarlyClobber()) : Pos.getBaseIndex(); const VNInfo *VNI = SR.getVNInfoAt(Pos); if (VNI == nullptr) continue; // Map to local representant ID. unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI); // Global ID unsigned ID = LocalID + SRInfo.Index; // Merge other sets MergedID = MergedID == ~0u ? ID : Classes.join(MergedID, ID); } } // Early exit if we ended up with a single equivalence class. Classes.compress(); unsigned NumClasses = Classes.getNumClasses(); return NumClasses > 1; }
static void determineMissingVNIs(const SlotIndexes &Indexes, LiveInterval &LI) { SmallPtrSet<const MachineBasicBlock*, 5> Visited; LiveRange::iterator OutIt; VNInfo *PrevValNo = nullptr; for (LiveRange::iterator I = LI.begin(), E = LI.end(); I != E; ++I) { LiveRange::Segment &S = *I; // Determine final VNI if necessary. if (S.valno == nullptr) { // This can only happen at the begin of a basic block. assert(S.start.isBlock() && "valno should only be missing at block begin"); Visited.clear(); const MachineBasicBlock *MBB = Indexes.getMBBFromIndex(S.start); for (const MachineBasicBlock *Pred : MBB->predecessors()) { VNInfo *VNI = searchForVNI(Indexes, LI, Pred, Visited); if (VNI != nullptr) { S.valno = VNI; break; } } assert(S.valno != nullptr && "could not determine valno"); } // Merge with previous segment if it has the same VNI. if (PrevValNo == S.valno && OutIt->end == S.start) { OutIt->end = S.end; } else { // Didn't merge. Move OutIt to next segment. if (PrevValNo == nullptr) OutIt = LI.begin(); else ++OutIt; if (OutIt != I) *OutIt = *I; PrevValNo = S.valno; } } // If we merged some segments chop off the end. ++OutIt; LI.segments.erase(OutIt, LI.end()); }
/// computeLiveInRegUnits - Precompute the live ranges of any register units /// that are live-in to an ABI block somewhere. Register values can appear /// without a corresponding def when entering the entry block or a landing pad. /// void LiveIntervals::computeLiveInRegUnits() { RegUnitIntervals.resize(TRI->getNumRegUnits()); DEBUG(dbgs() << "Computing live-in reg-units in ABI blocks.\n"); // Keep track of the intervals allocated. SmallVector<LiveInterval*, 8> NewIntvs; // Check all basic blocks for live-ins. for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); MFI != MFE; ++MFI) { const MachineBasicBlock *MBB = MFI; // We only care about ABI blocks: Entry + landing pads. if ((MFI != MF->begin() && !MBB->isLandingPad()) || MBB->livein_empty()) continue; // Create phi-defs at Begin for all live-in registers. SlotIndex Begin = Indexes->getMBBStartIdx(MBB); DEBUG(dbgs() << Begin << "\tBB#" << MBB->getNumber()); for (MachineBasicBlock::livein_iterator LII = MBB->livein_begin(), LIE = MBB->livein_end(); LII != LIE; ++LII) { for (MCRegUnitIterator Units(*LII, TRI); Units.isValid(); ++Units) { unsigned Unit = *Units; LiveInterval *Intv = RegUnitIntervals[Unit]; if (!Intv) { Intv = RegUnitIntervals[Unit] = new LiveInterval(Unit, HUGE_VALF); NewIntvs.push_back(Intv); } VNInfo *VNI = Intv->createDeadDef(Begin, getVNInfoAllocator()); (void)VNI; DEBUG(dbgs() << ' ' << PrintRegUnit(Unit, TRI) << '#' << VNI->id); } } DEBUG(dbgs() << '\n'); } DEBUG(dbgs() << "Created " << NewIntvs.size() << " new intervals.\n"); // Compute the 'normal' part of the intervals. for (unsigned i = 0, e = NewIntvs.size(); i != e; ++i) computeRegUnitInterval(NewIntvs[i]); }
void StackColoring::removeInvalidSlotRanges() { for (MachineBasicBlock &BB : *MF) for (MachineInstr &I : BB) { if (I.getOpcode() == TargetOpcode::LIFETIME_START || I.getOpcode() == TargetOpcode::LIFETIME_END || I.isDebugValue()) continue; // Some intervals are suspicious! In some cases we find address // calculations outside of the lifetime zone, but not actual memory // read or write. Memory accesses outside of the lifetime zone are a clear // violation, but address calculations are okay. This can happen when // GEPs are hoisted outside of the lifetime zone. // So, in here we only check instructions which can read or write memory. if (!I.mayLoad() && !I.mayStore()) continue; // Check all of the machine operands. for (const MachineOperand &MO : I.operands()) { if (!MO.isFI()) continue; int Slot = MO.getIndex(); if (Slot<0) continue; if (Intervals[Slot]->empty()) continue; // Check that the used slot is inside the calculated lifetime range. // If it is not, warn about it and invalidate the range. LiveInterval *Interval = &*Intervals[Slot]; SlotIndex Index = Indexes->getInstructionIndex(I); if (Interval->find(Index) == Interval->end()) { Interval->clear(); DEBUG(dbgs()<<"Invalidating range #"<<Slot<<"\n"); EscapedAllocas++; } } } }