LLVM 18.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
30namespace {
31
32/// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or
33/// llvm.gcwrite intrinsics, replacing them with simple loads and stores as
34/// directed by the GCStrategy. It also performs automatic root initialization
35/// and custom intrinsic lowering.
36class LowerIntrinsics : public FunctionPass {
37 bool DoLowering(Function &F, GCStrategy &S);
38
39public:
40 static char ID;
41
42 LowerIntrinsics();
43 StringRef getPassName() const override;
44 void getAnalysisUsage(AnalysisUsage &AU) const override;
45
46 bool doInitialization(Module &M) override;
47 bool runOnFunction(Function &F) override;
48};
49
50/// GCMachineCodeAnalysis - This is a target-independent pass over the machine
51/// function representation to identify safe points for the garbage collector
52/// in the machine code. It inserts labels at safe points and populates a
53/// GCMetadata record for each function.
54class GCMachineCodeAnalysis : public MachineFunctionPass {
55 GCFunctionInfo *FI = nullptr;
56 const TargetInstrInfo *TII = nullptr;
57
58 void FindSafePoints(MachineFunction &MF);
59 void VisitCallPoint(MachineBasicBlock::iterator CI);
61 const DebugLoc &DL) const;
62
63 void FindStackOffsets(MachineFunction &MF);
64
65public:
66 static char ID;
67
68 GCMachineCodeAnalysis();
69 void getAnalysisUsage(AnalysisUsage &AU) const override;
70
71 bool runOnMachineFunction(MachineFunction &MF) override;
72};
73}
74
75// -----------------------------------------------------------------------------
76
77INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", false,
78 false)
80INITIALIZE_PASS_END(LowerIntrinsics, "gc-lowering", "GC Lowering", false, false)
81
82FunctionPass *llvm::createGCLoweringPass() { return new LowerIntrinsics(); }
83
84char LowerIntrinsics::ID = 0;
85char &llvm::GCLoweringID = LowerIntrinsics::ID;
86
87LowerIntrinsics::LowerIntrinsics() : FunctionPass(ID) {
89}
90
91StringRef LowerIntrinsics::getPassName() const {
92 return "Lower Garbage Collection Instructions";
93}
94
95void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const {
96 FunctionPass::getAnalysisUsage(AU);
99}
100
101/// doInitialization - If this module uses the GC intrinsics, find them now.
102bool LowerIntrinsics::doInitialization(Module &M) {
103 GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
104 assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?");
105 for (Function &F : M)
106 if (!F.isDeclaration() && F.hasGC())
107 MI->getFunctionInfo(F); // Instantiate the GC strategy.
108
109 return false;
110}
111
112/// CouldBecomeSafePoint - Predicate to conservatively determine whether the
113/// instruction could introduce a safe point.
115 // The natural definition of instructions which could introduce safe points
116 // are:
117 //
118 // - call, invoke (AfterCall, BeforeCall)
119 // - phis (Loops)
120 // - invoke, ret, unwind (Exit)
121 //
122 // However, instructions as seemingly inoccuous as arithmetic can become
123 // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead
124 // it is necessary to take a conservative approach.
125
126 if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) || isa<StoreInst>(I) ||
127 isa<LoadInst>(I))
128 return false;
129
130 // llvm.gcroot is safe because it doesn't do anything at runtime.
131 if (CallInst *CI = dyn_cast<CallInst>(I))
132 if (Function *F = CI->getCalledFunction())
133 if (Intrinsic::ID IID = F->getIntrinsicID())
134 if (IID == Intrinsic::gcroot)
135 return false;
136
137 return true;
138}
139
141 // Scroll past alloca instructions.
142 BasicBlock::iterator IP = F.getEntryBlock().begin();
143 while (isa<AllocaInst>(IP))
144 ++IP;
145
146 // Search for initializers in the initial BB.
148 for (; !CouldBecomeSafePoint(&*IP); ++IP)
149 if (StoreInst *SI = dyn_cast<StoreInst>(IP))
150 if (AllocaInst *AI =
151 dyn_cast<AllocaInst>(SI->getOperand(1)->stripPointerCasts()))
152 InitedRoots.insert(AI);
153
154 // Add root initializers.
155 bool MadeChange = false;
156
157 for (AllocaInst *Root : Roots)
158 if (!InitedRoots.count(Root)) {
159 new StoreInst(
160 ConstantPointerNull::get(cast<PointerType>(Root->getAllocatedType())),
161 Root, Root->getNextNode());
162 MadeChange = true;
163 }
164
165 return MadeChange;
166}
167
168/// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores.
169/// Leave gcroot intrinsics; the code generator needs to see those.
170bool LowerIntrinsics::runOnFunction(Function &F) {
171 // Quick exit for functions that do not use GC.
172 if (!F.hasGC())
173 return false;
174
175 GCFunctionInfo &FI = getAnalysis<GCModuleInfo>().getFunctionInfo(F);
176 GCStrategy &S = FI.getStrategy();
177
178 return DoLowering(F, S);
179}
180
181/// Lower barriers out of existance (if the associated GCStrategy hasn't
182/// already done so...), and insert initializing stores to roots as a defensive
183/// measure. Given we're going to report all roots live at all safepoints, we
184/// need to be able to ensure each root has been initialized by the point the
185/// first safepoint is reached. This really should have been done by the
186/// frontend, but the old API made this non-obvious, so we do a potentially
187/// redundant store just in case.
188bool LowerIntrinsics::DoLowering(Function &F, GCStrategy &S) {
190
191 bool MadeChange = false;
192 for (BasicBlock &BB : F)
194 IntrinsicInst *CI = dyn_cast<IntrinsicInst>(&I);
195 if (!CI)
196 continue;
197
199 switch (F->getIntrinsicID()) {
200 default: break;
201 case Intrinsic::gcwrite: {
202 // Replace a write barrier with a simple store.
203 Value *St = new StoreInst(CI->getArgOperand(0),
204 CI->getArgOperand(2), CI);
205 CI->replaceAllUsesWith(St);
206 CI->eraseFromParent();
207 MadeChange = true;
208 break;
209 }
210 case Intrinsic::gcread: {
211 // Replace a read barrier with a simple load.
212 Value *Ld = new LoadInst(CI->getType(), CI->getArgOperand(1), "", CI);
213 Ld->takeName(CI);
214 CI->replaceAllUsesWith(Ld);
215 CI->eraseFromParent();
216 MadeChange = true;
217 break;
218 }
219 case Intrinsic::gcroot: {
220 // Initialize the GC root, but do not delete the intrinsic. The
221 // backend needs the intrinsic to flag the stack slot.
222 Roots.push_back(
223 cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts()));
224 break;
225 }
226 }
227 }
228
229 if (Roots.size())
230 MadeChange |= InsertRootInitializers(F, Roots);
231
232 return MadeChange;
233}
234
235// -----------------------------------------------------------------------------
236
237char GCMachineCodeAnalysis::ID = 0;
238char &llvm::GCMachineCodeAnalysisID = GCMachineCodeAnalysis::ID;
239
240INITIALIZE_PASS(GCMachineCodeAnalysis, "gc-analysis",
241 "Analyze Machine Code For Garbage Collection", false, false)
242
243GCMachineCodeAnalysis::GCMachineCodeAnalysis() : MachineFunctionPass(ID) {}
244
245void GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
247 AU.setPreservesAll();
249}
250
251MCSymbol *GCMachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB,
253 const DebugLoc &DL) const {
255 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
256 return Label;
257}
258
259void GCMachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) {
260 // Find the return address (next instruction), since that's what will be on
261 // the stack when the call is suspended and we need to inspect the stack.
263 ++RAI;
264
265 MCSymbol *Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc());
266 FI->addSafePoint(Label, CI->getDebugLoc());
267}
268
269void GCMachineCodeAnalysis::FindSafePoints(MachineFunction &MF) {
270 for (MachineBasicBlock &MBB : MF)
271 for (MachineInstr &MI : MBB)
272 if (MI.isCall()) {
273 // Do not treat tail or sibling call sites as safe points. This is
274 // legal since any arguments passed to the callee which live in the
275 // remnants of the callers frame will be owned and updated by the
276 // callee if required.
277 if (MI.isTerminator())
278 continue;
279 VisitCallPoint(&MI);
280 }
281}
282
283void GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
285 assert(TFI && "TargetRegisterInfo not available!");
286
288 RI != FI->roots_end();) {
289 // If the root references a dead object, no need to keep it.
290 if (MF.getFrameInfo().isDeadObjectIndex(RI->Num)) {
291 RI = FI->removeStackRoot(RI);
292 } else {
293 Register FrameReg; // FIXME: surely GCRoot ought to store the
294 // register that the offset is from?
295 auto FrameOffset = TFI->getFrameIndexReference(MF, RI->Num, FrameReg);
296 assert(!FrameOffset.getScalable() &&
297 "Frame offsets with a scalable component are not supported");
298 RI->StackOffset = FrameOffset.getFixed();
299 ++RI;
300 }
301 }
302}
303
304bool GCMachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) {
305 // Quick exit for functions that do not use GC.
306 if (!MF.getFunction().hasGC())
307 return false;
308
309 FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(MF.getFunction());
311
312 // Find the size of the stack frame. There may be no correct static frame
313 // size, we use UINT64_MAX to represent this.
314 const MachineFrameInfo &MFI = MF.getFrameInfo();
316 const bool DynamicFrameSize =
317 MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF);
318 FI->setFrameSize(DynamicFrameSize ? UINT64_MAX : MFI.getStackSize());
319
320 // Find all safe points.
321 if (FI->getStrategy().needsSafePoints())
322 FindSafePoints(MF);
323
324 // Find the concrete stack offsets for all roots (stack slots)
325 FindStackOffsets(MF);
326
327 return false;
328}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool InsertRootInitializers(Function &F, ArrayRef< AllocaInst * > Roots)
static bool CouldBecomeSafePoint(Instruction *I)
CouldBecomeSafePoint - Predicate to conservatively determine whether the instruction could introduce ...
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.
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#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
pre isel intrinsic Pre ISel Intrinsic Lowering
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
an instruction to allocate memory on the stack
Definition: Instructions.h:58
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:56
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:87
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Definition: InstrTypes.h:1412
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1357
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:1691
A debug info location.
Definition: DebugLoc.h:33
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:314
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
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:307
Garbage collection metadata for a single function.
Definition: GCMetadata.h:77
void setFrameSize(uint64_t S)
Definition: GCMetadata.h:131
void addSafePoint(MCSymbol *Label, const DebugLoc &DL)
addSafePoint - Notes the existence of a safe point.
Definition: GCMetadata.h:125
std::vector< GCRoot >::iterator roots_iterator
Definition: GCMetadata.h:80
roots_iterator removeStackRoot(roots_iterator position)
removeStackRoot - Removes a root.
Definition: GCMetadata.h:118
GCStrategy & getStrategy()
getStrategy - Return the GC strategy for the function.
Definition: GCMetadata.h:108
roots_iterator roots_end()
Definition: GCMetadata.h:140
roots_iterator roots_begin()
roots_begin/roots_end - Iterators for all roots in the function.
Definition: GCMetadata.h:139
An analysis pass which caches information about the entire Module.
Definition: GCMetadata.h:152
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
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:83
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:47
An instruction for reading from memory.
Definition: Instructions.h:177
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:322
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:68
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
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:384
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:366
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:451
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
An instruction for storing to memory.
Definition: Instructions.h:301
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:535
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:688
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:384
#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:666
void initializeLowerIntrinsicsPass(PassRegistry &)