summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CalcSpillWeights.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CalcSpillWeights.cpp')
-rw-r--r--lib/CodeGen/CalcSpillWeights.cpp166
1 files changed, 128 insertions, 38 deletions
diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp
index c2ced19458ed..b8920a601938 100644
--- a/lib/CodeGen/CalcSpillWeights.cpp
+++ b/lib/CodeGen/CalcSpillWeights.cpp
@@ -1,4 +1,4 @@
-//===------------------------ CalcSpillWeights.cpp ------------------------===//
+//===- CalcSpillWeights.cpp -----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,17 +8,23 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/CalcSpillWeights.h"
-#include "llvm/CodeGen/LiveIntervalAnalysis.h"
-#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/CodeGen/LiveInterval.h"
+#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
+#include <cassert>
+#include <tuple>
+
using namespace llvm;
#define DEBUG_TYPE "calcspillweights"
@@ -64,13 +70,24 @@ static unsigned copyHint(const MachineInstr *mi, unsigned reg,
return sub == hsub ? hreg : 0;
const TargetRegisterClass *rc = mri.getRegClass(reg);
+ if (!tri.enableMultipleCopyHints()) {
+ // Only allow physreg hints in rc.
+ if (sub == 0)
+ return rc->contains(hreg) ? hreg : 0;
+
+ // reg:sub should match the physreg hreg.
+ return tri.getMatchingSuperReg(hreg, sub, rc);
+ }
+
+ unsigned CopiedPReg = (hsub ? tri.getSubReg(hreg, hsub) : hreg);
+ if (rc->contains(CopiedPReg))
+ return CopiedPReg;
- // Only allow physreg hints in rc.
- if (sub == 0)
- return rc->contains(hreg) ? hreg : 0;
+ // Check if reg:sub matches so that a super register could be hinted.
+ if (sub)
+ return tri.getMatchingSuperReg(CopiedPReg, sub, rc);
- // reg:sub should match the physreg hreg.
- return tri.getMatchingSuperReg(hreg, sub, rc);
+ return 0;
}
// Check if all values in LI are rematerializable
@@ -127,8 +144,21 @@ static bool isRematerializable(const LiveInterval &LI,
return true;
}
-void
-VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
+void VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
+ float weight = weightCalcHelper(li);
+ // Check if unspillable.
+ if (weight < 0)
+ return;
+ li.weight = weight;
+}
+
+float VirtRegAuxInfo::futureWeight(LiveInterval &li, SlotIndex start,
+ SlotIndex end) {
+ return weightCalcHelper(li, &start, &end);
+}
+
+float VirtRegAuxInfo::weightCalcHelper(LiveInterval &li, SlotIndex *start,
+ SlotIndex *end) {
MachineRegisterInfo &mri = MF.getRegInfo();
const TargetRegisterInfo &tri = *MF.getSubtarget().getRegisterInfo();
MachineBasicBlock *mbb = nullptr;
@@ -138,20 +168,73 @@ VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
unsigned numInstr = 0; // Number of instructions using li
SmallPtrSet<MachineInstr*, 8> visited;
- // Find the best physreg hint and the best virtreg hint.
- float bestPhys = 0, bestVirt = 0;
- unsigned hintPhys = 0, hintVirt = 0;
-
- // Don't recompute a target specific hint.
- bool noHint = mri.getRegAllocationHint(li.reg).first != 0;
+ std::pair<unsigned, unsigned> TargetHint = mri.getRegAllocationHint(li.reg);
// Don't recompute spill weight for an unspillable register.
bool Spillable = li.isSpillable();
+ bool localSplitArtifact = start && end;
+
+ // Do not update future local split artifacts.
+ bool updateLI = !localSplitArtifact;
+
+ if (localSplitArtifact) {
+ MachineBasicBlock *localMBB = LIS.getMBBFromIndex(*end);
+ assert(localMBB == LIS.getMBBFromIndex(*start) &&
+ "start and end are expected to be in the same basic block");
+
+ // Local split artifact will have 2 additional copy instructions and they
+ // will be in the same BB.
+ // localLI = COPY other
+ // ...
+ // other = COPY localLI
+ totalWeight += LiveIntervals::getSpillWeight(true, false, &MBFI, localMBB);
+ totalWeight += LiveIntervals::getSpillWeight(false, true, &MBFI, localMBB);
+
+ numInstr += 2;
+ }
+
+ // CopyHint is a sortable hint derived from a COPY instruction.
+ struct CopyHint {
+ unsigned Reg;
+ float Weight;
+ bool IsPhys;
+ unsigned HintOrder;
+ CopyHint(unsigned R, float W, bool P, unsigned HR) :
+ Reg(R), Weight(W), IsPhys(P), HintOrder(HR) {}
+ bool operator<(const CopyHint &rhs) const {
+ // Always prefer any physreg hint.
+ if (IsPhys != rhs.IsPhys)
+ return (IsPhys && !rhs.IsPhys);
+ if (Weight != rhs.Weight)
+ return (Weight > rhs.Weight);
+
+ // This is just a temporary way to achive NFC for targets that don't
+ // enable multiple copy hints. HintOrder should be removed when all
+ // targets return true in enableMultipleCopyHints().
+ return (HintOrder < rhs.HintOrder);
+
+#if 0 // Should replace the HintOrder check, see above.
+ // (just for the purpose of maintaining the set)
+ return Reg < rhs.Reg;
+#endif
+ }
+ };
+ std::set<CopyHint> CopyHints;
+
+ // Temporary: see comment for HintOrder above.
+ unsigned CopyHintOrder = 0;
for (MachineRegisterInfo::reg_instr_iterator
I = mri.reg_instr_begin(li.reg), E = mri.reg_instr_end();
I != E; ) {
MachineInstr *mi = &*(I++);
+
+ // For local split artifacts, we are interested only in instructions between
+ // the expected start and end of the range.
+ SlotIndex si = LIS.getInstructionIndex(*mi);
+ if (localSplitArtifact && ((si < *start) || (si > *end)))
+ continue;
+
numInstr++;
if (mi->isIdentityCopy() || mi->isImplicitDef() || mi->isDebugValue())
continue;
@@ -180,7 +263,8 @@ VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
}
// Get allocation hints from copies.
- if (noHint || !mi->isCopy())
+ if (!mi->isCopy() ||
+ (TargetHint.first != 0 && !tri.enableMultipleCopyHints()))
continue;
unsigned hint = copyHint(mi, li.reg, tri, mri);
if (!hint)
@@ -190,39 +274,43 @@ VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
//
// FIXME: we probably shouldn't use floats at all.
volatile float hweight = Hint[hint] += weight;
- if (TargetRegisterInfo::isPhysicalRegister(hint)) {
- if (hweight > bestPhys && mri.isAllocatable(hint)) {
- bestPhys = hweight;
- hintPhys = hint;
- }
- } else {
- if (hweight > bestVirt) {
- bestVirt = hweight;
- hintVirt = hint;
- }
- }
+ if (TargetRegisterInfo::isVirtualRegister(hint) || mri.isAllocatable(hint))
+ CopyHints.insert(CopyHint(hint, hweight, tri.isPhysicalRegister(hint),
+ (tri.enableMultipleCopyHints() ? hint : CopyHintOrder++)));
}
Hint.clear();
- // Always prefer the physreg hint.
- if (unsigned hint = hintPhys ? hintPhys : hintVirt) {
- mri.setRegAllocationHint(li.reg, 0, hint);
+ // Pass all the sorted copy hints to mri.
+ if (updateLI && CopyHints.size()) {
+ // Remove a generic hint if previously added by target.
+ if (TargetHint.first == 0 && TargetHint.second)
+ mri.clearSimpleHint(li.reg);
+
+ for (auto &Hint : CopyHints) {
+ if (TargetHint.first != 0 && Hint.Reg == TargetHint.second)
+ // Don't add again the target-type hint.
+ continue;
+ mri.addRegAllocationHint(li.reg, Hint.Reg);
+ if (!tri.enableMultipleCopyHints())
+ break;
+ }
+
// Weakly boost the spill weight of hinted registers.
totalWeight *= 1.01F;
}
// If the live interval was already unspillable, leave it that way.
if (!Spillable)
- return;
+ return -1.0;
// Mark li as unspillable if all live ranges are tiny and the interval
// is not live at any reg mask. If the interval is live at a reg mask
// spilling may be required.
- if (li.isZeroLength(LIS.getSlotIndexes()) &&
+ if (updateLI && li.isZeroLength(LIS.getSlotIndexes()) &&
!li.isLiveAtIndexes(LIS.getRegMaskSlots())) {
li.markNotSpillable();
- return;
+ return -1.0;
}
// If all of the definitions of the interval are re-materializable,
@@ -232,5 +320,7 @@ VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
if (isRematerializable(li, LIS, VRM, *MF.getSubtarget().getInstrInfo()))
totalWeight *= 0.5F;
- li.weight = normalize(totalWeight, li.getSize(), numInstr);
+ if (localSplitArtifact)
+ return normalize(totalWeight, start->distance(*end), numInstr);
+ return normalize(totalWeight, li.getSize(), numInstr);
}