Transpose the calculation of spill weights such that we are calculating one

register at a time. This turns out to be slightly faster than iterating over
instructions, but more importantly, it allows us to compute spill weights for
new registers created after the spill weight pass has run.

Also compute the allocation hint at the same time as the spill weight. This
allows us to use the spill weight as a cost metric for copies, and choose the
most profitable hint if there is more than one possibility.

The new hints provide a very small (< 0.1%) but universal code size improvement.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110631 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2010-08-10 00:02:26 +00:00
parent 533a7df02d
commit df30cf9e61
7 changed files with 169 additions and 116 deletions

View File

@ -12,10 +12,35 @@
#define LLVM_CODEGEN_CALCSPILLWEIGHTS_H
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/ADT/DenseMap.h"
namespace llvm {
class LiveInterval;
class LiveIntervals;
class MachineLoopInfo;
/// VirtRegAuxInfo - Calculate auxiliary information for a virtual
/// register such as its spill weight and allocation hint.
class VirtRegAuxInfo {
MachineFunction &mf_;
LiveIntervals &lis_;
MachineLoopInfo &loops_;
DenseMap<unsigned, float> hint_;
public:
VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis,
MachineLoopInfo &loops) :
mf_(mf), lis_(lis), loops_(loops) {}
/// CalculateRegClass - recompute the register class for li from its uses.
/// Since the register class can affect the allocation hint, this function
/// should be called before CalculateWeightAndHint if both are called.
void CalculateRegClass(LiveInterval &li);
/// CalculateWeightAndHint - (re)compute li's spill weight and allocation
/// hint.
void CalculateWeightAndHint(LiveInterval &li);
};
/// CalculateSpillWeights - Compute spill weights for all virtual register
/// live intervals.
@ -27,7 +52,7 @@ namespace llvm {
virtual void getAnalysisUsage(AnalysisUsage &au) const;
virtual bool runOnMachineFunction(MachineFunction &fn);
virtual bool runOnMachineFunction(MachineFunction &fn);
private:
/// Returns true if the given live interval is zero length.

View File

@ -520,6 +520,15 @@ namespace llvm {
///
unsigned getSize() const;
/// Returns true if the live interval is zero length, i.e. no live ranges
/// span instructions. It doesn't pay to spill such an interval.
bool isZeroLength() const {
for (const_iterator i = begin(), e = end(); i != e; ++i)
if (i->end.getPrevIndex() > i->start)
return false;
return true;
}
/// isSpillable - Can this interval be spilled?
bool isSpillable() const {
return weight != HUGE_VALF;

View File

@ -105,6 +105,12 @@ namespace llvm {
return r2iMap_.count(reg);
}
/// isAllocatable - is the physical register reg allocatable in the current
/// function?
bool isAllocatable(unsigned reg) const {
return allocatableRegs_.test(reg);
}
/// 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.