blob: 7491a92645f5ec7fb1933db4c4d86088d35c5489 [file] [log] [blame]
Serguei Katkov4275eb12020-04-09 18:40:53 +07001//===-- FixupStatepointCallerSaved.cpp - Fixup caller saved registers ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// Statepoint instruction in deopt parameters contains values which are
12/// meaningful to the runtime and should be able to be read at the moment the
13/// call returns. So we can say that we need to encode the fact that these
14/// values are "late read" by runtime. If we could express this notion for
15/// register allocator it would produce the right form for us.
16/// The need to fixup (i.e this pass) is specifically handling the fact that
17/// we cannot describe such a late read for the register allocator.
18/// Register allocator may put the value on a register clobbered by the call.
19/// This pass forces the spill of such registers and replaces corresponding
20/// statepoint operands to added spill slots.
21///
22//===----------------------------------------------------------------------===//
23
24#include "llvm/ADT/SmallSet.h"
25#include "llvm/ADT/Statistic.h"
26#include "llvm/CodeGen/MachineFrameInfo.h"
27#include "llvm/CodeGen/MachineFunctionPass.h"
28#include "llvm/CodeGen/MachineRegisterInfo.h"
29#include "llvm/CodeGen/Passes.h"
30#include "llvm/CodeGen/StackMaps.h"
31#include "llvm/CodeGen/TargetFrameLowering.h"
32#include "llvm/CodeGen/TargetInstrInfo.h"
33#include "llvm/IR/Statepoint.h"
34#include "llvm/InitializePasses.h"
35#include "llvm/Support/Debug.h"
36
37using namespace llvm;
38
39#define DEBUG_TYPE "fixup-statepoint-caller-saved"
40STATISTIC(NumSpilledRegisters, "Number of spilled register");
41STATISTIC(NumSpillSlotsAllocated, "Number of spill slots allocated");
42STATISTIC(NumSpillSlotsExtended, "Number of spill slots extended");
43
44static cl::opt<bool> FixupSCSExtendSlotSize(
45 "fixup-scs-extend-slot-size", cl::Hidden, cl::init(false),
46 cl::desc("Allow spill in spill slot of greater size than register size"),
47 cl::Hidden);
48
Denis Antrushin5f6bee72020-06-10 20:52:25 +070049static cl::opt<bool> PassGCPtrInCSR(
50 "fixup-allow-gcptr-in-csr", cl::Hidden, cl::init(false),
51 cl::desc("Allow passing GC Pointer arguments in callee saved registers"));
52
53static cl::opt<bool> EnableCopyProp(
54 "fixup-scs-enable-copy-propagation", cl::Hidden, cl::init(true),
55 cl::desc("Enable simple copy propagation during register reloading"));
56
57// This is purely debugging option.
58// It may be handy for investigating statepoint spilling issues.
59static cl::opt<unsigned> MaxStatepointsWithRegs(
60 "fixup-max-csr-statepoints", cl::Hidden,
61 cl::desc("Max number of statepoints allowed to pass GC Ptrs in registers"));
62
Serguei Katkov4275eb12020-04-09 18:40:53 +070063namespace {
64
65class FixupStatepointCallerSaved : public MachineFunctionPass {
66public:
67 static char ID;
68
69 FixupStatepointCallerSaved() : MachineFunctionPass(ID) {
70 initializeFixupStatepointCallerSavedPass(*PassRegistry::getPassRegistry());
71 }
72
73 void getAnalysisUsage(AnalysisUsage &AU) const override {
Craig Topperde92dc22020-05-13 10:29:04 -070074 AU.setPreservesCFG();
Serguei Katkov4275eb12020-04-09 18:40:53 +070075 MachineFunctionPass::getAnalysisUsage(AU);
76 }
77
78 StringRef getPassName() const override {
79 return "Fixup Statepoint Caller Saved";
80 }
81
82 bool runOnMachineFunction(MachineFunction &MF) override;
83};
Denis Antrushin5f6bee72020-06-10 20:52:25 +070084
Serguei Katkov4275eb12020-04-09 18:40:53 +070085} // End anonymous namespace.
86
87char FixupStatepointCallerSaved::ID = 0;
88char &llvm::FixupStatepointCallerSavedID = FixupStatepointCallerSaved::ID;
89
90INITIALIZE_PASS_BEGIN(FixupStatepointCallerSaved, DEBUG_TYPE,
91 "Fixup Statepoint Caller Saved", false, false)
92INITIALIZE_PASS_END(FixupStatepointCallerSaved, DEBUG_TYPE,
93 "Fixup Statepoint Caller Saved", false, false)
94
95// Utility function to get size of the register.
96static unsigned getRegisterSize(const TargetRegisterInfo &TRI, Register Reg) {
97 const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);
98 return TRI.getSpillSize(*RC);
99}
100
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700101// Advance iterator to the next stack map entry
102static MachineInstr::const_mop_iterator
103advanceToNextStackMapElt(MachineInstr::const_mop_iterator MOI) {
104 if (MOI->isImm()) {
105 switch (MOI->getImm()) {
106 default:
107 llvm_unreachable("Unrecognized operand type.");
108 case StackMaps::DirectMemRefOp:
109 MOI += 2; // <Reg>, <Imm>
110 break;
111 case StackMaps::IndirectMemRefOp:
112 MOI += 3; // <Size>, <Reg>, <Imm>
113 break;
114 case StackMaps::ConstantOp:
115 MOI += 1;
116 break;
117 }
118 }
119 return ++MOI;
120}
121
122// Return statepoint GC args as a set
123static SmallSet<Register, 8> collectGCRegs(MachineInstr &MI) {
124 StatepointOpers SO(&MI);
125 unsigned NumDeoptIdx = SO.getNumDeoptArgsIdx();
126 unsigned NumDeoptArgs = MI.getOperand(NumDeoptIdx).getImm();
127 MachineInstr::const_mop_iterator MOI(MI.operands_begin() + NumDeoptIdx + 1),
128 MOE(MI.operands_end());
129
130 // Skip deopt args
131 while (NumDeoptArgs--)
132 MOI = advanceToNextStackMapElt(MOI);
133
134 SmallSet<Register, 8> Result;
135 while (MOI != MOE) {
136 if (MOI->isReg() && !MOI->isImplicit())
137 Result.insert(MOI->getReg());
138 MOI = advanceToNextStackMapElt(MOI);
139 }
140 return Result;
141}
142
143// Try to eliminate redundant copy to register which we're going to
144// spill, i.e. try to change:
145// X = COPY Y
146// SPILL X
147// to
148// SPILL Y
149// If there are no uses of X between copy and STATEPOINT, that COPY
150// may be eliminated.
151// Reg - register we're about to spill
152// RI - On entry points to statepoint.
153// On successful copy propagation set to new spill point.
154// IsKill - set to true if COPY is Kill (there are no uses of Y)
155// Returns either found source copy register or original one.
156static Register performCopyPropagation(Register Reg,
157 MachineBasicBlock::iterator &RI,
158 bool &IsKill, const TargetInstrInfo &TII,
159 const TargetRegisterInfo &TRI) {
160 if (!EnableCopyProp)
161 return Reg;
162
163 // First check if statepoint itself uses Reg in non-meta operands.
164 int Idx = RI->findRegisterUseOperandIdx(Reg, false, &TRI);
165 if (Idx >= 0 && (unsigned)Idx < StatepointOpers(&*RI).getNumDeoptArgsIdx())
166 return Reg;
167
168 MachineBasicBlock *MBB = RI->getParent();
169 MachineBasicBlock::reverse_iterator E = MBB->rend();
170 MachineInstr *Def = nullptr, *Use = nullptr;
171 for (auto It = ++(RI.getReverse()); It != E; ++It) {
172 if (It->readsRegister(Reg, &TRI) && !Use)
173 Use = &*It;
174 if (It->modifiesRegister(Reg, &TRI)) {
175 Def = &*It;
176 break;
177 }
178 }
179
180 if (!Def)
181 return Reg;
182
183 auto DestSrc = TII.isCopyInstr(*Def);
184 if (!DestSrc || DestSrc->Destination->getReg() != Reg)
185 return Reg;
186
187 Register SrcReg = DestSrc->Source->getReg();
188
189 if (getRegisterSize(TRI, Reg) != getRegisterSize(TRI, SrcReg))
190 return Reg;
191
192 LLVM_DEBUG(dbgs() << "spillRegisters: perform copy propagation "
193 << printReg(Reg, &TRI) << " -> " << printReg(SrcReg, &TRI)
194 << "\n");
195
196 // Insert spill immediately after Def
197 RI = ++MachineBasicBlock::iterator(Def);
198 IsKill = DestSrc->Source->isKill();
199
200 // There are no uses of original register between COPY and STATEPOINT.
201 // There can't be any after STATEPOINT, so we can eliminate Def.
202 if (!Use) {
203 LLVM_DEBUG(dbgs() << "spillRegisters: removing dead copy " << *Def);
204 Def->eraseFromParent();
205 }
206 return SrcReg;
207}
208
Benjamin Kramer1d427642020-04-25 11:50:52 +0200209namespace {
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700210// Pair {Register, FrameIndex}
211using RegSlotPair = std::pair<Register, int>;
212
213// Keeps track of what reloads were inserted in MBB.
214class RegReloadCache {
215 using ReloadSet = SmallSet<RegSlotPair, 8>;
216 DenseMap<const MachineBasicBlock *, ReloadSet> Reloads;
217
218public:
219 RegReloadCache() = default;
220
221 // Record reload of Reg from FI in block MBB
222 void recordReload(Register Reg, int FI, const MachineBasicBlock *MBB) {
223 RegSlotPair RSP(Reg, FI);
224 auto Res = Reloads[MBB].insert(RSP);
225 assert(Res.second && "reload already exists");
226 }
227
228 // Does basic block MBB contains reload of Reg from FI?
229 bool hasReload(Register Reg, int FI, const MachineBasicBlock *MBB) {
230 RegSlotPair RSP(Reg, FI);
231 return Reloads.count(MBB) && Reloads[MBB].count(RSP);
232 }
233};
234
Serguei Katkov4275eb12020-04-09 18:40:53 +0700235// Cache used frame indexes during statepoint re-write to re-use them in
236// processing next statepoint instruction.
237// Two strategies. One is to preserve the size of spill slot while another one
238// extends the size of spill slots to reduce the number of them, causing
239// the less total frame size. But unspill will have "implicit" any extend.
240class FrameIndexesCache {
241private:
242 struct FrameIndexesPerSize {
243 // List of used frame indexes during processing previous statepoints.
244 SmallVector<int, 8> Slots;
245 // Current index of un-used yet frame index.
246 unsigned Index = 0;
247 };
248 MachineFrameInfo &MFI;
249 const TargetRegisterInfo &TRI;
250 // Map size to list of frame indexes of this size. If the mode is
251 // FixupSCSExtendSlotSize then the key 0 is used to keep all frame indexes.
252 // If the size of required spill slot is greater than in a cache then the
253 // size will be increased.
254 DenseMap<unsigned, FrameIndexesPerSize> Cache;
255
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700256 // Keeps track of slots reserved for the shared landing pad processing.
257 // Initialized from GlobalIndices for the current EHPad.
258 SmallSet<int, 8> ReservedSlots;
259
260 // Landing pad can be destination of several statepoints. Every register
261 // defined by such statepoints must be spilled to the same stack slot.
262 // This map keeps that information.
263 DenseMap<const MachineBasicBlock *, SmallVector<RegSlotPair, 8>>
264 GlobalIndices;
265
266 FrameIndexesPerSize &getCacheBucket(unsigned Size) {
267 // In FixupSCSExtendSlotSize mode the bucket with 0 index is used
268 // for all sizes.
269 return Cache[FixupSCSExtendSlotSize ? 0 : Size];
270 }
271
Serguei Katkov4275eb12020-04-09 18:40:53 +0700272public:
273 FrameIndexesCache(MachineFrameInfo &MFI, const TargetRegisterInfo &TRI)
274 : MFI(MFI), TRI(TRI) {}
275 // Reset the current state of used frame indexes. After invocation of
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700276 // this function all frame indexes are available for allocation with
277 // the exception of slots reserved for landing pad processing (if any).
278 void reset(const MachineBasicBlock *EHPad) {
Serguei Katkov4275eb12020-04-09 18:40:53 +0700279 for (auto &It : Cache)
280 It.second.Index = 0;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700281
282 ReservedSlots.clear();
283 if (EHPad && GlobalIndices.count(EHPad))
284 for (auto &RSP : GlobalIndices[EHPad])
285 ReservedSlots.insert(RSP.second);
Serguei Katkov4275eb12020-04-09 18:40:53 +0700286 }
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700287
Serguei Katkov4275eb12020-04-09 18:40:53 +0700288 // Get frame index to spill the register.
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700289 int getFrameIndex(Register Reg, MachineBasicBlock *EHPad) {
290 // Check if slot for Reg is already reserved at EHPad.
291 auto It = GlobalIndices.find(EHPad);
292 if (It != GlobalIndices.end()) {
293 auto &Vec = It->second;
294 auto Idx = llvm::find_if(
295 Vec, [Reg](RegSlotPair &RSP) { return Reg == RSP.first; });
296 if (Idx != Vec.end()) {
297 int FI = Idx->second;
298 LLVM_DEBUG(dbgs() << "Found global FI " << FI << " for register "
299 << printReg(Reg, &TRI) << " at "
300 << printMBBReference(*EHPad) << "\n");
301 assert(ReservedSlots.count(FI) && "using unreserved slot");
302 return FI;
303 }
304 }
305
Serguei Katkov4275eb12020-04-09 18:40:53 +0700306 unsigned Size = getRegisterSize(TRI, Reg);
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700307 FrameIndexesPerSize &Line = getCacheBucket(Size);
308 while (Line.Index < Line.Slots.size()) {
Serguei Katkov4275eb12020-04-09 18:40:53 +0700309 int FI = Line.Slots[Line.Index++];
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700310 if (ReservedSlots.count(FI))
311 continue;
Serguei Katkov4275eb12020-04-09 18:40:53 +0700312 // If all sizes are kept together we probably need to extend the
313 // spill slot size.
314 if (MFI.getObjectSize(FI) < Size) {
315 MFI.setObjectSize(FI, Size);
316 MFI.setObjectAlignment(FI, Align(Size));
317 NumSpillSlotsExtended++;
318 }
319 return FI;
320 }
Guillaume Chatelet7f37d882020-07-01 08:49:28 +0000321 int FI = MFI.CreateSpillStackObject(Size, Align(Size));
Serguei Katkov4275eb12020-04-09 18:40:53 +0700322 NumSpillSlotsAllocated++;
323 Line.Slots.push_back(FI);
324 ++Line.Index;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700325
326 // Remember assignment {Reg, FI} for EHPad
327 if (EHPad) {
328 GlobalIndices[EHPad].push_back(std::make_pair(Reg, FI));
329 LLVM_DEBUG(dbgs() << "Reserved FI " << FI << " for spilling reg "
330 << printReg(Reg, &TRI) << " at landing pad "
331 << printMBBReference(*EHPad) << "\n");
332 }
333
Serguei Katkov4275eb12020-04-09 18:40:53 +0700334 return FI;
335 }
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700336
Serguei Katkov4275eb12020-04-09 18:40:53 +0700337 // Sort all registers to spill in descendent order. In the
338 // FixupSCSExtendSlotSize mode it will minimize the total frame size.
339 // In non FixupSCSExtendSlotSize mode we can skip this step.
340 void sortRegisters(SmallVectorImpl<Register> &Regs) {
341 if (!FixupSCSExtendSlotSize)
342 return;
343 llvm::sort(Regs.begin(), Regs.end(), [&](Register &A, Register &B) {
344 return getRegisterSize(TRI, A) > getRegisterSize(TRI, B);
345 });
346 }
347};
348
349// Describes the state of the current processing statepoint instruction.
350class StatepointState {
351private:
352 // statepoint instruction.
353 MachineInstr &MI;
354 MachineFunction &MF;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700355 // If non-null then statepoint is invoke, and this points to the landing pad.
356 MachineBasicBlock *EHPad;
Serguei Katkov4275eb12020-04-09 18:40:53 +0700357 const TargetRegisterInfo &TRI;
358 const TargetInstrInfo &TII;
359 MachineFrameInfo &MFI;
360 // Mask with callee saved registers.
361 const uint32_t *Mask;
362 // Cache of frame indexes used on previous instruction processing.
363 FrameIndexesCache &CacheFI;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700364 bool AllowGCPtrInCSR;
Serguei Katkov4275eb12020-04-09 18:40:53 +0700365 // Operands with physical registers requiring spilling.
366 SmallVector<unsigned, 8> OpsToSpill;
367 // Set of register to spill.
368 SmallVector<Register, 8> RegsToSpill;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700369 // Set of registers to reload after statepoint.
370 SmallVector<Register, 8> RegsToReload;
Serguei Katkov4275eb12020-04-09 18:40:53 +0700371 // Map Register to Frame Slot index.
372 DenseMap<Register, int> RegToSlotIdx;
373
374public:
375 StatepointState(MachineInstr &MI, const uint32_t *Mask,
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700376 FrameIndexesCache &CacheFI, bool AllowGCPtrInCSR)
Serguei Katkov4275eb12020-04-09 18:40:53 +0700377 : MI(MI), MF(*MI.getMF()), TRI(*MF.getSubtarget().getRegisterInfo()),
378 TII(*MF.getSubtarget().getInstrInfo()), MFI(MF.getFrameInfo()),
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700379 Mask(Mask), CacheFI(CacheFI), AllowGCPtrInCSR(AllowGCPtrInCSR) {
380
381 // Find statepoint's landing pad, if any.
382 EHPad = nullptr;
383 MachineBasicBlock *MBB = MI.getParent();
384 // Invoke statepoint must be last one in block.
385 bool Last = std::none_of(++MI.getIterator(), MBB->end().getInstrIterator(),
386 [](MachineInstr &I) {
387 return I.getOpcode() == TargetOpcode::STATEPOINT;
388 });
389
390 if (!Last)
391 return;
392
393 auto IsEHPad = [](MachineBasicBlock *B) { return B->isEHPad(); };
394
395 assert(llvm::count_if(MBB->successors(), IsEHPad) < 2 && "multiple EHPads");
396
397 auto It = llvm::find_if(MBB->successors(), IsEHPad);
398 if (It != MBB->succ_end())
399 EHPad = *It;
400 }
401
402 MachineBasicBlock *getEHPad() const { return EHPad; }
403
Serguei Katkov4275eb12020-04-09 18:40:53 +0700404 // Return true if register is callee saved.
405 bool isCalleeSaved(Register Reg) { return (Mask[Reg / 32] >> Reg % 32) & 1; }
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700406
Serguei Katkov4275eb12020-04-09 18:40:53 +0700407 // Iterates over statepoint meta args to find caller saver registers.
408 // Also cache the size of found registers.
409 // Returns true if caller save registers found.
410 bool findRegistersToSpill() {
411 SmallSet<Register, 8> VisitedRegs;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700412 SmallSet<Register, 8> GCRegs = collectGCRegs(MI);
Serguei Katkov4275eb12020-04-09 18:40:53 +0700413 for (unsigned Idx = StatepointOpers(&MI).getVarIdx(),
414 EndIdx = MI.getNumOperands();
415 Idx < EndIdx; ++Idx) {
416 MachineOperand &MO = MI.getOperand(Idx);
417 if (!MO.isReg() || MO.isImplicit())
418 continue;
419 Register Reg = MO.getReg();
420 assert(Reg.isPhysical() && "Only physical regs are expected");
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700421
422 if (isCalleeSaved(Reg) && (AllowGCPtrInCSR || !is_contained(GCRegs, Reg)))
Serguei Katkov4275eb12020-04-09 18:40:53 +0700423 continue;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700424
425 LLVM_DEBUG(dbgs() << "Will spill " << printReg(Reg, &TRI) << " at index "
426 << Idx << "\n");
427
Serguei Katkov4275eb12020-04-09 18:40:53 +0700428 if (VisitedRegs.insert(Reg).second)
429 RegsToSpill.push_back(Reg);
430 OpsToSpill.push_back(Idx);
431 }
432 CacheFI.sortRegisters(RegsToSpill);
433 return !RegsToSpill.empty();
434 }
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700435
Serguei Katkov4275eb12020-04-09 18:40:53 +0700436 // Spill all caller saved registers right before statepoint instruction.
437 // Remember frame index where register is spilled.
438 void spillRegisters() {
439 for (Register Reg : RegsToSpill) {
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700440 int FI = CacheFI.getFrameIndex(Reg, EHPad);
Serguei Katkov4275eb12020-04-09 18:40:53 +0700441 const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700442
Serguei Katkov4275eb12020-04-09 18:40:53 +0700443 NumSpilledRegisters++;
444 RegToSlotIdx[Reg] = FI;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700445
446 LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, &TRI) << " to FI " << FI
447 << "\n");
448
449 // Perform trivial copy propagation
450 bool IsKill = true;
451 MachineBasicBlock::iterator InsertBefore(MI);
452 Reg = performCopyPropagation(Reg, InsertBefore, IsKill, TII, TRI);
453
454 LLVM_DEBUG(dbgs() << "Insert spill before " << *InsertBefore);
455 TII.storeRegToStackSlot(*MI.getParent(), InsertBefore, Reg, IsKill, FI,
456 RC, &TRI);
Serguei Katkov4275eb12020-04-09 18:40:53 +0700457 }
458 }
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700459
460 void insertReloadBefore(unsigned Reg, MachineBasicBlock::iterator It,
461 MachineBasicBlock *MBB) {
462 const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);
463 int FI = RegToSlotIdx[Reg];
464 if (It != MBB->end()) {
465 TII.loadRegFromStackSlot(*MBB, It, Reg, FI, RC, &TRI);
466 return;
467 }
468
469 // To insert reload at the end of MBB, insert it before last instruction
470 // and then swap them.
471 assert(MBB->begin() != MBB->end() && "Empty block");
472 --It;
473 TII.loadRegFromStackSlot(*MBB, It, Reg, FI, RC, &TRI);
474 MachineInstr *Reload = It->getPrevNode();
475 int Dummy = 0;
476 assert(TII.isLoadFromStackSlot(*Reload, Dummy) == Reg);
477 assert(Dummy == FI);
478 MBB->remove(Reload);
479 MBB->insertAfter(It, Reload);
480 }
481
482 // Insert reloads of (relocated) registers spilled in statepoint.
483 void insertReloads(MachineInstr *NewStatepoint, RegReloadCache &RC) {
484 MachineBasicBlock *MBB = NewStatepoint->getParent();
485 auto InsertPoint = std::next(NewStatepoint->getIterator());
486
487 for (auto Reg : RegsToReload) {
488 insertReloadBefore(Reg, InsertPoint, MBB);
489 LLVM_DEBUG(dbgs() << "Reloading " << printReg(Reg, &TRI) << " from FI "
490 << RegToSlotIdx[Reg] << " after statepoint\n");
491
492 if (EHPad && !RC.hasReload(Reg, RegToSlotIdx[Reg], EHPad)) {
493 RC.recordReload(Reg, RegToSlotIdx[Reg], EHPad);
494 auto EHPadInsertPoint = EHPad->SkipPHIsLabelsAndDebug(EHPad->begin());
495 insertReloadBefore(Reg, EHPadInsertPoint, EHPad);
496 LLVM_DEBUG(dbgs() << "...also reload at EHPad "
497 << printMBBReference(*EHPad) << "\n");
498 }
499 }
500 }
501
Serguei Katkov4275eb12020-04-09 18:40:53 +0700502 // Re-write statepoint machine instruction to replace caller saved operands
503 // with indirect memory location (frame index).
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700504 MachineInstr *rewriteStatepoint() {
Serguei Katkov4275eb12020-04-09 18:40:53 +0700505 MachineInstr *NewMI =
506 MF.CreateMachineInstr(TII.get(MI.getOpcode()), MI.getDebugLoc(), true);
507 MachineInstrBuilder MIB(MF, NewMI);
508
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700509 unsigned NumOps = MI.getNumOperands();
510
511 // New indices for the remaining defs.
512 SmallVector<unsigned, 8> NewIndices;
513 unsigned NumDefs = MI.getNumDefs();
514 for (unsigned I = 0; I < NumDefs; ++I) {
515 MachineOperand &DefMO = MI.getOperand(I);
516 assert(DefMO.isReg() && DefMO.isDef() && "Expected Reg Def operand");
517 Register Reg = DefMO.getReg();
518 if (!AllowGCPtrInCSR) {
519 assert(is_contained(RegsToSpill, Reg));
520 RegsToReload.push_back(Reg);
521 } else {
522 if (isCalleeSaved(Reg)) {
523 NewIndices.push_back(NewMI->getNumOperands());
524 MIB.addReg(Reg, RegState::Define);
525 } else {
526 NewIndices.push_back(NumOps);
527 RegsToReload.push_back(Reg);
528 }
529 }
530 }
531
Serguei Katkov4275eb12020-04-09 18:40:53 +0700532 // Add End marker.
533 OpsToSpill.push_back(MI.getNumOperands());
534 unsigned CurOpIdx = 0;
535
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700536 for (unsigned I = NumDefs; I < MI.getNumOperands(); ++I) {
Serguei Katkov4275eb12020-04-09 18:40:53 +0700537 MachineOperand &MO = MI.getOperand(I);
538 if (I == OpsToSpill[CurOpIdx]) {
539 int FI = RegToSlotIdx[MO.getReg()];
540 MIB.addImm(StackMaps::IndirectMemRefOp);
541 MIB.addImm(getRegisterSize(TRI, MO.getReg()));
542 assert(MO.isReg() && "Should be register");
543 assert(MO.getReg().isPhysical() && "Should be physical register");
544 MIB.addFrameIndex(FI);
545 MIB.addImm(0);
546 ++CurOpIdx;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700547 } else {
Serguei Katkov4275eb12020-04-09 18:40:53 +0700548 MIB.add(MO);
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700549 unsigned OldDef;
550 if (AllowGCPtrInCSR && MI.isRegTiedToDefOperand(I, &OldDef)) {
551 assert(OldDef < NumDefs);
552 assert(NewIndices[OldDef] < NumOps);
553 MIB->tieOperands(NewIndices[OldDef], MIB->getNumOperands() - 1);
554 }
555 }
Serguei Katkov4275eb12020-04-09 18:40:53 +0700556 }
557 assert(CurOpIdx == (OpsToSpill.size() - 1) && "Not all operands processed");
558 // Add mem operands.
559 NewMI->setMemRefs(MF, MI.memoperands());
560 for (auto It : RegToSlotIdx) {
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700561 Register R = It.first;
Serguei Katkov4275eb12020-04-09 18:40:53 +0700562 int FrameIndex = It.second;
563 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700564 MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad;
565 if (is_contained(RegsToReload, R))
566 Flags |= MachineMemOperand::MOStore;
567 auto *MMO =
568 MF.getMachineMemOperand(PtrInfo, Flags, getRegisterSize(TRI, R),
569 MFI.getObjectAlign(FrameIndex));
Serguei Katkov4275eb12020-04-09 18:40:53 +0700570 NewMI->addMemOperand(MF, MMO);
571 }
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700572
Serguei Katkov4275eb12020-04-09 18:40:53 +0700573 // Insert new statepoint and erase old one.
574 MI.getParent()->insert(MI, NewMI);
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700575
576 LLVM_DEBUG(dbgs() << "rewritten statepoint to : " << *NewMI << "\n");
Serguei Katkov4275eb12020-04-09 18:40:53 +0700577 MI.eraseFromParent();
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700578 return NewMI;
Serguei Katkov4275eb12020-04-09 18:40:53 +0700579 }
580};
581
582class StatepointProcessor {
583private:
584 MachineFunction &MF;
585 const TargetRegisterInfo &TRI;
586 FrameIndexesCache CacheFI;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700587 RegReloadCache ReloadCache;
Serguei Katkov4275eb12020-04-09 18:40:53 +0700588
589public:
590 StatepointProcessor(MachineFunction &MF)
591 : MF(MF), TRI(*MF.getSubtarget().getRegisterInfo()),
592 CacheFI(MF.getFrameInfo(), TRI) {}
593
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700594 bool process(MachineInstr &MI, bool AllowGCPtrInCSR) {
Denis Antrushinedbb27c2020-04-14 18:30:51 +0300595 StatepointOpers SO(&MI);
596 uint64_t Flags = SO.getFlags();
Serguei Katkov4275eb12020-04-09 18:40:53 +0700597 // Do nothing for LiveIn, it supports all registers.
598 if (Flags & (uint64_t)StatepointFlags::DeoptLiveIn)
599 return false;
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700600 LLVM_DEBUG(dbgs() << "\nMBB " << MI.getParent()->getNumber() << " "
601 << MI.getParent()->getName() << " : process statepoint "
602 << MI);
Denis Antrushinedbb27c2020-04-14 18:30:51 +0300603 CallingConv::ID CC = SO.getCallingConv();
Serguei Katkov4275eb12020-04-09 18:40:53 +0700604 const uint32_t *Mask = TRI.getCallPreservedMask(MF, CC);
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700605 StatepointState SS(MI, Mask, CacheFI, AllowGCPtrInCSR);
606 CacheFI.reset(SS.getEHPad());
Serguei Katkov4275eb12020-04-09 18:40:53 +0700607
608 if (!SS.findRegistersToSpill())
609 return false;
610
611 SS.spillRegisters();
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700612 auto *NewStatepoint = SS.rewriteStatepoint();
613 SS.insertReloads(NewStatepoint, ReloadCache);
Serguei Katkov4275eb12020-04-09 18:40:53 +0700614 return true;
615 }
616};
Benjamin Kramer1d427642020-04-25 11:50:52 +0200617} // namespace
Serguei Katkov4275eb12020-04-09 18:40:53 +0700618
619bool FixupStatepointCallerSaved::runOnMachineFunction(MachineFunction &MF) {
620 if (skipFunction(MF.getFunction()))
621 return false;
622
623 const Function &F = MF.getFunction();
624 if (!F.hasGC())
625 return false;
626
627 SmallVector<MachineInstr *, 16> Statepoints;
628 for (MachineBasicBlock &BB : MF)
629 for (MachineInstr &I : BB)
630 if (I.getOpcode() == TargetOpcode::STATEPOINT)
631 Statepoints.push_back(&I);
632
633 if (Statepoints.empty())
634 return false;
635
636 bool Changed = false;
637 StatepointProcessor SPP(MF);
Denis Antrushin5f6bee72020-06-10 20:52:25 +0700638 unsigned NumStatepoints = 0;
639 bool AllowGCPtrInCSR = PassGCPtrInCSR;
640 for (MachineInstr *I : Statepoints) {
641 ++NumStatepoints;
642 if (MaxStatepointsWithRegs.getNumOccurrences() &&
643 NumStatepoints >= MaxStatepointsWithRegs)
644 AllowGCPtrInCSR = false;
645 Changed |= SPP.process(*I, AllowGCPtrInCSR);
646 }
Serguei Katkov4275eb12020-04-09 18:40:53 +0700647 return Changed;
648}