LLVM 22.0.0git
CalcSpillWeights.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
23#include "llvm/Support/Debug.h"
26#include <cassert>
27#include <tuple>
28
29using namespace llvm;
30
31#define DEBUG_TYPE "calcspillweights"
32
34 LLVM_DEBUG(dbgs() << "********** Compute Spill Weights **********\n"
35 << "********** Function: " << MF.getName() << '\n');
36
38 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
40 if (MRI.reg_nodbg_empty(Reg))
41 continue;
43 }
44}
45
46// Return the preferred allocation register for reg, given a COPY instruction.
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 rematerializable
82 const LiveIntervals &LIS,
83 const VirtRegMap &VRM,
84 const TargetInstrInfo &TII) {
85 Register Reg = LI.reg();
86 Register Original = VRM.getOriginal(Reg);
88 I != E; ++I) {
89 const VNInfo *VNI = *I;
90 if (VNI->isUnused())
91 continue;
92 if (VNI->isPHIDef())
93 return false;
94
96 assert(MI && "Dead valno in interval");
97
98 // Trace copies introduced by live range splitting. The inline
99 // spiller can rematerialize through these copies, so the spill
100 // weight must reflect this.
101 while (TII.isFullCopyInstr(*MI)) {
102 // The copy destination must match the interval register.
103 if (MI->getOperand(0).getReg() != Reg)
104 return false;
105
106 // Get the source register.
107 Reg = MI->getOperand(1).getReg();
108
109 // If the original (pre-splitting) registers match this
110 // copy came from a split.
111 if (!Reg.isVirtual() || VRM.getOriginal(Reg) != Original)
112 return false;
113
114 // Follow the copy live-in value.
115 const LiveInterval &SrcLI = LIS.getInterval(Reg);
116 LiveQueryResult SrcQ = SrcLI.Query(VNI->def);
117 VNI = SrcQ.valueIn();
118 assert(VNI && "Copy from non-existing value");
119 if (VNI->isPHIDef())
120 return false;
121 MI = LIS.getInstructionFromIndex(VNI->def);
122 assert(MI && "Dead valno in interval");
123 }
124
125 if (!TII.isTriviallyReMaterializable(*MI))
126 return false;
127 }
128 return true;
129}
130
131bool VirtRegAuxInfo::isLiveAtStatepointVarArg(LiveInterval &LI) {
132 return any_of(VRM.getRegInfo().reg_operands(LI.reg()),
133 [](MachineOperand &MO) {
134 MachineInstr *MI = MO.getParent();
135 if (MI->getOpcode() != TargetOpcode::STATEPOINT)
136 return false;
137 return StatepointOpers(MI).getVarIdx() <= MO.getOperandNo();
138 });
139}
140
142 float Weight = weightCalcHelper(LI);
143 // Check if unspillable.
144 if (Weight < 0)
145 return;
146 LI.setWeight(Weight);
147}
148
150 const MachineRegisterInfo &MRI) {
151 for (const MachineOperand &MO : MRI.reg_operands(LI.reg())) {
152 const MachineInstr *MI = MO.getParent();
153 if (MI->isInlineAsm() && MI->mayFoldInlineAsmRegOp(MI->getOperandNo(&MO)))
154 return true;
155 }
156
157 return false;
158}
159
161 SlotIndex *End) {
165 MachineBasicBlock *MBB = nullptr;
166 float TotalWeight = 0;
167 unsigned NumInstr = 0; // Number of instructions using LI
169
170 std::pair<unsigned, Register> TargetHint = MRI.getRegAllocationHint(LI.reg());
171
172 if (LI.isSpillable()) {
173 Register Reg = LI.reg();
174 Register Original = VRM.getOriginal(Reg);
175 const LiveInterval &OrigInt = LIS.getInterval(Original);
176 // li comes from a split of OrigInt. If OrigInt was marked
177 // as not spillable, make sure the new interval is marked
178 // as not spillable as well.
179 if (!OrigInt.isSpillable())
180 LI.markNotSpillable();
181 }
182
183 // Don't recompute spill weight for an unspillable register.
184 bool IsSpillable = LI.isSpillable();
185
186 bool IsLocalSplitArtifact = Start && End;
187
188 // Do not update future local split artifacts.
189 bool ShouldUpdateLI = !IsLocalSplitArtifact;
190
191 if (IsLocalSplitArtifact) {
192 MachineBasicBlock *LocalMBB = LIS.getMBBFromIndex(*End);
193 assert(LocalMBB == LIS.getMBBFromIndex(*Start) &&
194 "start and end are expected to be in the same basic block");
195
196 // Local split artifact will have 2 additional copy instructions and they
197 // will be in the same BB.
198 // localLI = COPY other
199 // ...
200 // other = COPY localLI
201 TotalWeight +=
202 LiveIntervals::getSpillWeight(true, false, &MBFI, LocalMBB, PSI);
203 TotalWeight +=
204 LiveIntervals::getSpillWeight(false, true, &MBFI, LocalMBB, PSI);
205
206 NumInstr += 2;
207 }
208
209 // CopyHint is a sortable hint derived from a COPY instruction.
210 struct CopyHint {
212 float Weight;
213 bool IsCSR;
214 CopyHint(Register R, float W, bool IsCSR)
215 : Reg(R), Weight(W), IsCSR(IsCSR) {}
216 bool operator<(const CopyHint &Rhs) const {
217 // Always prefer any physreg hint.
218 if (Reg.isPhysical() != Rhs.Reg.isPhysical())
219 return Reg.isPhysical();
220 if (Weight != Rhs.Weight)
221 return (Weight > Rhs.Weight);
222 // Prefer non-CSR to CSR.
223 if (Reg.isPhysical() && IsCSR != Rhs.IsCSR)
224 return !IsCSR;
225 return Reg.id() < Rhs.Reg.id(); // Tie-breaker.
226 }
227 };
228
229 bool IsExiting = false;
232 I = MRI.reg_instr_nodbg_begin(LI.reg()),
233 E = MRI.reg_instr_nodbg_end();
234 I != E;) {
235 MachineInstr *MI = &*(I++);
236
237 // For local split artifacts, we are interested only in instructions between
238 // the expected start and end of the range.
240 if (IsLocalSplitArtifact && ((SI < *Start) || (SI > *End)))
241 continue;
242
243 NumInstr++;
244 bool identityCopy = false;
245 auto DestSrc = TII.isCopyInstr(*MI);
246 if (DestSrc) {
247 const MachineOperand *DestRegOp = DestSrc->Destination;
248 const MachineOperand *SrcRegOp = DestSrc->Source;
249 identityCopy = DestRegOp->getReg() == SrcRegOp->getReg() &&
250 DestRegOp->getSubReg() == SrcRegOp->getSubReg();
251 }
252
253 if (identityCopy || MI->isImplicitDef())
254 continue;
255 if (!Visited.insert(MI).second)
256 continue;
257
258 // For terminators that produce values, ask the backend if the register is
259 // not spillable.
260 if (TII.isUnspillableTerminator(MI) &&
261 MI->definesRegister(LI.reg(), /*TRI=*/nullptr)) {
262 LI.markNotSpillable();
263 return -1.0f;
264 }
265
266 // Force Weight onto the stack so that x86 doesn't add hidden precision.
267 stack_float_t Weight = 1.0f;
268 if (IsSpillable) {
269 // Get loop info for mi.
270 if (MI->getParent() != MBB) {
271 MBB = MI->getParent();
272 const MachineLoop *Loop = Loops.getLoopFor(MBB);
273 IsExiting = Loop ? Loop->isLoopExiting(MBB) : false;
274 }
275
276 // Calculate instr weight.
277 bool Reads, Writes;
278 std::tie(Reads, Writes) = MI->readsWritesVirtualRegister(LI.reg());
279 Weight = LiveIntervals::getSpillWeight(Writes, Reads, &MBFI, *MI, PSI);
280
281 // Give extra weight to what looks like a loop induction variable update.
282 if (Writes && IsExiting && LIS.isLiveOutOfMBB(LI, MBB))
283 Weight *= 3;
284
285 TotalWeight += Weight;
286 }
287
288 // Get allocation hints from copies.
289 if (!TII.isCopyInstr(*MI))
290 continue;
291 Register HintReg = copyHint(MI, LI.reg(), TRI, MRI);
292 if (HintReg && (HintReg.isVirtual() || MRI.isAllocatable(HintReg)))
293 Hint[HintReg] += Weight;
294 }
295
296 // Pass all the sorted copy hints to mri.
297 if (ShouldUpdateLI && Hint.size()) {
298 // Remove a generic hint if previously added by target.
299 if (TargetHint.first == 0 && TargetHint.second)
300 MRI.clearSimpleHint(LI.reg());
301
302 // Don't add the target-type hint again.
303 Register SkipReg = TargetHint.first != 0 ? TargetHint.second : Register();
305 for (const auto &[Reg, Weight] : Hint) {
306 if (Reg != SkipReg)
307 RegHints.emplace_back(
308 Reg, Weight,
309 Reg.isPhysical() ? TRI.isCalleeSavedPhysReg(Reg, MF) : false);
310 }
311 sort(RegHints);
312 for (const auto &[Reg, _, __] : RegHints)
313 MRI.addRegAllocationHint(LI.reg(), Reg);
314
315 // Weakly boost the spill weight of hinted registers.
316 TotalWeight *= 1.01F;
317 }
318
319 // If the live interval was already unspillable, leave it that way.
320 if (!IsSpillable)
321 return -1.0;
322
323 // Mark li as unspillable if all live ranges are tiny and the interval
324 // is not live at any reg mask. If the interval is live at a reg mask
325 // spilling may be required. If li is live as use in statepoint instruction
326 // spilling may be required due to if we mark interval with use in statepoint
327 // as not spillable we are risky to end up with no register to allocate.
328 // At the same time STATEPOINT instruction is perfectly fine to have this
329 // operand on stack, so spilling such interval and folding its load from stack
330 // into instruction itself makes perfect sense.
331 if (ShouldUpdateLI && LI.isZeroLength(LIS.getSlotIndexes()) &&
332 !LI.isLiveAtIndexes(LIS.getRegMaskSlots()) &&
333 !isLiveAtStatepointVarArg(LI) && !canMemFoldInlineAsm(LI, MRI)) {
334 LI.markNotSpillable();
335 return -1.0;
336 }
337
338 // If all of the definitions of the interval are re-materializable,
339 // it is a preferred candidate for spilling.
340 // FIXME: this gets much more complicated once we support non-trivial
341 // re-materialization.
342 if (isRematerializable(LI, LIS, VRM, *MF.getSubtarget().getInstrInfo()))
343 TotalWeight *= 0.5F;
344
345 // Finally, we scale the weight by the scale factor of register class.
346 const TargetRegisterClass *RC = MRI.getRegClass(LI.reg());
347 TotalWeight *= TRI.getSpillWeightScaleFactor(RC);
348
349 if (IsLocalSplitArtifact)
350 return normalize(TotalWeight, Start->distance(*End), NumInstr);
351 return normalize(TotalWeight, LI.getSize(), NumInstr);
352}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static bool canMemFoldInlineAsm(LiveInterval &LI, const MachineRegisterInfo &MRI)
bool End
Definition: ELF_riscv.cpp:480
SmallVector< uint32_t, 0 > Writes
Definition: ELF_riscv.cpp:497
const HexagonInstrInfo * TII
#define _
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
Register Reg
Register const TargetRegisterInfo * TRI
This file defines the SmallPtrSet class.
#define LLVM_DEBUG(...)
Definition: Debug.h:119
unsigned size() const
Definition: DenseMap.h:120
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:690
void markNotSpillable()
markNotSpillable - Mark interval as not spillable
Definition: LiveInterval.h:832
Register reg() const
Definition: LiveInterval.h:721
bool isSpillable() const
isSpillable - Can this interval be spilled?
Definition: LiveInterval.h:829
LLVM_ABI unsigned getSize() const
getSize - Returns the sum of sizes of all the LiveRange's.
void setWeight(float Value)
Definition: LiveInterval.h:724
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
SlotIndexes * getSlotIndexes() const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
static LLVM_ABI float getSpillWeight(bool isDef, bool isUse, const MachineBlockFrequencyInfo *MBFI, const MachineInstr &MI, ProfileSummaryInfo *PSI=nullptr)
Calculate the spill weight to assign to a single instruction.
ArrayRef< SlotIndex > getRegMaskSlots() const
Returns a sorted array of slot indices of all instructions with register mask operands.
LiveInterval & getInterval(Register Reg)
bool isLiveOutOfMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const
MachineBasicBlock * getMBBFromIndex(SlotIndex index) const
Result of a LiveRange query.
Definition: LiveInterval.h:91
VNInfo * valueIn() const
Return the value that is live-in to the instruction.
Definition: LiveInterval.h:106
LLVM_ABI bool isLiveAtIndexes(ArrayRef< SlotIndex > Slots) const
vni_iterator vni_begin()
Definition: LiveInterval.h:225
bool isZeroLength(SlotIndexes *Indexes) const
Returns true if the live range is zero length, i.e.
Definition: LiveInterval.h:590
LiveQueryResult Query(SlotIndex Idx) const
Query Liveness at Idx.
Definition: LiveInterval.h:545
vni_iterator vni_end()
Definition: LiveInterval.h:226
bool isLoopExiting(const BlockT *BB) const
True if terminator in the block can branch to another block that is outside of the current loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:40
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
Definition: MachineInstr.h:72
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
Register getReg() const
getReg - Returns the register number.
defusechain_iterator - This class provides iterator support for machine operands in the function that...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
iterator_range< reg_iterator > reg_operands(Register Reg) const
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition: Register.h:67
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition: Register.h:102
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:74
constexpr unsigned id() const
Definition: Register.h:95
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:78
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:66
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:401
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:541
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
TargetInstrInfo - Interface to description of machine instruction set.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
VNInfo - Value Number Information.
Definition: LiveInterval.h:54
bool isUnused() const
Returns true if this value is unused.
Definition: LiveInterval.h:82
SlotIndex def
The index of the defining instruction.
Definition: LiveInterval.h:62
bool isPHIDef() const
Returns true if this value is defined by a PHI instruction (or was, PHI instructions may have been el...
Definition: LiveInterval.h:79
float weightCalcHelper(LiveInterval &LI, SlotIndex *Start=nullptr, SlotIndex *End=nullptr)
Helper function for weight calculations.
void calculateSpillWeightsAndHints()
Compute spill weights and allocation hints for all virtual register live intervals.
virtual float normalize(float UseDefFreq, unsigned Size, unsigned NumInstr)
Weight normalization function.
static bool isRematerializable(const LiveInterval &LI, const LiveIntervals &LIS, const VirtRegMap &VRM, const TargetInstrInfo &TII)
Determine if all values in LI are rematerializable.
static Register copyHint(const MachineInstr *MI, Register Reg, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI)
Return the preferred allocation register for reg, given a COPY instruction.
void calculateSpillWeightAndHint(LiveInterval &LI)
(re)compute li's spill weight and allocation hint.
Register getOriginal(Register VirtReg) const
getOriginal - Return the original virtual register that VirtReg descends from through splitting.
Definition: VirtRegMap.h:155
MachineRegisterInfo & getRegInfo() const
Definition: VirtRegMap.h:80
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
float stack_float_t
Type to force float point values onto the stack, so that x86 doesn't add hidden precision,...
Definition: MathExtras.h:791
bool operator<(int64_t V1, const APSInt &V2)
Definition: APSInt.h:362
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1751
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1669
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
@ Sub
Subtraction of integers.