diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 8efcbee2908..ebbcf63b700 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -75,6 +75,9 @@ namespace llvm { /// and MBB id. std::vector Idx2MBBMap; + /// FunctionSize - The number of instructions present in the function + uint64_t FunctionSize; + typedef std::map Mi2IndexMap; Mi2IndexMap mi2iMap_; @@ -169,11 +172,18 @@ namespace llvm { return MBB2IdxMap[MBBNo].second; } - /// getIntervalSize - get the size of an interval in "units," + /// getScaledIntervalSize - get the size of an interval in "units," /// where every function is composed of one thousand units. This /// measure scales properly with empty index slots in the function. - unsigned getScaledIntervalSize(LiveInterval& I) const { - return (1000 / InstrSlots::NUM * I.getSize()) / i2miMap_.size(); + double getScaledIntervalSize(LiveInterval& I) { + return (1000.0 / InstrSlots::NUM * I.getSize()) / i2miMap_.size(); + } + + /// getApproximateInstructionCount - computes an estimate of the number + /// of instructions in a given LiveInterval. + unsigned getApproximateInstructionCount(LiveInterval& I) { + double IntervalPercentage = getScaledIntervalSize(I) / 1000.0; + return IntervalPercentage * FunctionSize; } /// getMBBFromIndex - given an index in any instruction of an diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index f57cd2b7d18..295a1615b69 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -87,6 +87,8 @@ void LiveIntervals::computeNumbering() { mi2iMap_.clear(); i2miMap_.clear(); + FunctionSize = 0; + // Number MachineInstrs and MachineBasicBlocks. // Initialize MBB indexes to a sentinal. MBB2IdxMap.resize(mf_->getNumBlockIDs(), std::make_pair(~0U,~0U)); @@ -102,6 +104,8 @@ void LiveIntervals::computeNumbering() { assert(inserted && "multiple MachineInstr -> index mappings"); i2miMap_.push_back(I); MIIndex += InstrSlots::NUM; + + FunctionSize++; } if (StartIdx == MIIndex) { @@ -1789,7 +1793,7 @@ addIntervalsForSpills(const LiveInterval &li, for (unsigned i = 0, e = NewLIs.size(); i != e; ++i) { LiveInterval *LI = NewLIs[i]; if (!LI->empty()) { - LI->weight /= LI->getSize(); + LI->weight /= getApproximateInstructionCount(*LI); if (!AddedKill.count(LI)) { LiveRange *LR = &LI->ranges[LI->ranges.size()-1]; unsigned LastUseIdx = getBaseIndex(LR->end); diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index a26924be627..4df172d40c7 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -851,7 +851,8 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) if (minWeight == HUGE_VALF) { // All registers must have inf weight. Just grab one! minReg = BestPhysReg ? BestPhysReg : *RC->allocation_order_begin(*mf_); - if (cur->weight == HUGE_VALF || cur->getSize() == 1) + if (cur->weight == HUGE_VALF || + li_->getApproximateInstructionCount(*cur) == 1) // Spill a physical register around defs and uses. li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_); } diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 5b7f55dfc9a..29e634b477d 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -851,8 +851,8 @@ SimpleRegisterCoalescing::isProfitableToCoalesceToSubRC(unsigned SrcReg, // Then make sure the intervals are *short*. LiveInterval &SrcInt = li_->getInterval(SrcReg); LiveInterval &DstInt = li_->getInterval(DstReg); - unsigned SrcSize = SrcInt.getSize() / InstrSlots::NUM; - unsigned DstSize = DstInt.getSize() / InstrSlots::NUM; + unsigned SrcSize = li_->getApproximateInstructionCount(SrcInt); + unsigned DstSize = li_->getApproximateInstructionCount(DstInt); const TargetRegisterClass *RC = mri_->getRegClass(DstReg); unsigned Threshold = allocatableRCRegs_[RC].count() * 2; return (SrcSize + DstSize) <= Threshold; @@ -1011,10 +1011,10 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { if (SubIdx) { unsigned LargeReg = isExtSubReg ? SrcReg : DstReg; unsigned SmallReg = isExtSubReg ? DstReg : SrcReg; - unsigned LargeRegSize = - li_->getInterval(LargeReg).getSize() / InstrSlots::NUM; - unsigned SmallRegSize = - li_->getInterval(SmallReg).getSize() / InstrSlots::NUM; + unsigned LargeRegSize = + li_->getApproximateInstructionCount(li_->getInterval(LargeReg)); + unsigned SmallRegSize = + li_->getApproximateInstructionCount(li_->getInterval(SmallReg)); const TargetRegisterClass *RC = mri_->getRegClass(SmallReg); unsigned Threshold = allocatableRCRegs_[RC].count(); // Be conservative. If both sides are virtual registers, do not coalesce @@ -1081,7 +1081,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // If the virtual register live interval is long but it has low use desity, // do not join them, instead mark the physical register as its allocation // preference. - unsigned Length = JoinVInt.getSize() / InstrSlots::NUM; + unsigned Length = li_->getApproximateInstructionCount(JoinVInt); if (Length > Threshold && (((float)std::distance(mri_->use_begin(JoinVReg), mri_->use_end()) / Length) < (1.0 / Threshold))) { @@ -2196,7 +2196,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { // Divide the weight of the interval by its size. This encourages // spilling of intervals that are large and have few uses, and // discourages spilling of small intervals with many uses. - LI.weight /= LI.getSize(); + LI.weight /= li_->getApproximateInstructionCount(LI); } } diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h index 3a65a9f4dd7..de16fa15356 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/lib/CodeGen/SimpleRegisterCoalescing.h @@ -126,7 +126,7 @@ namespace llvm { unsigned getRepIntervalSize(unsigned Reg) { if (!li_->hasInterval(Reg)) return 0; - return li_->getInterval(Reg).getSize(); + return li_->getApproximateInstructionCount(li_->getInterval(Reg)); } /// print - Implement the dump method.