Skip to content

Commit

Permalink
Clean up duplicated calls to the same target in LLVM output
Browse files Browse the repository at this point in the history
Currently, every not-previously-emitted reference to a julia function
gets a unique new name when we generate LLVM ir and we resolve all
those names later when we actually emit the referenced function.
This causes confusion in LLVM IR output (e.g. in #44998, where
we had tens of thousands of unique names for the exact same
function). It doesn't so much matter for the JIT, since the
references get merged before the JIT runs, but for output to
IR, this change will make the result much nicer.
  • Loading branch information
Keno committed Apr 25, 2022
1 parent 68adc00 commit 88c330a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 6 deletions.
18 changes: 14 additions & 4 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,7 @@ class jl_codectx_t {
public:
IRBuilder<> builder;
jl_codegen_params_t &emission_context;
jl_codegen_call_targets_t &call_targets;
llvm::MapVector<jl_code_instance_t*, jl_codegen_call_target_t> call_targets;
std::map<void*, GlobalVariable*> &global_targets;
Function *f = NULL;
// local var info. globals are not in here.
Expand Down Expand Up @@ -1366,7 +1366,7 @@ class jl_codectx_t {
jl_codectx_t(LLVMContext &llvmctx, jl_codegen_params_t &params)
: builder(llvmctx),
emission_context(params),
call_targets(params.workqueue),
call_targets(),
global_targets(params.globals),
world(params.world),
use_cache(params.cache),
Expand All @@ -1384,6 +1384,9 @@ class jl_codectx_t {

~jl_codectx_t() {
assert(this->roots == NULL);
// Transfer local delayed calls to the global queue
for (auto call_target : call_targets)
emission_context.workqueue.push_back(call_target);
}
};

Expand Down Expand Up @@ -3911,6 +3914,11 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const
}
}
}
auto it = ctx.call_targets.find(codeinst);
if (need_to_emit && it != ctx.call_targets.end()) {
protoname = std::get<2>(it->second)->getName();
need_to_emit = false;
}
if (need_to_emit) {
raw_string_ostream(name) << (specsig ? "j_" : "j1_") << name_from_method_instance(mi) << "_" << globalUniqueGeneratedNames++;
protoname = StringRef(name);
Expand All @@ -3924,7 +3932,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const
handled = true;
if (need_to_emit) {
Function *trampoline_decl = cast<Function>(jl_Module->getNamedValue(protoname));
ctx.call_targets.push_back(std::make_tuple(codeinst, cc, return_roots, trampoline_decl, specsig));
ctx.call_targets[codeinst] = std::make_tuple(cc, return_roots, trampoline_decl, specsig);
}
}
}
Expand Down Expand Up @@ -8097,7 +8105,9 @@ void jl_compile_workqueue(
jl_returninfo_t::CallingConv proto_cc;
bool proto_specsig;
unsigned proto_return_roots;
std::tie(codeinst, proto_cc, proto_return_roots, protodecl, proto_specsig) = params.workqueue.back();
auto it = params.workqueue.back();
codeinst = it.first;
std::tie(proto_cc, proto_return_roots, protodecl, proto_specsig) = it.second;
params.workqueue.pop_back();
// try to emit code for this item from the workqueue
assert(codeinst->min_world <= params.world && codeinst->max_world >= params.world &&
Expand Down
6 changes: 4 additions & 2 deletions src/jitlayers.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// This file is a part of Julia. License is MIT: https://julialang.org/license

#include <llvm/ADT/MapVector.h>

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/Module.h>
Expand Down Expand Up @@ -114,14 +116,14 @@ struct jl_llvmf_dump_t {
Function *F;
};

typedef std::vector<std::tuple<jl_code_instance_t*, jl_returninfo_t::CallingConv, unsigned, llvm::Function*, bool>> jl_codegen_call_targets_t;
typedef std::tuple<jl_returninfo_t::CallingConv, unsigned, llvm::Function*, bool> jl_codegen_call_target_t;

typedef struct _jl_codegen_params_t {
orc::ThreadSafeContext tsctx;
orc::ThreadSafeContext::Lock tsctx_lock;
typedef StringMap<GlobalVariable*> SymMapGV;
// outputs
jl_codegen_call_targets_t workqueue;
std::vector<std::pair<jl_code_instance_t*, jl_codegen_call_target_t>> workqueue;
std::map<void*, GlobalVariable*> globals;
std::map<jl_datatype_t*, DIType*> ditypes;
std::map<jl_datatype_t*, Type*> llvmtypes;
Expand Down

0 comments on commit 88c330a

Please sign in to comment.