//===-- FixupStatepointCallerSaved.cpp - Fixup caller saved registers ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// Statepoint instruction in deopt parameters contains values which are /// meaningful to the runtime and should be able to be read at the moment the /// call returns. So we can say that we need to encode the fact that these /// values are "late read" by runtime. If we could express this notion for /// register allocator it would produce the right form for us. /// The need to fixup (i.e this pass) is specifically handling the fact that /// we cannot describe such a late read for the register allocator. /// Register allocator may put the value on a register clobbered by the call. /// This pass forces the spill of such registers and replaces corresponding /// statepoint operands to added spill slots. /// //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/IR/Statepoint.h" #include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(NumSpilledRegisters, "Number of spilled register"); STATISTIC(NumSpillSlotsAllocated, "Number of spill slots allocated"); STATISTIC(NumSpillSlotsExtended, "Number of spill slots extended"); static cl::opt<bool> FixupSCSExtendSlotSize( "fixup-scs-extend-slot-size", cl::Hidden, cl::init(false), cl::desc("Allow spill in spill slot of greater size than register size"), cl::Hidden); static cl::opt<bool> PassGCPtrInCSR( "fixup-allow-gcptr-in-csr", cl::Hidden, cl::init(false), cl::desc("Allow passing GC Pointer arguments in callee saved registers")); static cl::opt<bool> EnableCopyProp( "fixup-scs-enable-copy-propagation", cl::Hidden, cl::init(true), cl::desc("Enable simple copy propagation during register reloading")); // This is purely debugging option. // It may be handy for investigating statepoint spilling issues. static cl::opt<unsigned> MaxStatepointsWithRegs( "fixup-max-csr-statepoints", cl::Hidden, cl::desc("Max number of statepoints allowed to pass GC Ptrs in registers")); namespace { class FixupStatepointCallerSaved : public MachineFunctionPass { … }; } // End anonymous namespace. char FixupStatepointCallerSaved::ID = …; char &llvm::FixupStatepointCallerSavedID = …; INITIALIZE_PASS_BEGIN(FixupStatepointCallerSaved, DEBUG_TYPE, "Fixup Statepoint Caller Saved", false, false) INITIALIZE_PASS_END(FixupStatepointCallerSaved, DEBUG_TYPE, "Fixup Statepoint Caller Saved", false, false) // Utility function to get size of the register. static unsigned getRegisterSize(const TargetRegisterInfo &TRI, Register Reg) { … } // Try to eliminate redundant copy to register which we're going to // spill, i.e. try to change: // X = COPY Y // SPILL X // to // SPILL Y // If there are no uses of X between copy and STATEPOINT, that COPY // may be eliminated. // Reg - register we're about to spill // RI - On entry points to statepoint. // On successful copy propagation set to new spill point. // IsKill - set to true if COPY is Kill (there are no uses of Y) // Returns either found source copy register or original one. static Register performCopyPropagation(Register Reg, MachineBasicBlock::iterator &RI, bool &IsKill, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI) { … } namespace { // Pair {Register, FrameIndex} RegSlotPair; // Keeps track of what reloads were inserted in MBB. class RegReloadCache { … }; // Cache used frame indexes during statepoint re-write to re-use them in // processing next statepoint instruction. // Two strategies. One is to preserve the size of spill slot while another one // extends the size of spill slots to reduce the number of them, causing // the less total frame size. But unspill will have "implicit" any extend. class FrameIndexesCache { … }; // Describes the state of the current processing statepoint instruction. class StatepointState { … }; class StatepointProcessor { … }; } // namespace bool FixupStatepointCallerSaved::runOnMachineFunction(MachineFunction &MF) { … }