/// eliminateRedundantSpills - SLI:VNI is known to be on the stack. Remove any /// redundant spills of this value in SLI.reg and sibling copies. void InlineSpiller::eliminateRedundantSpills(LiveInterval &SLI, VNInfo *VNI) { assert(VNI && "Missing value"); SmallVector<std::pair<LiveInterval*, VNInfo*>, 8> WorkList; WorkList.push_back(std::make_pair(&SLI, VNI)); assert(StackInt && "No stack slot assigned yet."); do { LiveInterval *LI; tie(LI, VNI) = WorkList.pop_back_val(); unsigned Reg = LI->reg; DEBUG(dbgs() << "Checking redundant spills for " << VNI->id << '@' << VNI->def << " in " << *LI << '\n'); // Regs to spill are taken care of. if (isRegToSpill(Reg)) continue; // Add all of VNI's live range to StackInt. StackInt->MergeValueInAsValue(*LI, VNI, StackInt->getValNumInfo(0)); DEBUG(dbgs() << "Merged to stack int: " << *StackInt << '\n'); // Find all spills and copies of VNI. for (MachineRegisterInfo::use_nodbg_iterator UI = MRI.use_nodbg_begin(Reg); MachineInstr *MI = UI.skipInstruction();) { if (!MI->isCopy() && !MI->mayStore()) continue; SlotIndex Idx = LIS.getInstructionIndex(MI); if (LI->getVNInfoAt(Idx) != VNI) continue; // Follow sibling copies down the dominator tree. if (unsigned DstReg = isFullCopyOf(MI, Reg)) { if (isSibling(DstReg)) { LiveInterval &DstLI = LIS.getInterval(DstReg); VNInfo *DstVNI = DstLI.getVNInfoAt(Idx.getRegSlot()); assert(DstVNI && "Missing defined value"); assert(DstVNI->def == Idx.getRegSlot() && "Wrong copy def slot"); WorkList.push_back(std::make_pair(&DstLI, DstVNI)); } continue; } // Erase spills. int FI; if (Reg == TII.isStoreToStackSlot(MI, FI) && FI == StackSlot) { DEBUG(dbgs() << "Redundant spill " << Idx << '\t' << *MI); // eliminateDeadDefs won't normally remove stores, so switch opcode. MI->setDesc(TII.get(TargetOpcode::KILL)); DeadDefs.push_back(MI); ++NumSpillsRemoved; --NumSpills; } } } while (!WorkList.empty()); }
/// Helper to find a vreg use between two indices [PriorUseIdx, NextUseIdx). static bool findUseBetween(unsigned Reg, SlotIndex PriorUseIdx, SlotIndex NextUseIdx, const MachineRegisterInfo *MRI, const LiveIntervals *LIS) { for (MachineRegisterInfo::use_nodbg_iterator UI = MRI->use_nodbg_begin(Reg), UE = MRI->use_nodbg_end(); UI != UE; UI.skipInstruction()) { const MachineInstr* MI = &*UI; SlotIndex InstSlot = LIS->getInstructionIndex(MI).getRegSlot(); if (InstSlot >= PriorUseIdx && InstSlot < NextUseIdx) return true; } return false; }
/// reMaterializeAll - Try to rematerialize as many uses of li_ as possible, /// and trim the live ranges after. void InlineSpiller::reMaterializeAll() { // Do a quick scan of the interval values to find if any are remattable. reMattable_.clear(); usedValues_.clear(); for (LiveInterval::const_vni_iterator I = li_->vni_begin(), E = li_->vni_end(); I != E; ++I) { VNInfo *VNI = *I; if (VNI->isUnused() || !VNI->isDefAccurate()) continue; MachineInstr *DefMI = lis_.getInstructionFromIndex(VNI->def); if (!DefMI || !tii_.isTriviallyReMaterializable(DefMI)) continue; reMattable_.insert(VNI); } // Often, no defs are remattable. if (reMattable_.empty()) return; // Try to remat before all uses of li_->reg. bool anyRemat = false; for (MachineRegisterInfo::use_nodbg_iterator RI = mri_.use_nodbg_begin(li_->reg); MachineInstr *MI = RI.skipInstruction();) anyRemat |= reMaterializeFor(MI); if (!anyRemat) return; // Remove any values that were completely rematted. bool anyRemoved = false; for (SmallPtrSet<VNInfo*, 8>::iterator I = reMattable_.begin(), E = reMattable_.end(); I != E; ++I) { VNInfo *VNI = *I; if (VNI->hasPHIKill() || usedValues_.count(VNI)) continue; MachineInstr *DefMI = lis_.getInstructionFromIndex(VNI->def); DEBUG(dbgs() << "\tremoving dead def: " << VNI->def << '\t' << *DefMI); lis_.RemoveMachineInstrFromMaps(DefMI); vrm_.RemoveMachineInstrFromMaps(DefMI); DefMI->eraseFromParent(); VNI->setIsDefAccurate(false); anyRemoved = true; } if (!anyRemoved) return; // Removing values may cause debug uses where li_ is not live. for (MachineRegisterInfo::use_iterator RI = mri_.use_begin(li_->reg); MachineInstr *MI = RI.skipInstruction();) { if (!MI->isDebugValue()) continue; // Try to preserve the debug value if li_ is live immediately after it. MachineBasicBlock::iterator NextMI = MI; ++NextMI; if (NextMI != MI->getParent()->end() && !lis_.isNotInMIMap(NextMI)) { VNInfo *VNI = li_->getVNInfoAt(lis_.getInstructionIndex(NextMI)); if (VNI && (VNI->hasPHIKill() || usedValues_.count(VNI))) continue; } DEBUG(dbgs() << "Removing debug info due to remat:" << "\t" << *MI); MI->eraseFromParent(); } }