diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 38 | ||||
-rw-r--r-- | lib/CodeGen/SimpleRegisterCoalescing.cpp | 14 |
2 files changed, 48 insertions, 4 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index a9e69483be..92627345de 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -607,12 +607,16 @@ LiveInterval LiveIntervals::createInterval(unsigned reg) { /// isReMaterializable - Returns true if the definition MI of the specified /// val# of the specified interval is re-materializable. bool LiveIntervals::isReMaterializable(const LiveInterval &li, - const VNInfo *ValNo, MachineInstr *MI) { + const VNInfo *ValNo, MachineInstr *MI, + bool &isLoad) { if (DisableReMat) return false; - if (tii_->isTriviallyReMaterializable(MI)) + isLoad = false; + if (tii_->isTriviallyReMaterializable(MI)) { + isLoad = MI->getInstrDescriptor()->Flags & M_LOAD_FLAG; return true; + } int FrameIdx = 0; if (!tii_->isLoadFromStackSlot(MI, FrameIdx) || @@ -621,6 +625,7 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li, // This is a load from fixed stack slot. It can be rematerialized unless it's // re-defined by a two-address instruction. + isLoad = true; for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end(); i != e; ++i) { const VNInfo *VNI = *i; @@ -631,8 +636,32 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li, continue; // Dead val#. MachineInstr *DefMI = (DefIdx == ~0u) ? NULL : getInstructionFromIndex(DefIdx); - if (DefMI && DefMI->isRegReDefinedByTwoAddr(li.reg)) + if (DefMI && DefMI->isRegReDefinedByTwoAddr(li.reg)) { + isLoad = false; + return false; + } + } + return true; +} + +/// isReMaterializable - Returns true if every definition of MI of every +/// val# of the specified interval is re-materializable. +bool LiveIntervals::isReMaterializable(const LiveInterval &li, bool &isLoad) { + isLoad = false; + for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end(); + i != e; ++i) { + const VNInfo *VNI = *i; + unsigned DefIdx = VNI->def; + if (DefIdx == ~1U) + continue; // Dead val#. + // Is the def for the val# rematerializable? + if (DefIdx == ~0u) + return false; + MachineInstr *ReMatDefMI = getInstructionFromIndex(DefIdx); + bool DefIsLoad = false; + if (!ReMatDefMI || !isReMaterializable(li, VNI, ReMatDefMI, DefIsLoad)) return false; + isLoad |= DefIsLoad; } return true; } @@ -1225,7 +1254,8 @@ addIntervalsForSpills(const LiveInterval &li, // Is the def for the val# rematerializable? MachineInstr *ReMatDefMI = (DefIdx == ~0u) ? 0 : getInstructionFromIndex(DefIdx); - if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI)) { + bool dummy; + if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI, dummy)) { // Remember how to remat the def of this val#. ReMatOrigDefs[VN] = ReMatDefMI; // Original def may be modified so we have to make a copy here. vrm must diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 3d2669becd..6eec5ab885 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -1485,6 +1485,20 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { // it and hope it will be easier to allocate for this li. if (isZeroLengthInterval(&LI)) LI.weight = HUGE_VALF; + else { + bool isLoad = false; + if (li_->isReMaterializable(LI, isLoad)) { + // If all of the definitions of the interval are re-materializable, + // it is a preferred candidate for spilling. If non of the defs are + // loads, then it's potentially very cheap to re-materialize. + // FIXME: this gets much more complicated once we support non-trivial + // re-materialization. + if (isLoad) + LI.weight *= 0.9F; + else + LI.weight *= 0.5F; + } + } // Slightly prefer live interval that has been assigned a preferred reg. if (LI.preference) |