Skip to content

Commit

Permalink
Optimize PLT and jl_load_and_lookup calls (#50745)
Browse files Browse the repository at this point in the history
  • Loading branch information
pchintalapudi authored Aug 3, 2023
1 parent 881e08b commit c03a346
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 60 deletions.
3 changes: 3 additions & 0 deletions src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,9 @@ void jl_get_llvmf_defn_impl(jl_llvmf_dump_t* dump, jl_method_instance_t *mi, siz
global.second->setVisibility(GlobalValue::DefaultVisibility);
}
}
if (!jl_options.image_codegen) {
optimizeDLSyms(*m.getModuleUnlocked());
}
assert(!verifyLLVMIR(*m.getModuleUnlocked()));
if (optimize) {
#ifndef JL_USE_NEW_PM
Expand Down
66 changes: 14 additions & 52 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ static Value *runtime_sym_lookup(
// f_lib is actually one of the special sentinel values
libname = ConstantExpr::getIntToPtr(ConstantInt::get(emission_context.DL.getIntPtrType(irbuilder.getContext()), (uintptr_t)f_lib), getInt8PtrTy(irbuilder.getContext()));
}
llvmf = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jldlsym_func),
auto lookup = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jldlsym_func),
{ libname, nameval, libptrgv });
llvmf = lookup;
}
setName(emission_context, llvmf, f_name + StringRef(".found"));
StoreInst *store = irbuilder.CreateAlignedStore(llvmf, llvmgv, Align(sizeof(void*)));
Expand All @@ -187,17 +188,6 @@ static Value *runtime_sym_lookup(
return irbuilder.CreateBitCast(p, funcptype);
}

static Value *runtime_sym_lookup(
jl_codectx_t &ctx,
PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
const char *f_name, Function *f,
GlobalVariable *libptrgv,
GlobalVariable *llvmgv, bool runtime_lib)
{
return runtime_sym_lookup(ctx.emission_context, ctx.builder, &ctx, funcptype, f_lib, lib_expr,
f_name, f, libptrgv, llvmgv, runtime_lib);
}

static Value *runtime_sym_lookup(
jl_codectx_t &ctx,
PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
Expand Down Expand Up @@ -225,7 +215,7 @@ static Value *runtime_sym_lookup(
libptrgv = prepare_global_in(jl_Module, libptrgv);
}
llvmgv = prepare_global_in(jl_Module, llvmgv);
return runtime_sym_lookup(ctx, funcptype, f_lib, lib_expr, f_name, f, libptrgv, llvmgv, runtime_lib);
return runtime_sym_lookup(ctx.emission_context, ctx.builder, &ctx, funcptype, f_lib, lib_expr, f_name, f, libptrgv, llvmgv, runtime_lib);
}

// Emit a "PLT" entry that will be lazily initialized
Expand All @@ -250,21 +240,26 @@ static GlobalVariable *emit_plt_thunk(
plt->setAttributes(attrs);
if (cc != CallingConv::C)
plt->setCallingConv(cc);
fname += "_got";
auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(M->getContext());
GlobalVariable *got = new GlobalVariable(*M, T_pvoidfunc, false,
GlobalVariable::ExternalLinkage,
ConstantExpr::getBitCast(plt, T_pvoidfunc),
fname);
fname + "_got");
if (runtime_lib) {
got->addAttribute("julia.libname", f_lib);
} else {
got->addAttribute("julia.libidx", std::to_string((uintptr_t) f_lib));
}
got->addAttribute("julia.fname", f_name);
BasicBlock *b0 = BasicBlock::Create(M->getContext(), "top", plt);
IRBuilder<> irbuilder(b0);
Value *ptr = runtime_sym_lookup(ctx.emission_context, irbuilder, NULL, funcptype, f_lib, NULL, f_name, plt, libptrgv,
llvmgv, runtime_lib);
StoreInst *store = irbuilder.CreateAlignedStore(irbuilder.CreateBitCast(ptr, T_pvoidfunc), got, Align(sizeof(void*)));
store->setAtomic(AtomicOrdering::Release);
SmallVector<Value*, 16> args;
for (Function::arg_iterator arg = plt->arg_begin(), arg_e = plt->arg_end(); arg != arg_e; ++arg)
args.push_back(&*arg);
for (auto &arg : plt->args())
args.push_back(&arg);
assert(cast<PointerType>(ptr->getType())->isOpaqueOrPointeeTypeMatches(functype));
CallInst *ret = irbuilder.CreateCall(
functype,
Expand Down Expand Up @@ -307,7 +302,6 @@ static Value *emit_plt(
CallingConv::ID cc, const char *f_lib, const char *f_name)
{
++PLT;
assert(ctx.emission_context.imaging);
// Don't do this for vararg functions so that the `musttail` is only
// an optimization and is not required to function correctly.
assert(!functype->isVarArg());
Expand Down Expand Up @@ -724,26 +718,10 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
if (sym.lib_expr) {
res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), NULL, sym.lib_expr, sym.f_name, ctx.f);
}
else if (ctx.emission_context.imaging) {
else /*if (ctx.emission_context.imaging) */{
res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
res = ctx.builder.CreatePtrToInt(res, lrt);
}
else {
void *symaddr;

void* libsym = jl_get_library_(sym.f_lib, 0);
int symbol_found = jl_dlsym(libsym, sym.f_name, &symaddr, 0);
if (!libsym || !symbol_found) {
// Error mode, either the library or the symbol couldn't be find during compiletime.
// Fallback to a runtime symbol lookup.
res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
res = ctx.builder.CreatePtrToInt(res, lrt);
} else {
// since we aren't saving this code, there's no sense in
// putting anything complicated here: just JIT the address of the cglobal
res = ConstantInt::get(lrt, (uint64_t)symaddr);
}
}
}

JL_GC_POP();
Expand Down Expand Up @@ -2106,7 +2084,7 @@ jl_cgval_t function_sig_t::emit_a_ccall(
++DeferredCCallLookups;
llvmf = runtime_sym_lookup(ctx, funcptype, NULL, symarg.lib_expr, symarg.f_name, ctx.f);
}
else if (ctx.emission_context.imaging) {
else /*if (ctx.emission_context.imaging) */{
++DeferredCCallLookups;
// vararg requires musttail,
// but musttail is incompatible with noreturn.
Expand All @@ -2115,22 +2093,6 @@ jl_cgval_t function_sig_t::emit_a_ccall(
else
llvmf = emit_plt(ctx, functype, attributes, cc, symarg.f_lib, symarg.f_name);
}
else {
void *symaddr;
void *libsym = jl_get_library_(symarg.f_lib, 0);
int symbol_found = jl_dlsym(libsym, symarg.f_name, &symaddr, 0);
if (!libsym || !symbol_found) {
++DeferredCCallLookups;
// either the library or the symbol could not be found, place a runtime
// lookup here instead.
llvmf = runtime_sym_lookup(ctx, funcptype, symarg.f_lib, NULL, symarg.f_name, ctx.f);
} else {
++LiteralCCalls;
// since we aren't saving this code, there's no sense in
// putting anything complicated here: just JIT the function address
llvmf = literal_static_pointer_val(symaddr, funcptype);
}
}
}

OperandBundleDef OpBundle("jl_roots", gc_uses);
Expand Down
2 changes: 2 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2368,6 +2368,8 @@ std::unique_ptr<Module> jl_create_llvm_module(StringRef name, LLVMContext &conte
if (!m->getModuleFlag("Debug Info Version"))
m->addModuleFlag(llvm::Module::Warning, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION);
if (imaging_mode)
m->addModuleFlag(llvm::Module::Error, "julia.imaging_mode", 1);
m->setDataLayout(DL);
m->setTargetTriple(triple.str());

Expand Down
Loading

0 comments on commit c03a346

Please sign in to comment.