425 lines · cpp
1//===- CalcSpillWeights.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/CodeGen/CalcSpillWeights.h"10#include "llvm/ADT/SmallPtrSet.h"11#include "llvm/CodeGen/LiveInterval.h"12#include "llvm/CodeGen/LiveIntervals.h"13#include "llvm/CodeGen/MachineFunction.h"14#include "llvm/CodeGen/MachineInstr.h"15#include "llvm/CodeGen/MachineLoopInfo.h"16#include "llvm/CodeGen/MachineOperand.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/CodeGen/StackMaps.h"19#include "llvm/CodeGen/TargetInstrInfo.h"20#include "llvm/CodeGen/TargetRegisterInfo.h"21#include "llvm/CodeGen/TargetSubtargetInfo.h"22#include "llvm/CodeGen/VirtRegMap.h"23#include "llvm/Support/Debug.h"24#include "llvm/Support/MathExtras.h"25#include "llvm/Support/raw_ostream.h"26#include <cassert>27#include <tuple>28 29using namespace llvm;30 31#define DEBUG_TYPE "calcspillweights"32 33void VirtRegAuxInfo::calculateSpillWeightsAndHints() {34 LLVM_DEBUG(dbgs() << "********** Compute Spill Weights **********\n"35 << "********** Function: " << MF.getName() << '\n');36 37 MachineRegisterInfo &MRI = MF.getRegInfo();38 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {39 Register Reg = Register::index2VirtReg(I);40 if (MRI.reg_nodbg_empty(Reg))41 continue;42 calculateSpillWeightAndHint(LIS.getInterval(Reg));43 }44}45 46// Return the preferred allocation register for reg, given a COPY instruction.47Register VirtRegAuxInfo::copyHint(const MachineInstr *MI, Register Reg,48 const TargetRegisterInfo &TRI,49 const MachineRegisterInfo &MRI) {50 unsigned Sub, HSub;51 Register HReg;52 if (MI->getOperand(0).getReg() == Reg) {53 Sub = MI->getOperand(0).getSubReg();54 HReg = MI->getOperand(1).getReg();55 HSub = MI->getOperand(1).getSubReg();56 } else {57 Sub = MI->getOperand(1).getSubReg();58 HReg = MI->getOperand(0).getReg();59 HSub = MI->getOperand(0).getSubReg();60 }61 62 if (!HReg)63 return 0;64 65 if (HReg.isVirtual())66 return Sub == HSub ? HReg : Register();67 68 const TargetRegisterClass *RC = MRI.getRegClass(Reg);69 MCRegister CopiedPReg = HSub ? TRI.getSubReg(HReg, HSub) : HReg.asMCReg();70 if (RC->contains(CopiedPReg))71 return CopiedPReg;72 73 // Check if reg:sub matches so that a super register could be hinted.74 if (Sub)75 return TRI.getMatchingSuperReg(CopiedPReg, Sub, RC);76 77 return Register();78}79 80// Check if all values in LI are rematerializable81bool VirtRegAuxInfo::isRematerializable(const LiveInterval &LI,82 const LiveIntervals &LIS,83 const VirtRegMap &VRM,84 const MachineRegisterInfo &MRI,85 const TargetInstrInfo &TII) {86 Register Reg = LI.reg();87 Register Original = VRM.getOriginal(Reg);88 SmallDenseMap<unsigned, MachineInstr *> VNIDefs;89 for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end();90 I != E; ++I) {91 const VNInfo *VNI = *I;92 const VNInfo *OrigVNI = VNI;93 if (VNI->isUnused())94 continue;95 if (VNI->isPHIDef())96 return false;97 98 MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def);99 assert(MI && "Dead valno in interval");100 101 // Trace copies introduced by live range splitting. The inline102 // spiller can rematerialize through these copies, so the spill103 // weight must reflect this.104 while (TII.isFullCopyInstr(*MI)) {105 // The copy destination must match the interval register.106 if (MI->getOperand(0).getReg() != Reg)107 return false;108 109 // Get the source register.110 Reg = MI->getOperand(1).getReg();111 112 // If the original (pre-splitting) registers match this113 // copy came from a split.114 if (!Reg.isVirtual() || VRM.getOriginal(Reg) != Original)115 return false;116 117 // Follow the copy live-in value.118 const LiveInterval &SrcLI = LIS.getInterval(Reg);119 LiveQueryResult SrcQ = SrcLI.Query(VNI->def);120 VNI = SrcQ.valueIn();121 assert(VNI && "Copy from non-existing value");122 if (VNI->isPHIDef())123 return false;124 MI = LIS.getInstructionFromIndex(VNI->def);125 assert(MI && "Dead valno in interval");126 }127 128 if (!TII.isReMaterializable(*MI))129 return false;130 131 VNIDefs[OrigVNI->id] = MI;132 }133 134 // If MI has register uses, it will only be rematerializable if its uses are135 // also live at the indices it will be rematerialized at.136 for (MachineOperand &MO : MRI.reg_nodbg_operands(LI.reg())) {137 if (!MO.readsReg())138 continue;139 SlotIndex UseIdx = LIS.getInstructionIndex(*MO.getParent());140 MachineInstr *Def = VNIDefs[LI.getVNInfoAt(UseIdx)->id];141 assert(Def && "Use with no def");142 if (!allUsesAvailableAt(Def, UseIdx, LIS, MRI, TII))143 return false;144 }145 146 return true;147}148 149bool VirtRegAuxInfo::allUsesAvailableAt(const MachineInstr *MI,150 SlotIndex UseIdx,151 const LiveIntervals &LIS,152 const MachineRegisterInfo &MRI,153 const TargetInstrInfo &TII) {154 SlotIndex OrigIdx = LIS.getInstructionIndex(*MI).getRegSlot(true);155 UseIdx = std::max(UseIdx, UseIdx.getRegSlot(true));156 for (const MachineOperand &MO : MI->operands()) {157 if (!MO.isReg() || !MO.getReg() || !MO.readsReg())158 continue;159 160 // We can't remat physreg uses, unless it is a constant or target wants161 // to ignore this use.162 if (MO.getReg().isPhysical()) {163 if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO))164 continue;165 return false;166 }167 168 const LiveInterval &li = LIS.getInterval(MO.getReg());169 const VNInfo *OVNI = li.getVNInfoAt(OrigIdx);170 if (!OVNI)171 continue;172 173 // Don't allow rematerialization immediately after the original def.174 // It would be incorrect if OrigMI redefines the register.175 // See PR14098.176 if (SlotIndex::isSameInstr(OrigIdx, UseIdx))177 return false;178 179 if (OVNI != li.getVNInfoAt(UseIdx))180 return false;181 182 // Check that subrange is live at UseIdx.183 if (li.hasSubRanges()) {184 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();185 unsigned SubReg = MO.getSubReg();186 LaneBitmask LM = SubReg ? TRI->getSubRegIndexLaneMask(SubReg)187 : MRI.getMaxLaneMaskForVReg(MO.getReg());188 for (const LiveInterval::SubRange &SR : li.subranges()) {189 if ((SR.LaneMask & LM).none())190 continue;191 if (!SR.liveAt(UseIdx))192 return false;193 // Early exit if all used lanes are checked. No need to continue.194 LM &= ~SR.LaneMask;195 if (LM.none())196 break;197 }198 }199 }200 return true;201}202 203bool VirtRegAuxInfo::isLiveAtStatepointVarArg(LiveInterval &LI) {204 return any_of(VRM.getRegInfo().reg_operands(LI.reg()),205 [](MachineOperand &MO) {206 MachineInstr *MI = MO.getParent();207 if (MI->getOpcode() != TargetOpcode::STATEPOINT)208 return false;209 return StatepointOpers(MI).getVarIdx() <= MO.getOperandNo();210 });211}212 213void VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &LI) {214 float Weight = weightCalcHelper(LI);215 // Check if unspillable.216 if (Weight < 0)217 return;218 LI.setWeight(Weight);219}220 221static bool canMemFoldInlineAsm(LiveInterval &LI,222 const MachineRegisterInfo &MRI) {223 for (const MachineOperand &MO : MRI.reg_operands(LI.reg())) {224 const MachineInstr *MI = MO.getParent();225 if (MI->isInlineAsm() && MI->mayFoldInlineAsmRegOp(MI->getOperandNo(&MO)))226 return true;227 }228 229 return false;230}231 232float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,233 SlotIndex *End) {234 MachineRegisterInfo &MRI = MF.getRegInfo();235 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();236 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();237 MachineBasicBlock *MBB = nullptr;238 float TotalWeight = 0;239 unsigned NumInstr = 0; // Number of instructions using LI240 SmallPtrSet<MachineInstr *, 8> Visited;241 242 std::pair<unsigned, Register> TargetHint = MRI.getRegAllocationHint(LI.reg());243 244 if (LI.isSpillable()) {245 Register Reg = LI.reg();246 Register Original = VRM.getOriginal(Reg);247 const LiveInterval &OrigInt = LIS.getInterval(Original);248 // li comes from a split of OrigInt. If OrigInt was marked249 // as not spillable, make sure the new interval is marked250 // as not spillable as well.251 if (!OrigInt.isSpillable())252 LI.markNotSpillable();253 }254 255 // Don't recompute spill weight for an unspillable register.256 bool IsSpillable = LI.isSpillable();257 258 bool IsLocalSplitArtifact = Start && End;259 260 // Do not update future local split artifacts.261 bool ShouldUpdateLI = !IsLocalSplitArtifact;262 263 if (IsLocalSplitArtifact) {264 MachineBasicBlock *LocalMBB = LIS.getMBBFromIndex(*End);265 assert(LocalMBB == LIS.getMBBFromIndex(*Start) &&266 "start and end are expected to be in the same basic block");267 268 // Local split artifact will have 2 additional copy instructions and they269 // will be in the same BB.270 // localLI = COPY other271 // ...272 // other = COPY localLI273 TotalWeight +=274 LiveIntervals::getSpillWeight(true, false, &MBFI, LocalMBB, PSI);275 TotalWeight +=276 LiveIntervals::getSpillWeight(false, true, &MBFI, LocalMBB, PSI);277 278 NumInstr += 2;279 }280 281 // CopyHint is a sortable hint derived from a COPY instruction.282 struct CopyHint {283 Register Reg;284 float Weight;285 bool IsCSR;286 CopyHint(Register R, float W, bool IsCSR)287 : Reg(R), Weight(W), IsCSR(IsCSR) {}288 bool operator<(const CopyHint &Rhs) const {289 // Always prefer any physreg hint.290 if (Reg.isPhysical() != Rhs.Reg.isPhysical())291 return Reg.isPhysical();292 if (Weight != Rhs.Weight)293 return (Weight > Rhs.Weight);294 // Prefer non-CSR to CSR.295 if (Reg.isPhysical() && IsCSR != Rhs.IsCSR)296 return !IsCSR;297 return Reg.id() < Rhs.Reg.id(); // Tie-breaker.298 }299 };300 301 bool IsExiting = false;302 SmallDenseMap<Register, float, 8> Hint;303 for (MachineRegisterInfo::reg_instr_nodbg_iterator304 I = MRI.reg_instr_nodbg_begin(LI.reg()),305 E = MRI.reg_instr_nodbg_end();306 I != E;) {307 MachineInstr *MI = &*(I++);308 309 // For local split artifacts, we are interested only in instructions between310 // the expected start and end of the range.311 SlotIndex SI = LIS.getInstructionIndex(*MI);312 if (IsLocalSplitArtifact && ((SI < *Start) || (SI > *End)))313 continue;314 315 NumInstr++;316 bool identityCopy = false;317 auto DestSrc = TII.isCopyInstr(*MI);318 if (DestSrc) {319 const MachineOperand *DestRegOp = DestSrc->Destination;320 const MachineOperand *SrcRegOp = DestSrc->Source;321 identityCopy = DestRegOp->getReg() == SrcRegOp->getReg() &&322 DestRegOp->getSubReg() == SrcRegOp->getSubReg();323 }324 325 if (identityCopy || MI->isImplicitDef())326 continue;327 if (!Visited.insert(MI).second)328 continue;329 330 // For terminators that produce values, ask the backend if the register is331 // not spillable.332 if (TII.isUnspillableTerminator(MI) &&333 MI->definesRegister(LI.reg(), /*TRI=*/nullptr)) {334 LI.markNotSpillable();335 return -1.0f;336 }337 338 // Force Weight onto the stack so that x86 doesn't add hidden precision.339 stack_float_t Weight = 1.0f;340 if (IsSpillable) {341 // Get loop info for mi.342 if (MI->getParent() != MBB) {343 MBB = MI->getParent();344 const MachineLoop *Loop = Loops.getLoopFor(MBB);345 IsExiting = Loop ? Loop->isLoopExiting(MBB) : false;346 }347 348 // Calculate instr weight.349 bool Reads, Writes;350 std::tie(Reads, Writes) = MI->readsWritesVirtualRegister(LI.reg());351 Weight = LiveIntervals::getSpillWeight(Writes, Reads, &MBFI, *MI, PSI);352 353 // Give extra weight to what looks like a loop induction variable update.354 if (Writes && IsExiting && LIS.isLiveOutOfMBB(LI, MBB))355 Weight *= 3;356 357 TotalWeight += Weight;358 }359 360 // Get allocation hints from copies.361 if (!TII.isCopyInstr(*MI))362 continue;363 Register HintReg = copyHint(MI, LI.reg(), TRI, MRI);364 if (HintReg && (HintReg.isVirtual() || MRI.isAllocatable(HintReg)))365 Hint[HintReg] += Weight;366 }367 368 // Pass all the sorted copy hints to mri.369 if (ShouldUpdateLI && Hint.size()) {370 // Remove a generic hint if previously added by target.371 if (TargetHint.first == 0 && TargetHint.second)372 MRI.clearSimpleHint(LI.reg());373 374 // Don't add the target-type hint again.375 Register SkipReg = TargetHint.first != 0 ? TargetHint.second : Register();376 SmallVector<CopyHint, 8> RegHints;377 for (const auto &[Reg, Weight] : Hint) {378 if (Reg != SkipReg)379 RegHints.emplace_back(380 Reg, Weight,381 Reg.isPhysical() ? TRI.isCalleeSavedPhysReg(Reg, MF) : false);382 }383 sort(RegHints);384 for (const auto &[Reg, _, __] : RegHints)385 MRI.addRegAllocationHint(LI.reg(), Reg);386 387 // Weakly boost the spill weight of hinted registers.388 TotalWeight *= 1.01F;389 }390 391 // If the live interval was already unspillable, leave it that way.392 if (!IsSpillable)393 return -1.0;394 395 // Mark li as unspillable if all live ranges are tiny and the interval396 // is not live at any reg mask. If the interval is live at a reg mask397 // spilling may be required. If li is live as use in statepoint instruction398 // spilling may be required due to if we mark interval with use in statepoint399 // as not spillable we are risky to end up with no register to allocate.400 // At the same time STATEPOINT instruction is perfectly fine to have this401 // operand on stack, so spilling such interval and folding its load from stack402 // into instruction itself makes perfect sense.403 if (ShouldUpdateLI && LI.isZeroLength(LIS.getSlotIndexes()) &&404 !LI.isLiveAtIndexes(LIS.getRegMaskSlots()) &&405 !isLiveAtStatepointVarArg(LI) && !canMemFoldInlineAsm(LI, MRI)) {406 LI.markNotSpillable();407 return -1.0;408 }409 410 // If all of the definitions of the interval are re-materializable,411 // it is a preferred candidate for spilling.412 // FIXME: this gets much more complicated once we support non-trivial413 // re-materialization.414 if (isRematerializable(LI, LIS, VRM, MRI, *MF.getSubtarget().getInstrInfo()))415 TotalWeight *= 0.5F;416 417 // Finally, we scale the weight by the scale factor of register class.418 const TargetRegisterClass *RC = MRI.getRegClass(LI.reg());419 TotalWeight *= TRI.getSpillWeightScaleFactor(RC);420 421 if (IsLocalSplitArtifact)422 return normalize(TotalWeight, Start->distance(*End), NumInstr);423 return normalize(TotalWeight, LI.getSize(), NumInstr);424}425