LLVM 20.0.0git
GCRootLowering.cpp
Go to the documentation of this file.
1//===-- GCRootLowering.cpp - Garbage collection infrastructure ------------===//
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//
9// This file implements the lowering for the gc.root mechanism.
10//
11//===----------------------------------------------------------------------===//
12
17#include "llvm/CodeGen/Passes.h"
22#include "llvm/IR/Dominators.h"
24#include "llvm/IR/Module.h"
26#include "llvm/MC/MCContext.h"
27
28using namespace llvm;
29
30/// Lower barriers out of existence (if the associated GCStrategy hasn't
31/// already done so...), and insert initializing stores to roots as a defensive
32/// measure. Given we're going to report all roots live at all safepoints, we
33/// need to be able to ensure each root has been initialized by the point the
34/// first safepoint is reached. This really should have been done by the
35/// frontend, but the old API made this non-obvious, so we do a potentially
36/// redundant store just in case.
37static bool DoLowering(Function &F, GCStrategy &S);
38
39namespace {
40
41/// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or
42/// llvm.gcwrite intrinsics, replacing them with simple loads and stores as
43/// directed by the GCStrategy. It also performs automatic root initialization
44/// and custom intrinsic lowering.
45class LowerIntrinsics : public FunctionPass {
46public:
47 static char ID;
48
49 LowerIntrinsics();
50 StringRef getPassName() const override;
51 void getAnalysisUsage(AnalysisUsage &AU) const override;
52
53 bool doInitialization(Module &M) override;
54 bool runOnFunction(Function &F) override;
55};
56
57/// GCMachineCodeAnalysis - This is a target-independent pass over the machine
58/// function representation to identify safe points for the garbage collector
59/// in the machine code. It inserts labels at safe points and populates a
60/// GCMetadata record for each function.
61class GCMachineCodeAnalysis : public MachineFunctionPass {
62 GCFunctionInfo *FI = nullptr;
63 const TargetInstrInfo *TII = nullptr;
64
65 void FindSafePoints(MachineFunction &MF);
66 void VisitCallPoint(MachineBasicBlock::iterator CI);
68 const DebugLoc &DL) const;
69
70 void FindStackOffsets(MachineFunction &MF);
71
72public:
73 static char ID;
74
75 GCMachineCodeAnalysis();
76 void getAnalysisUsage(AnalysisUsage &AU) const override;
77
78 bool runOnMachineFunction(MachineFunction &MF) override;
79};
80}
81
84 if (!F.hasGC())
86
88
89 bool Changed = DoLowering(F, Info.getStrategy());
90
91 if (!Changed)
95 return PA;
96}
97
98// -----------------------------------------------------------------------------
99
100INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", false,
101 false)
103INITIALIZE_PASS_END(LowerIntrinsics, "gc-lowering", "GC Lowering", false, false)
104
105FunctionPass *llvm::createGCLoweringPass() { return new LowerIntrinsics(); }
106
107char LowerIntrinsics::ID = 0;
108char &llvm::GCLoweringID = LowerIntrinsics::ID;
109
110LowerIntrinsics::LowerIntrinsics() : FunctionPass(ID) {
112}
113
114StringRef LowerIntrinsics::getPassName() const {
115 return "Lower Garbage Collection Instructions";
116}
117
118void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const {
119 FunctionPass::getAnalysisUsage(AU);
122}
123
124/// doInitialization - If this module uses the GC intrinsics, find them now.
125bool LowerIntrinsics::doInitialization(Module &M) {
126 GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
127 assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?");
128 for (Function &F : M)
129 if (!F.isDeclaration() && F.hasGC())
130 MI->getFunctionInfo(F); // Instantiate the GC strategy.
131
132 return false;
133}
134
135/// CouldBecomeSafePoint - Predicate to conservatively determine whether the
136/// instruction could introduce a safe point.
138 // The natural definition of instructions which could introduce safe points
139 // are:
140 //
141 // - call, invoke (AfterCall, BeforeCall)
142 // - phis (Loops)
143 // - invoke, ret, unwind (Exit)
144 //
145 // However, instructions as seemingly inoccuous as arithmetic can become
146 // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead
147 // it is necessary to take a conservative approach.
148
149 if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) || isa<StoreInst>(I) ||
150 isa<LoadInst>(I))
151 return false;
152
153 // llvm.gcroot is safe because it doesn't do anything at runtime.
154 if (CallInst *CI = dyn_cast<CallInst>(I))
155 if (Function *F = CI->getCalledFunction())
156 if (Intrinsic::ID IID = F->getIntrinsicID())
157 if (IID == Intrinsic::gcroot)
158 return false;
159
160 return true;
161}
162
164 // Scroll past alloca instructions.
165 BasicBlock::iterator IP = F.getEntryBlock().begin();
166 while (isa<AllocaInst>(IP))
167 ++IP;
168
169 // Search for initializers in the initial BB.
171 for (; !CouldBecomeSafePoint(&*IP); ++IP)
172 if (StoreInst *SI = dyn_cast<StoreInst>(IP))
173 if (AllocaInst *AI =
174 dyn_cast<AllocaInst>(SI->getOperand(1)->stripPointerCasts()))
175 InitedRoots.insert(AI);
176
177 // Add root initializers.
178 bool MadeChange = false;
179
180 for (AllocaInst *Root : Roots)
181 if (!InitedRoots.count(Root)) {
182 new StoreInst(
183 ConstantPointerNull::get(cast<PointerType>(Root->getAllocatedType())),
184 Root, std::next(Root->getIterator()));
185 MadeChange = true;
186 }
187
188 return MadeChange;
189}
190
191/// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores.
192/// Leave gcroot intrinsics; the code generator needs to see those.
193bool LowerIntrinsics::runOnFunction(Function &F) {
194 // Quick exit for functions that do not use GC.
195 if (!F.hasGC())
196 return false;
197
198 GCFunctionInfo &FI = getAnalysis<GCModuleInfo>().getFunctionInfo(F);
199 GCStrategy &S = FI.getStrategy();
200
201 return DoLowering(F, S);
202}
203
206
207 bool MadeChange = false;
208 for (BasicBlock &BB : F)
210 IntrinsicInst *CI = dyn_cast<IntrinsicInst>(&I);
211 if (!CI)
212 continue;
213
215 switch (F->getIntrinsicID()) {
216 default: break;
217 case Intrinsic::gcwrite: {
218 // Replace a write barrier with a simple store.
219 Value *St = new StoreInst(CI->getArgOperand(0), CI->getArgOperand(2),
220 CI->getIterator());
221 CI->replaceAllUsesWith(St);
222 CI->eraseFromParent();
223 MadeChange = true;
224 break;
225 }
226 case Intrinsic::gcread: {
227 // Replace a read barrier with a simple load.
228 Value *Ld = new LoadInst(CI->getType(), CI->getArgOperand(1), "",
229 CI->getIterator());
230 Ld->takeName(CI);
231 CI->replaceAllUsesWith(Ld);
232 CI->eraseFromParent();
233 MadeChange = true;
234 break;
235 }
236 case Intrinsic::gcroot: {
237 // Initialize the GC root, but do not delete the intrinsic. The
238 // backend needs the intrinsic to flag the stack slot.
239 Roots.push_back(
240 cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts()));
241 break;
242 }
243 }
244 }
245
246 if (Roots.size())
247 MadeChange |= InsertRootInitializers(F, Roots);
248
249 return MadeChange;
250}
251
252// -----------------------------------------------------------------------------
253
254char GCMachineCodeAnalysis::ID = 0;
255char &llvm::GCMachineCodeAnalysisID = GCMachineCodeAnalysis::ID;
256
257INITIALIZE_PASS(GCMachineCodeAnalysis, "gc-analysis",
258 "Analyze Machine Code For Garbage Collection", false, false)
259
260GCMachineCodeAnalysis::GCMachineCodeAnalysis() : MachineFunctionPass(ID) {}
261
262void GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
264 AU.setPreservesAll();
266}
267
268MCSymbol *GCMachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB,
270 const DebugLoc &DL) const {
272 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
273 return Label;
274}
275
276void GCMachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) {
277 // Find the return address (next instruction), since that's what will be on
278 // the stack when the call is suspended and we need to inspect the stack.
280 ++RAI;
281
282 MCSymbol *Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc());
283 FI->addSafePoint(Label, CI->getDebugLoc());
284}
285
286void GCMachineCodeAnalysis::FindSafePoints(MachineFunction &MF) {
287 for (MachineBasicBlock &MBB : MF)
288 for (MachineInstr &MI : MBB)
289 if (MI.isCall()) {
290 // Do not treat tail or sibling call sites as safe points. This is
291 // legal since any arguments passed to the callee which live in the
292 // remnants of the callers frame will be owned and updated by the
293 // callee if required.
294 if (MI.isTerminator())
295 continue;
296 VisitCallPoint(&MI);
297 }
298}
299
300void GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
302 assert(TFI && "TargetRegisterInfo not available!");
303
305 RI != FI->roots_end();) {
306 // If the root references a dead object, no need to keep it.
307 if (MF.getFrameInfo().isDeadObjectIndex(RI->Num)) {
308 RI = FI->removeStackRoot(RI);
309 } else {
310 Register FrameReg; // FIXME: surely GCRoot ought to store the
311 // register that the offset is from?
312 auto FrameOffset = TFI->getFrameIndexReference(MF, RI->Num, FrameReg);
313 assert(!FrameOffset.getScalable() &&
314 "Frame offsets with a scalable component are not supported");
315 RI->StackOffset = FrameOffset.getFixed();
316 ++RI;
317 }
318 }
319}
320
321bool GCMachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) {
322 // Quick exit for functions that do not use GC.
323 if (!MF.getFunction().hasGC())
324 return false;
325
326 FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(MF.getFunction());
328
329 // Find the size of the stack frame. There may be no correct static frame
330 // size, we use UINT64_MAX to represent this.
331 const MachineFrameInfo &MFI = MF.getFrameInfo();
333 const bool DynamicFrameSize =
334 MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF);
335 FI->setFrameSize(DynamicFrameSize ? UINT64_MAX : MFI.getStackSize());
336
337 // Find all safe points.
338 if (FI->getStrategy().needsSafePoints())
339 FindSafePoints(MF);
340
341 // Find the concrete stack offsets for all roots (stack slots)
342 FindStackOffsets(MF);
343
344 return false;
345}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
static bool InsertRootInitializers(Function &F, ArrayRef< AllocaInst * > Roots)
static bool CouldBecomeSafePoint(Instruction *I)
CouldBecomeSafePoint - Predicate to conservatively determine whether the instruction could introduce ...
static bool DoLowering(Function &F, GCStrategy &S)
Lower barriers out of existence (if the associated GCStrategy hasn't already done so....
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:57
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
pre isel intrinsic lowering
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
an instruction to allocate memory on the stack
Definition: Instructions.h:61
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:405
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:177
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Definition: InstrTypes.h:1465
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1410
This class represents a function call, abstracting a target machine's calling convention.
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1800
A debug info location.
Definition: DebugLoc.h:33
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:279
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:317
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
bool hasGC() const
hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm to use during code generatio...
Definition: Function.h:349
An analysis pass which caches information about the Function.
Definition: GCMetadata.h:180
Garbage collection metadata for a single function.
Definition: GCMetadata.h:78
void setFrameSize(uint64_t S)
Definition: GCMetadata.h:136
void addSafePoint(MCSymbol *Label, const DebugLoc &DL)
addSafePoint - Notes the existence of a safe point.
Definition: GCMetadata.h:130
std::vector< GCRoot >::iterator roots_iterator
Definition: GCMetadata.h:81
roots_iterator removeStackRoot(roots_iterator position)
removeStackRoot - Removes a root.
Definition: GCMetadata.h:123
GCStrategy & getStrategy()
getStrategy - Return the GC strategy for the function.
Definition: GCMetadata.h:113
roots_iterator roots_end()
Definition: GCMetadata.h:145
roots_iterator roots_begin()
roots_begin/roots_end - Iterators for all roots in the function.
Definition: GCMetadata.h:144
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
An analysis pass which caches information about the entire Module.
Definition: GCMetadata.h:203
GCStrategy describes a garbage collector algorithm's code generation requirements,...
Definition: GCStrategy.h:63
bool needsSafePoints() const
True if safe points need to be inferred on call sites.
Definition: GCStrategy.h:127
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:92
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:48
An instruction for reading from memory.
Definition: Instructions.h:174
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:346
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
Definition: Pass.h:119
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
void preserve()
Mark an analysis as preserved.
Definition: Analysis.h:131
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:435
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:367
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:502
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
An instruction for storing to memory.
Definition: Instructions.h:290
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Information about stack frame layout on the target.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:694
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:383
self_iterator getIterator()
Definition: ilist_node.h:132
#define UINT64_MAX
Definition: DataTypes.h:77
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
char & GCMachineCodeAnalysisID
GCMachineCodeAnalysis - Target-independent pass to mark safe points in machine code.
FunctionPass * createGCLoweringPass()
GCLowering Pass - Used by gc.root to perform its default lowering operations.
char & GCLoweringID
GCLowering Pass - Used by gc.root to perform its default lowering operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:656
void initializeLowerIntrinsicsPass(PassRegistry &)