Skip to content

Commit 4710009

Browse files
wsmosesKristofferC
authored andcommitted
Fix final gc lowering on dynamically sized allocation (#48620)
(cherry picked from commit 7e57dc7)
1 parent 570251e commit 4710009

File tree

4 files changed

+68
-17
lines changed

4 files changed

+68
-17
lines changed

src/llvm-final-gc-lowering.cpp

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct FinalLowerGC: private JuliaPassContext {
4949
Function *queueBindingFunc;
5050
Function *poolAllocFunc;
5151
Function *bigAllocFunc;
52+
Function *allocTypedFunc;
5253
Instruction *pgcstack;
5354

5455
// Lowers a `julia.new_gc_frame` intrinsic.
@@ -205,23 +206,35 @@ Value *FinalLowerGC::lowerGCAllocBytes(CallInst *target, Function &F)
205206
{
206207
++GCAllocBytesCount;
207208
assert(target->arg_size() == 2);
208-
auto sz = (size_t)cast<ConstantInt>(target->getArgOperand(1))->getZExtValue();
209-
// This is strongly architecture and OS dependent
210-
int osize;
211-
int offset = jl_gc_classify_pools(sz, &osize);
209+
CallInst *newI;
210+
212211
IRBuilder<> builder(target);
213212
builder.SetCurrentDebugLocation(target->getDebugLoc());
214213
auto ptls = target->getArgOperand(0);
215-
CallInst *newI;
216-
if (offset < 0) {
217-
newI = builder.CreateCall(
218-
bigAllocFunc,
219-
{ ptls, ConstantInt::get(getSizeTy(F.getContext()), sz + sizeof(void*)) });
220-
}
221-
else {
222-
auto pool_offs = ConstantInt::get(Type::getInt32Ty(F.getContext()), offset);
223-
auto pool_osize = ConstantInt::get(Type::getInt32Ty(F.getContext()), osize);
224-
newI = builder.CreateCall(poolAllocFunc, { ptls, pool_offs, pool_osize });
214+
Attribute derefAttr;
215+
216+
if (auto CI = dyn_cast<ConstantInt>(target->getArgOperand(1))) {
217+
size_t sz = (size_t)CI->getZExtValue();
218+
// This is strongly architecture and OS dependent
219+
int osize;
220+
int offset = jl_gc_classify_pools(sz, &osize);
221+
if (offset < 0) {
222+
newI = builder.CreateCall(
223+
bigAllocFunc,
224+
{ ptls, ConstantInt::get(getSizeTy(F.getContext()), sz + sizeof(void*)) });
225+
derefAttr = Attribute::getWithDereferenceableBytes(F.getContext(), sz + sizeof(void*));
226+
}
227+
else {
228+
auto pool_offs = ConstantInt::get(Type::getInt32Ty(F.getContext()), offset);
229+
auto pool_osize = ConstantInt::get(Type::getInt32Ty(F.getContext()), osize);
230+
newI = builder.CreateCall(poolAllocFunc, { ptls, pool_offs, pool_osize });
231+
derefAttr = Attribute::getWithDereferenceableBytes(F.getContext(), osize);
232+
}
233+
} else {
234+
auto size = builder.CreateZExtOrTrunc(target->getArgOperand(1), getSizeTy(F.getContext()));
235+
size = builder.CreateAdd(size, ConstantInt::get(getSizeTy(F.getContext()), sizeof(void*)));
236+
newI = builder.CreateCall(allocTypedFunc, { ptls, size, ConstantPointerNull::get(Type::getInt8PtrTy(F.getContext())) });
237+
derefAttr = Attribute::getWithDereferenceableBytes(F.getContext(), sizeof(void*));
225238
}
226239
newI->setAttributes(newI->getCalledFunction()->getAttributes());
227240
newI->takeName(target);
@@ -237,8 +250,9 @@ bool FinalLowerGC::doInitialization(Module &M) {
237250
queueBindingFunc = getOrDeclare(jl_well_known::GCQueueBinding);
238251
poolAllocFunc = getOrDeclare(jl_well_known::GCPoolAlloc);
239252
bigAllocFunc = getOrDeclare(jl_well_known::GCBigAlloc);
253+
allocTypedFunc = getOrDeclare(jl_well_known::GCAllocTyped);
240254

241-
GlobalValue *functionList[] = {queueRootFunc, queueBindingFunc, poolAllocFunc, bigAllocFunc};
255+
GlobalValue *functionList[] = {queueRootFunc, queueBindingFunc, poolAllocFunc, bigAllocFunc, allocTypedFunc};
242256
unsigned j = 0;
243257
for (unsigned i = 0; i < sizeof(functionList) / sizeof(void*); i++) {
244258
if (!functionList[i])
@@ -254,8 +268,8 @@ bool FinalLowerGC::doInitialization(Module &M) {
254268

255269
bool FinalLowerGC::doFinalization(Module &M)
256270
{
257-
GlobalValue *functionList[] = {queueRootFunc, queueBindingFunc, poolAllocFunc, bigAllocFunc};
258-
queueRootFunc = queueBindingFunc = poolAllocFunc = bigAllocFunc = nullptr;
271+
GlobalValue *functionList[] = {queueRootFunc, queueBindingFunc, poolAllocFunc, bigAllocFunc, allocTypedFunc};
272+
queueRootFunc = queueBindingFunc = poolAllocFunc = bigAllocFunc = allocTypedFunc = nullptr;
259273
auto used = M.getGlobalVariable("llvm.compiler.used");
260274
if (!used)
261275
return false;

src/llvm-pass-helpers.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ namespace jl_well_known {
231231
static const char *GC_POOL_ALLOC_NAME = XSTR(jl_gc_pool_alloc);
232232
static const char *GC_QUEUE_ROOT_NAME = XSTR(jl_gc_queue_root);
233233
static const char *GC_QUEUE_BINDING_NAME = XSTR(jl_gc_queue_binding);
234+
static const char *GC_ALLOC_TYPED_NAME = XSTR(jl_gc_alloc_typed);
234235

235236
using jl_intrinsics::addGCAllocAttributes;
236237

@@ -292,4 +293,22 @@ namespace jl_well_known {
292293
func->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly);
293294
return func;
294295
});
296+
297+
const WellKnownFunctionDescription GCAllocTyped(
298+
GC_ALLOC_TYPED_NAME,
299+
[](const JuliaPassContext &context) {
300+
auto allocTypedFunc = Function::Create(
301+
FunctionType::get(
302+
context.T_prjlvalue,
303+
{ Type::getInt8PtrTy(context.getLLVMContext()),
304+
sizeof(size_t) == sizeof(uint32_t) ?
305+
Type::getInt32Ty(context.getLLVMContext()) :
306+
Type::getInt64Ty(context.getLLVMContext()),
307+
Type::getInt8PtrTy(context.getLLVMContext()) },
308+
false),
309+
Function::ExternalLinkage,
310+
GC_ALLOC_TYPED_NAME);
311+
allocTypedFunc->addFnAttr(Attribute::getWithAllocSizeArgs(context.getLLVMContext(), 1, None));
312+
return addGCAllocAttributes(allocTypedFunc, context.getLLVMContext());
313+
});
295314
}

src/llvm-pass-helpers.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ namespace jl_well_known {
152152

153153
// `jl_gc_queue_binding`: queues a binding for GC.
154154
extern const WellKnownFunctionDescription GCQueueBinding;
155+
156+
// `jl_gc_alloc_typed`: allocates bytes.
157+
extern const WellKnownFunctionDescription GCAllocTyped;
155158
}
156159

157160
#endif

test/llvmpasses/final-lower-gc.ll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ top:
6767
ret {} addrspace(10)* %v
6868
}
6969

70+
define {} addrspace(10)* @gc_alloc_lowering_var(i64 %size) {
71+
top:
72+
; CHECK-LABEL: @gc_alloc_lowering_var
73+
%pgcstack = call {}*** @julia.get_pgcstack()
74+
%ptls = call {}*** @julia.ptls_states()
75+
%ptls_i8 = bitcast {}*** %ptls to i8*
76+
; CHECK: %0 = add i64 %size, 8
77+
; CHECK: %v = call noalias nonnull {} addrspace(10)* @ijl_gc_alloc_typed(i8* %ptls_i8, i64 %0, i8* null)
78+
%v = call {} addrspace(10)* @julia.gc_alloc_bytes(i8* %ptls_i8, i64 %size)
79+
%0 = bitcast {} addrspace(10)* %v to {} addrspace(10)* addrspace(10)*
80+
%1 = getelementptr {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %0, i64 -1
81+
store {} addrspace(10)* @tag, {} addrspace(10)* addrspace(10)* %1, align 8, !tbaa !0
82+
ret {} addrspace(10)* %v
83+
}
84+
7085
!0 = !{!1, !1, i64 0}
7186
!1 = !{!"jtbaa_gcframe", !2, i64 0}
7287
!2 = !{!"jtbaa"}

0 commit comments

Comments
 (0)