Skip to content

Commit e4a485b

Browse files
committed
fixup! Emit safepoints at function entry and loop backedges
1 parent 5a9c6cf commit e4a485b

1 file changed

Lines changed: 115 additions & 0 deletions

File tree

src/llvm-gc-safepoint.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
#define DEBUG_TYPE "gc_safepoint"
4+
#undef DEBUG
5+
#include "llvm-version.h"
6+
7+
#include <llvm-c/Core.h>
8+
#include <llvm-c/Types.h>
9+
10+
#include <llvm/IR/Value.h>
11+
#include <llvm/IR/LegacyPassManager.h>
12+
#include <llvm/Analysis/LoopInfo.h>
13+
#include <llvm/IR/Function.h>
14+
#include <llvm/IR/Instructions.h>
15+
#include <llvm/IR/IntrinsicInst.h>
16+
#include <llvm/IR/Module.h>
17+
#include <llvm/IR/Operator.h>
18+
#include <llvm/IR/IRBuilder.h>
19+
#include <llvm/Pass.h>
20+
#include <llvm/Support/Debug.h>
21+
22+
#include "codegen_shared.h"
23+
#include "julia.h"
24+
#include "julia_internal.h"
25+
#include "julia_assert.h"
26+
#include "llvm-pass-helpers.h"
27+
28+
using namespace llvm;
29+
30+
struct GCSafepoint : public FunctionPass, private JuliaPassContext {
31+
static char ID;
32+
GCSafepoint() : FunctionPass(ID)
33+
{}
34+
35+
protected:
36+
void getAnalysisUsage(AnalysisUsage &AU) const override
37+
{
38+
AU.addRequired<LoopInfoWrapperPass>();
39+
AU.addPreserved<LoopInfoWrapperPass>();
40+
}
41+
42+
private:
43+
CallInst *pgcstack;
44+
void emitGCSafepoint(IRBuilder<> &B);
45+
Value *getCurrentSignalPage(IRBuilder<> &B);
46+
47+
bool runOnFunction(Function &F) override;
48+
};
49+
50+
Value *GCSafepoint::getCurrentSignalPage(IRBuilder<> &B)
51+
{
52+
assert(pgcstack);
53+
int nthfield = offsetof(jl_tls_states_t, safepoint) / sizeof(void *);
54+
Value *field = B.CreateInBoundsGEP(T_ppjlvalue, pgcstack, ConstantInt::get(T_size, nthfield));
55+
field = B.CreateBitCast(field, PointerType::get(PointerType::get(T_size, 0), 0));
56+
// TODO: TBAA annotation
57+
return B.CreateLoad(field);
58+
}
59+
60+
void GCSafepoint::emitGCSafepoint(IRBuilder<> &B)
61+
{
62+
B.CreateCall(getOrDeclare(jl_intrinsics::GCRootFlush));
63+
B.CreateFence(AtomicOrdering::SequentiallyConsistent, SyncScope::SingleThread);
64+
B.CreateLoad(T_size, getCurrentSignalPage(B), true);
65+
B.CreateFence(AtomicOrdering::SequentiallyConsistent, SyncScope::SingleThread);
66+
}
67+
68+
bool GCSafepoint::runOnFunction(Function &F)
69+
{
70+
LLVM_DEBUG(dbgs() << "GCSafepoint: Processing function " << F.getName() << "\n");
71+
// Check availability of functions again since they might have been deleted.
72+
initAll(*F.getParent());
73+
74+
IRBuilder<> B(F.getEntryBlock().getFirstNonPHI());
75+
76+
pgcstack = getPGCstack(F);
77+
if (!pgcstack) {
78+
LLVM_DEBUG(dbgs() << "GCSafepoint: Function " << F.getName() << " has no pgcstack, inserting one\n");
79+
pgcstack = B.CreateCall(getOrDeclare(jl_intrinsics::getPGCStack));
80+
}
81+
B.SetInsertPoint(pgcstack->getNextNode());
82+
83+
LLVM_DEBUG(dbgs() << "GCSafepoint: Inserting Safepoint at function entry of " << F.getName() << "\n");
84+
emitGCSafepoint(B);
85+
86+
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
87+
for (auto *Loop : LI.getLoopsInPreorder()) {
88+
// Iterate over backedges
89+
BasicBlock *Header = Loop->getHeader();
90+
for (const auto Edge : children<Inverse<BasicBlock *>>(Header)) {
91+
if (!Loop->contains(Edge))
92+
continue;
93+
B.SetInsertPoint(Edge->getTerminator());
94+
LLVM_DEBUG(dbgs() << "GCSafepoint: Inserting Safepoint at loop backedge: " << *Edge << "\n");
95+
emitGCSafepoint(B);
96+
}
97+
}
98+
99+
return true;
100+
}
101+
102+
char GCSafepoint::ID = 0;
103+
static RegisterPass<GCSafepoint> X("GCSafepoint", "Insert safepoints",
104+
false /* Only looks at CFG */,
105+
false /* Analysis Pass */);
106+
107+
Pass *createGCSafepointPass()
108+
{
109+
return new GCSafepoint();
110+
}
111+
112+
extern "C" JL_DLLEXPORT void LLVMExtraAddGCSafepointPass(LLVMPassManagerRef PM)
113+
{
114+
unwrap(PM)->add(createGCSafepointPass());
115+
}

0 commit comments

Comments
 (0)