644 lines · cpp
1//===-- FixupStatepointCallerSaved.cpp - Fixup caller saved registers ----===//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/// \file10/// Statepoint instruction in deopt parameters contains values which are11/// meaningful to the runtime and should be able to be read at the moment the12/// call returns. So we can say that we need to encode the fact that these13/// values are "late read" by runtime. If we could express this notion for14/// register allocator it would produce the right form for us.15/// The need to fixup (i.e this pass) is specifically handling the fact that16/// we cannot describe such a late read for the register allocator.17/// Register allocator may put the value on a register clobbered by the call.18/// This pass forces the spill of such registers and replaces corresponding19/// statepoint operands to added spill slots.20///21//===----------------------------------------------------------------------===//22 23#include "llvm/CodeGen/FixupStatepointCallerSaved.h"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/StackMaps.h"29#include "llvm/CodeGen/TargetInstrInfo.h"30#include "llvm/IR/Statepoint.h"31#include "llvm/InitializePasses.h"32#include "llvm/Support/Debug.h"33 34using namespace llvm;35 36#define DEBUG_TYPE "fixup-statepoint-caller-saved"37STATISTIC(NumSpilledRegisters, "Number of spilled register");38STATISTIC(NumSpillSlotsAllocated, "Number of spill slots allocated");39STATISTIC(NumSpillSlotsExtended, "Number of spill slots extended");40 41static cl::opt<bool> FixupSCSExtendSlotSize(42 "fixup-scs-extend-slot-size", cl::Hidden, cl::init(false),43 cl::desc("Allow spill in spill slot of greater size than register size"),44 cl::Hidden);45 46static cl::opt<bool> PassGCPtrInCSR(47 "fixup-allow-gcptr-in-csr", cl::Hidden, cl::init(false),48 cl::desc("Allow passing GC Pointer arguments in callee saved registers"));49 50static cl::opt<bool> EnableCopyProp(51 "fixup-scs-enable-copy-propagation", cl::Hidden, cl::init(true),52 cl::desc("Enable simple copy propagation during register reloading"));53 54// This is purely debugging option.55// It may be handy for investigating statepoint spilling issues.56static cl::opt<unsigned> MaxStatepointsWithRegs(57 "fixup-max-csr-statepoints", cl::Hidden,58 cl::desc("Max number of statepoints allowed to pass GC Ptrs in registers"));59 60namespace {61 62struct FixupStatepointCallerSavedImpl {63 bool run(MachineFunction &MF);64};65 66class FixupStatepointCallerSavedLegacy : public MachineFunctionPass {67public:68 static char ID;69 70 FixupStatepointCallerSavedLegacy() : MachineFunctionPass(ID) {71 initializeFixupStatepointCallerSavedLegacyPass(72 *PassRegistry::getPassRegistry());73 }74 void getAnalysisUsage(AnalysisUsage &AU) const override {75 AU.setPreservesCFG();76 MachineFunctionPass::getAnalysisUsage(AU);77 }78 79 StringRef getPassName() const override {80 return "Fixup Statepoint Caller Saved";81 }82 83 bool runOnMachineFunction(MachineFunction &MF) override;84};85 86} // End anonymous namespace.87 88char FixupStatepointCallerSavedLegacy::ID = 0;89char &llvm::FixupStatepointCallerSavedID = FixupStatepointCallerSavedLegacy::ID;90 91INITIALIZE_PASS_BEGIN(FixupStatepointCallerSavedLegacy, DEBUG_TYPE,92 "Fixup Statepoint Caller Saved", false, false)93INITIALIZE_PASS_END(FixupStatepointCallerSavedLegacy, DEBUG_TYPE,94 "Fixup Statepoint Caller Saved", false, false)95 96// Utility function to get size of the register.97static unsigned getRegisterSize(const TargetRegisterInfo &TRI, Register Reg) {98 const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);99 return TRI.getSpillSize(*RC);100}101 102// Try to eliminate redundant copy to register which we're going to103// spill, i.e. try to change:104// X = COPY Y105// SPILL X106// to107// SPILL Y108// If there are no uses of X between copy and STATEPOINT, that COPY109// may be eliminated.110// Reg - register we're about to spill111// RI - On entry points to statepoint.112// On successful copy propagation set to new spill point.113// IsKill - set to true if COPY is Kill (there are no uses of Y)114// Returns either found source copy register or original one.115static Register performCopyPropagation(Register Reg,116 MachineBasicBlock::iterator &RI,117 bool &IsKill, const TargetInstrInfo &TII,118 const TargetRegisterInfo &TRI) {119 // First check if statepoint itself uses Reg in non-meta operands.120 int Idx = RI->findRegisterUseOperandIdx(Reg, &TRI, false);121 if (Idx >= 0 && (unsigned)Idx < StatepointOpers(&*RI).getNumDeoptArgsIdx()) {122 IsKill = false;123 return Reg;124 }125 126 if (!EnableCopyProp)127 return Reg;128 129 MachineBasicBlock *MBB = RI->getParent();130 MachineBasicBlock::reverse_iterator E = MBB->rend();131 MachineInstr *Def = nullptr, *Use = nullptr;132 for (auto It = ++(RI.getReverse()); It != E; ++It) {133 if (It->readsRegister(Reg, &TRI) && !Use)134 Use = &*It;135 if (It->modifiesRegister(Reg, &TRI)) {136 Def = &*It;137 break;138 }139 }140 141 if (!Def)142 return Reg;143 144 auto DestSrc = TII.isCopyInstr(*Def);145 if (!DestSrc || DestSrc->Destination->getReg() != Reg)146 return Reg;147 148 Register SrcReg = DestSrc->Source->getReg();149 150 if (getRegisterSize(TRI, Reg) != getRegisterSize(TRI, SrcReg))151 return Reg;152 153 LLVM_DEBUG(dbgs() << "spillRegisters: perform copy propagation "154 << printReg(Reg, &TRI) << " -> " << printReg(SrcReg, &TRI)155 << "\n");156 157 // Insert spill immediately after Def158 RI = ++MachineBasicBlock::iterator(Def);159 IsKill = DestSrc->Source->isKill();160 161 if (!Use) {162 // There are no uses of original register between COPY and STATEPOINT.163 // There can't be any after STATEPOINT, so we can eliminate Def.164 LLVM_DEBUG(dbgs() << "spillRegisters: removing dead copy " << *Def);165 Def->eraseFromParent();166 } else if (IsKill) {167 // COPY will remain in place, spill will be inserted *after* it, so it is168 // not a kill of source anymore.169 const_cast<MachineOperand *>(DestSrc->Source)->setIsKill(false);170 }171 172 return SrcReg;173}174 175namespace {176// Pair {Register, FrameIndex}177using RegSlotPair = std::pair<Register, int>;178 179// Keeps track of what reloads were inserted in MBB.180class RegReloadCache {181 using ReloadSet = SmallSet<RegSlotPair, 8>;182 DenseMap<const MachineBasicBlock *, ReloadSet> Reloads;183 184public:185 RegReloadCache() = default;186 187 // Record reload of Reg from FI in block MBB if not present yet.188 // Return true if the reload is successfully recorded.189 bool tryRecordReload(Register Reg, int FI, const MachineBasicBlock *MBB) {190 RegSlotPair RSP(Reg, FI);191 return Reloads[MBB].insert(RSP).second;192 }193};194 195// Cache used frame indexes during statepoint re-write to re-use them in196// processing next statepoint instruction.197// Two strategies. One is to preserve the size of spill slot while another one198// extends the size of spill slots to reduce the number of them, causing199// the less total frame size. But unspill will have "implicit" any extend.200class FrameIndexesCache {201private:202 struct FrameIndexesPerSize {203 // List of used frame indexes during processing previous statepoints.204 SmallVector<int, 8> Slots;205 // Current index of un-used yet frame index.206 unsigned Index = 0;207 };208 MachineFrameInfo &MFI;209 const TargetRegisterInfo &TRI;210 // Map size to list of frame indexes of this size. If the mode is211 // FixupSCSExtendSlotSize then the key 0 is used to keep all frame indexes.212 // If the size of required spill slot is greater than in a cache then the213 // size will be increased.214 DenseMap<unsigned, FrameIndexesPerSize> Cache;215 216 // Keeps track of slots reserved for the shared landing pad processing.217 // Initialized from GlobalIndices for the current EHPad.218 SmallSet<int, 8> ReservedSlots;219 220 // Landing pad can be destination of several statepoints. Every register221 // defined by such statepoints must be spilled to the same stack slot.222 // This map keeps that information.223 DenseMap<const MachineBasicBlock *, SmallVector<RegSlotPair, 8>>224 GlobalIndices;225 226 FrameIndexesPerSize &getCacheBucket(unsigned Size) {227 // In FixupSCSExtendSlotSize mode the bucket with 0 index is used228 // for all sizes.229 return Cache[FixupSCSExtendSlotSize ? 0 : Size];230 }231 232public:233 FrameIndexesCache(MachineFrameInfo &MFI, const TargetRegisterInfo &TRI)234 : MFI(MFI), TRI(TRI) {}235 // Reset the current state of used frame indexes. After invocation of236 // this function all frame indexes are available for allocation with237 // the exception of slots reserved for landing pad processing (if any).238 void reset(const MachineBasicBlock *EHPad) {239 for (auto &It : Cache)240 It.second.Index = 0;241 242 ReservedSlots.clear();243 if (EHPad)244 if (auto It = GlobalIndices.find(EHPad); It != GlobalIndices.end())245 ReservedSlots.insert_range(llvm::make_second_range(It->second));246 }247 248 // Get frame index to spill the register.249 int getFrameIndex(Register Reg, MachineBasicBlock *EHPad) {250 // Check if slot for Reg is already reserved at EHPad.251 auto It = GlobalIndices.find(EHPad);252 if (It != GlobalIndices.end()) {253 auto &Vec = It->second;254 auto Idx = llvm::find_if(255 Vec, [Reg](RegSlotPair &RSP) { return Reg == RSP.first; });256 if (Idx != Vec.end()) {257 int FI = Idx->second;258 LLVM_DEBUG(dbgs() << "Found global FI " << FI << " for register "259 << printReg(Reg, &TRI) << " at "260 << printMBBReference(*EHPad) << "\n");261 assert(ReservedSlots.count(FI) && "using unreserved slot");262 return FI;263 }264 }265 266 unsigned Size = getRegisterSize(TRI, Reg);267 FrameIndexesPerSize &Line = getCacheBucket(Size);268 while (Line.Index < Line.Slots.size()) {269 int FI = Line.Slots[Line.Index++];270 if (ReservedSlots.count(FI))271 continue;272 // If all sizes are kept together we probably need to extend the273 // spill slot size.274 if (MFI.getObjectSize(FI) < Size) {275 MFI.setObjectSize(FI, Size);276 MFI.setObjectAlignment(FI, Align(Size));277 NumSpillSlotsExtended++;278 }279 return FI;280 }281 int FI = MFI.CreateSpillStackObject(Size, Align(Size));282 NumSpillSlotsAllocated++;283 Line.Slots.push_back(FI);284 ++Line.Index;285 286 // Remember assignment {Reg, FI} for EHPad287 if (EHPad) {288 GlobalIndices[EHPad].push_back(std::make_pair(Reg, FI));289 LLVM_DEBUG(dbgs() << "Reserved FI " << FI << " for spilling reg "290 << printReg(Reg, &TRI) << " at landing pad "291 << printMBBReference(*EHPad) << "\n");292 }293 294 return FI;295 }296 297 // Sort all registers to spill in descendent order. In the298 // FixupSCSExtendSlotSize mode it will minimize the total frame size.299 // In non FixupSCSExtendSlotSize mode we can skip this step.300 void sortRegisters(SmallVectorImpl<Register> &Regs) {301 if (!FixupSCSExtendSlotSize)302 return;303 llvm::sort(Regs, [&](Register &A, Register &B) {304 return getRegisterSize(TRI, A) > getRegisterSize(TRI, B);305 });306 }307};308 309// Describes the state of the current processing statepoint instruction.310class StatepointState {311private:312 // statepoint instruction.313 MachineInstr &MI;314 MachineFunction &MF;315 // If non-null then statepoint is invoke, and this points to the landing pad.316 MachineBasicBlock *EHPad;317 const TargetRegisterInfo &TRI;318 const TargetInstrInfo &TII;319 MachineFrameInfo &MFI;320 // Mask with callee saved registers.321 const uint32_t *Mask;322 // Cache of frame indexes used on previous instruction processing.323 FrameIndexesCache &CacheFI;324 bool AllowGCPtrInCSR;325 // Operands with physical registers requiring spilling.326 SmallVector<unsigned, 8> OpsToSpill;327 // Set of register to spill.328 SmallVector<Register, 8> RegsToSpill;329 // Set of registers to reload after statepoint.330 SmallVector<Register, 8> RegsToReload;331 // Map Register to Frame Slot index.332 DenseMap<Register, int> RegToSlotIdx;333 334public:335 StatepointState(MachineInstr &MI, const uint32_t *Mask,336 FrameIndexesCache &CacheFI, bool AllowGCPtrInCSR)337 : MI(MI), MF(*MI.getMF()), TRI(*MF.getSubtarget().getRegisterInfo()),338 TII(*MF.getSubtarget().getInstrInfo()), MFI(MF.getFrameInfo()),339 Mask(Mask), CacheFI(CacheFI), AllowGCPtrInCSR(AllowGCPtrInCSR) {340 341 // Find statepoint's landing pad, if any.342 EHPad = nullptr;343 MachineBasicBlock *MBB = MI.getParent();344 // Invoke statepoint must be last one in block.345 bool Last = std::none_of(++MI.getIterator(), MBB->end().getInstrIterator(),346 [](MachineInstr &I) {347 return I.getOpcode() == TargetOpcode::STATEPOINT;348 });349 350 if (!Last)351 return;352 353 auto IsEHPad = [](MachineBasicBlock *B) { return B->isEHPad(); };354 355 assert(llvm::count_if(MBB->successors(), IsEHPad) < 2 && "multiple EHPads");356 357 auto It = llvm::find_if(MBB->successors(), IsEHPad);358 if (It != MBB->succ_end())359 EHPad = *It;360 }361 362 MachineBasicBlock *getEHPad() const { return EHPad; }363 364 // Return true if register is callee saved.365 bool isCalleeSaved(Register Reg) {366 return (Mask[Reg.id() / 32] >> (Reg.id() % 32)) & 1;367 }368 369 // Iterates over statepoint meta args to find caller saver registers.370 // Also cache the size of found registers.371 // Returns true if caller save registers found.372 bool findRegistersToSpill() {373 SmallSet<Register, 8> GCRegs;374 // All GC pointer operands assigned to registers produce new value.375 // Since they're tied to their defs, it is enough to collect def registers.376 for (const auto &Def : MI.defs())377 GCRegs.insert(Def.getReg());378 379 SmallSet<Register, 8> VisitedRegs;380 for (unsigned Idx = StatepointOpers(&MI).getVarIdx(),381 EndIdx = MI.getNumOperands();382 Idx < EndIdx; ++Idx) {383 MachineOperand &MO = MI.getOperand(Idx);384 if (!MO.isReg() || MO.isImplicit() || MO.isUndef())385 continue;386 Register Reg = MO.getReg();387 assert(Reg.isPhysical() && "Only physical regs are expected");388 389 if (isCalleeSaved(Reg) && (AllowGCPtrInCSR || !GCRegs.contains(Reg)))390 continue;391 392 LLVM_DEBUG(dbgs() << "Will spill " << printReg(Reg, &TRI) << " at index "393 << Idx << "\n");394 395 if (VisitedRegs.insert(Reg).second)396 RegsToSpill.push_back(Reg);397 OpsToSpill.push_back(Idx);398 }399 CacheFI.sortRegisters(RegsToSpill);400 return !RegsToSpill.empty();401 }402 403 // Spill all caller saved registers right before statepoint instruction.404 // Remember frame index where register is spilled.405 void spillRegisters() {406 for (Register Reg : RegsToSpill) {407 int FI = CacheFI.getFrameIndex(Reg, EHPad);408 409 NumSpilledRegisters++;410 RegToSlotIdx[Reg] = FI;411 412 LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, &TRI) << " to FI " << FI413 << "\n");414 415 // Perform trivial copy propagation416 bool IsKill = true;417 MachineBasicBlock::iterator InsertBefore(MI);418 Reg = performCopyPropagation(Reg, InsertBefore, IsKill, TII, TRI);419 const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);420 421 LLVM_DEBUG(dbgs() << "Insert spill before " << *InsertBefore);422 TII.storeRegToStackSlot(*MI.getParent(), InsertBefore, Reg, IsKill, FI,423 RC, Register());424 }425 }426 427 void insertReloadBefore(Register Reg, MachineBasicBlock::iterator It,428 MachineBasicBlock *MBB) {429 const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);430 int FI = RegToSlotIdx[Reg];431 if (It != MBB->end()) {432 TII.loadRegFromStackSlot(*MBB, It, Reg, FI, RC, Register());433 return;434 }435 436 // To insert reload at the end of MBB, insert it before last instruction437 // and then swap them.438 assert(!MBB->empty() && "Empty block");439 --It;440 TII.loadRegFromStackSlot(*MBB, It, Reg, FI, RC, Register());441 MachineInstr *Reload = It->getPrevNode();442 int Dummy = 0;443 (void)Dummy;444 assert(TII.isLoadFromStackSlot(*Reload, Dummy) == Reg);445 assert(Dummy == FI);446 MBB->remove(Reload);447 MBB->insertAfter(It, Reload);448 }449 450 // Insert reloads of (relocated) registers spilled in statepoint.451 void insertReloads(MachineInstr *NewStatepoint, RegReloadCache &RC) {452 MachineBasicBlock *MBB = NewStatepoint->getParent();453 auto InsertPoint = std::next(NewStatepoint->getIterator());454 455 for (auto Reg : RegsToReload) {456 insertReloadBefore(Reg, InsertPoint, MBB);457 LLVM_DEBUG(dbgs() << "Reloading " << printReg(Reg, &TRI) << " from FI "458 << RegToSlotIdx[Reg] << " after statepoint\n");459 460 if (EHPad && RC.tryRecordReload(Reg, RegToSlotIdx[Reg], EHPad)) {461 auto EHPadInsertPoint =462 EHPad->SkipPHIsLabelsAndDebug(EHPad->begin(), Reg);463 insertReloadBefore(Reg, EHPadInsertPoint, EHPad);464 LLVM_DEBUG(dbgs() << "...also reload at EHPad "465 << printMBBReference(*EHPad) << "\n");466 }467 }468 }469 470 // Re-write statepoint machine instruction to replace caller saved operands471 // with indirect memory location (frame index).472 MachineInstr *rewriteStatepoint() {473 MachineInstr *NewMI =474 MF.CreateMachineInstr(TII.get(MI.getOpcode()), MI.getDebugLoc(), true);475 MachineInstrBuilder MIB(MF, NewMI);476 477 unsigned NumOps = MI.getNumOperands();478 479 // New indices for the remaining defs.480 SmallVector<unsigned, 8> NewIndices;481 unsigned NumDefs = MI.getNumDefs();482 for (unsigned I = 0; I < NumDefs; ++I) {483 MachineOperand &DefMO = MI.getOperand(I);484 assert(DefMO.isReg() && DefMO.isDef() && "Expected Reg Def operand");485 Register Reg = DefMO.getReg();486 assert(DefMO.isTied() && "Def is expected to be tied");487 // We skipped undef uses and did not spill them, so we should not488 // proceed with defs here.489 if (MI.getOperand(MI.findTiedOperandIdx(I)).isUndef()) {490 if (AllowGCPtrInCSR) {491 NewIndices.push_back(NewMI->getNumOperands());492 MIB.addReg(Reg, RegState::Define);493 }494 continue;495 }496 if (!AllowGCPtrInCSR) {497 assert(is_contained(RegsToSpill, Reg));498 RegsToReload.push_back(Reg);499 } else {500 if (isCalleeSaved(Reg)) {501 NewIndices.push_back(NewMI->getNumOperands());502 MIB.addReg(Reg, RegState::Define);503 } else {504 NewIndices.push_back(NumOps);505 RegsToReload.push_back(Reg);506 }507 }508 }509 510 // Add End marker.511 OpsToSpill.push_back(MI.getNumOperands());512 unsigned CurOpIdx = 0;513 514 for (unsigned I = NumDefs; I < MI.getNumOperands(); ++I) {515 MachineOperand &MO = MI.getOperand(I);516 if (I == OpsToSpill[CurOpIdx]) {517 int FI = RegToSlotIdx[MO.getReg()];518 MIB.addImm(StackMaps::IndirectMemRefOp);519 MIB.addImm(getRegisterSize(TRI, MO.getReg()));520 assert(MO.isReg() && "Should be register");521 assert(MO.getReg().isPhysical() && "Should be physical register");522 MIB.addFrameIndex(FI);523 MIB.addImm(0);524 ++CurOpIdx;525 } else {526 MIB.add(MO);527 unsigned OldDef;528 if (AllowGCPtrInCSR && MI.isRegTiedToDefOperand(I, &OldDef)) {529 assert(OldDef < NumDefs);530 assert(NewIndices[OldDef] < NumOps);531 MIB->tieOperands(NewIndices[OldDef], MIB->getNumOperands() - 1);532 }533 }534 }535 assert(CurOpIdx == (OpsToSpill.size() - 1) && "Not all operands processed");536 // Add mem operands.537 NewMI->setMemRefs(MF, MI.memoperands());538 for (auto It : RegToSlotIdx) {539 Register R = It.first;540 int FrameIndex = It.second;541 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);542 MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad;543 if (is_contained(RegsToReload, R))544 Flags |= MachineMemOperand::MOStore;545 auto *MMO =546 MF.getMachineMemOperand(PtrInfo, Flags, getRegisterSize(TRI, R),547 MFI.getObjectAlign(FrameIndex));548 NewMI->addMemOperand(MF, MMO);549 }550 551 // Insert new statepoint and erase old one.552 MI.getParent()->insert(MI, NewMI);553 554 LLVM_DEBUG(dbgs() << "rewritten statepoint to : " << *NewMI << "\n");555 MI.eraseFromParent();556 return NewMI;557 }558};559 560class StatepointProcessor {561private:562 MachineFunction &MF;563 const TargetRegisterInfo &TRI;564 FrameIndexesCache CacheFI;565 RegReloadCache ReloadCache;566 567public:568 StatepointProcessor(MachineFunction &MF)569 : MF(MF), TRI(*MF.getSubtarget().getRegisterInfo()),570 CacheFI(MF.getFrameInfo(), TRI) {}571 572 bool process(MachineInstr &MI, bool AllowGCPtrInCSR) {573 StatepointOpers SO(&MI);574 uint64_t Flags = SO.getFlags();575 // Do nothing for LiveIn, it supports all registers.576 if (Flags & (uint64_t)StatepointFlags::DeoptLiveIn)577 return false;578 LLVM_DEBUG(dbgs() << "\nMBB " << MI.getParent()->getNumber() << " "579 << MI.getParent()->getName() << " : process statepoint "580 << MI);581 CallingConv::ID CC = SO.getCallingConv();582 const uint32_t *Mask = TRI.getCallPreservedMask(MF, CC);583 StatepointState SS(MI, Mask, CacheFI, AllowGCPtrInCSR);584 CacheFI.reset(SS.getEHPad());585 586 if (!SS.findRegistersToSpill())587 return false;588 589 SS.spillRegisters();590 auto *NewStatepoint = SS.rewriteStatepoint();591 SS.insertReloads(NewStatepoint, ReloadCache);592 return true;593 }594};595} // namespace596 597bool FixupStatepointCallerSavedImpl::run(MachineFunction &MF) {598 const Function &F = MF.getFunction();599 if (!F.hasGC())600 return false;601 602 SmallVector<MachineInstr *, 16> Statepoints;603 for (MachineBasicBlock &BB : MF)604 for (MachineInstr &I : BB)605 if (I.getOpcode() == TargetOpcode::STATEPOINT)606 Statepoints.push_back(&I);607 608 if (Statepoints.empty())609 return false;610 611 bool Changed = false;612 StatepointProcessor SPP(MF);613 unsigned NumStatepoints = 0;614 bool AllowGCPtrInCSR = PassGCPtrInCSR;615 for (MachineInstr *I : Statepoints) {616 ++NumStatepoints;617 if (MaxStatepointsWithRegs.getNumOccurrences() &&618 NumStatepoints >= MaxStatepointsWithRegs)619 AllowGCPtrInCSR = false;620 Changed |= SPP.process(*I, AllowGCPtrInCSR);621 }622 return Changed;623}624 625bool FixupStatepointCallerSavedLegacy::runOnMachineFunction(626 MachineFunction &MF) {627 if (skipFunction(MF.getFunction()))628 return false;629 630 return FixupStatepointCallerSavedImpl().run(MF);631}632 633PreservedAnalyses634FixupStatepointCallerSavedPass::run(MachineFunction &MF,635 MachineFunctionAnalysisManager &MFAM) {636 637 if (!FixupStatepointCallerSavedImpl().run(MF))638 return PreservedAnalyses::all();639 640 auto PA = getMachineFunctionPassPreservedAnalyses();641 PA.preserveSet<CFGAnalyses>();642 return PA;643}644