Skip to content

Commit

Permalink
compile: make more efficient by discarding internal names (#56702)
Browse files Browse the repository at this point in the history
These are not user-visible, so this makes the compiler faster and more
efficient with no effort on our part, and avoids duplicating the
debug_level parameter.
  • Loading branch information
vtjnash authored Nov 29, 2024
1 parent 5053a17 commit c1f806d
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 45 deletions.
7 changes: 5 additions & 2 deletions src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,9 +593,10 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvm
});
egal_set method_roots;
jl_codegen_params_t params(ctxt, std::move(target_info.first), std::move(target_info.second));
if (!llvmmod)
params.getContext().setDiscardValueNames(true);
params.params = cgparams;
params.imaging_mode = imaging;
params.debug_level = cgparams->debug_info_level;
params.external_linkage = _external_linkage;
params.temporary_roots = jl_alloc_array_1d(jl_array_any_type, 0);
JL_GC_PUSH3(&params.temporary_roots, &method_roots.list, &method_roots.keyset);
Expand Down Expand Up @@ -1719,6 +1720,7 @@ static SmallVector<AOTOutputs, 16> add_output(Module &M, TargetMachine &TM, Stri
for (unsigned i = 0; i < threads; i++) {
std::function<void()> func = [&, i]() {
LLVMContext ctx;
ctx.setDiscardValueNames(true);
#if JL_LLVM_VERSION < 170000
SetOpaquePointer(ctx);
#endif
Expand Down Expand Up @@ -1930,6 +1932,7 @@ void jl_dump_native_impl(void *native_code,
if (z) {
JL_TIMING(NATIVE_AOT, NATIVE_Sysimg);
LLVMContext Context;
Context.setDiscardValueNames(true);
#if JL_LLVM_VERSION < 170000
SetOpaquePointer(Context);
#endif
Expand Down Expand Up @@ -2077,6 +2080,7 @@ void jl_dump_native_impl(void *native_code,
{
JL_TIMING(NATIVE_AOT, NATIVE_Metadata);
LLVMContext Context;
Context.setDiscardValueNames(true);
#if JL_LLVM_VERSION < 170000
SetOpaquePointer(Context);
#endif
Expand Down Expand Up @@ -2278,7 +2282,6 @@ void jl_get_llvmf_defn_impl(jl_llvmf_dump_t* dump, jl_method_instance_t *mi, jl_
// output.imaging = true;
// This would also be nice, but it seems to cause OOMs on the windows32 builder
// To get correct names in the IR this needs to be at least 2
output.debug_level = params.debug_info_level;
output.temporary_roots = jl_alloc_array_1d(jl_array_any_type, 0);
JL_GC_PUSH1(&output.temporary_roots);
auto decls = jl_emit_code(m, mi, src, output);
Expand Down
10 changes: 8 additions & 2 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar

// generate a temporary module that contains our IR
std::unique_ptr<Module> Mod;
bool shouldDiscardValueNames = ctx.builder.getContext().shouldDiscardValueNames();
Function *f;
if (entry == NULL) {
// we only have function IR, which we should put in a function
Expand Down Expand Up @@ -878,7 +879,9 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar
<< jl_string_data(ir) << "\n}";

SMDiagnostic Err = SMDiagnostic();
ctx.builder.getContext().setDiscardValueNames(false);
Mod = parseAssemblyString(ir_stream.str(), Err, ctx.builder.getContext());
ctx.builder.getContext().setDiscardValueNames(shouldDiscardValueNames);

// backwards compatibility: support for IR with integer pointers
if (!Mod) {
Expand Down Expand Up @@ -911,8 +914,9 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar
<< jl_string_data(ir) << "\n}";

SMDiagnostic Err = SMDiagnostic();
Mod =
parseAssemblyString(compat_ir_stream.str(), Err, ctx.builder.getContext());
ctx.builder.getContext().setDiscardValueNames(false);
Mod = parseAssemblyString(compat_ir_stream.str(), Err, ctx.builder.getContext());
ctx.builder.getContext().setDiscardValueNames(shouldDiscardValueNames);
}

if (!Mod) {
Expand All @@ -932,7 +936,9 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar

if (jl_is_string(ir)) {
SMDiagnostic Err = SMDiagnostic();
ctx.builder.getContext().setDiscardValueNames(false);
Mod = parseAssemblyString(jl_string_data(ir), Err, ctx.builder.getContext());
ctx.builder.getContext().setDiscardValueNames(shouldDiscardValueNames);
if (!Mod) {
std::string message = "Failed to parse LLVM assembly: \n";
raw_string_ostream stream(message);
Expand Down
27 changes: 12 additions & 15 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,31 +167,29 @@ void setName(jl_codegen_params_t &params, Value *V, const Twine &Name)
// is not checking that setName is only called for non-folded instructions (e.g. folded bitcasts
// and 0-byte geps), which can result in information loss on the renamed instruction.
assert((isa<Constant>(V) || isa<Instruction>(V)) && "Should only set names on instructions!");
if (params.debug_level >= 2 && !isa<Constant>(V)) {
if (!isa<Constant>(V)) {
V->setName(Name);
}
}

void maybeSetName(jl_codegen_params_t &params, Value *V, const Twine &Name)
{
// To be used when we may get an Instruction or something that is not an instruction i.e Constants/Arguments
if (params.debug_level >= 2 && isa<Instruction>(V)) {
if (isa<Instruction>(V))
V->setName(Name);
}
}

void setName(jl_codegen_params_t &params, Value *V, std::function<std::string()> GetName)
{
assert((isa<Constant>(V) || isa<Instruction>(V)) && "Should only set names on instructions!");
if (params.debug_level >= 2 && !isa<Constant>(V)) {
if (!params.getContext().shouldDiscardValueNames() && !isa<Constant>(V))
V->setName(Twine(GetName()));
}
}

void setNameWithField(jl_codegen_params_t &params, Value *V, std::function<StringRef()> GetObjName, jl_datatype_t *jt, unsigned idx, const Twine &suffix)
{
assert((isa<Constant>(V) || isa<Instruction>(V)) && "Should only set names on instructions!");
if (params.debug_level >= 2 && !isa<Constant>(V)) {
if (!params.getContext().shouldDiscardValueNames() && !isa<Constant>(V)) {
if (jl_is_tuple_type(jt)){
V->setName(Twine(GetObjName()) + "[" + Twine(idx + 1) + "]"+ suffix);
return;
Expand Down Expand Up @@ -8327,7 +8325,7 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value
if (f == NULL) {
f = Function::Create(ftype, GlobalVariable::ExternalLinkage, name, M);
jl_init_function(f, ctx.emission_context.TargetTriple);
if (ctx.emission_context.debug_level >= 2) {
if (ctx.emission_context.params->debug_info_level >= 2) {
ios_t sigbuf;
ios_mem(&sigbuf, 0);
jl_static_show_func_sig((JL_STREAM*) &sigbuf, sig);
Expand Down Expand Up @@ -8435,7 +8433,7 @@ static jl_llvm_functions_t
std::map<int, BasicBlock*> labels;
ctx.module = jl_is_method(lam->def.method) ? lam->def.method->module : lam->def.module;
ctx.linfo = lam;
ctx.name = TSM.getModuleUnlocked()->getModuleIdentifier().data();
ctx.name = name_from_method_instance(lam);
size_t nreq = src->nargs;
int va = src->isva;
ctx.nargs = nreq;
Expand Down Expand Up @@ -8488,7 +8486,7 @@ static jl_llvm_functions_t
// jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n",
// jl_symbol_name(ctx.name), ctx.file.str().c_str(), toplineno);

bool debug_enabled = ctx.emission_context.debug_level != 0;
bool debug_enabled = ctx.emission_context.params->debug_info_level != 0;
if (dbgFuncName.empty()) // Should never happen anymore?
debug_enabled = false;

Expand Down Expand Up @@ -8564,15 +8562,14 @@ static jl_llvm_functions_t
// allocate Function declarations and wrapper objects
//Safe because params holds ctx lock
Module *M = TSM.getModuleUnlocked();
M->addModuleFlag(Module::Warning, "julia.debug_level", ctx.emission_context.debug_level);
jl_debugcache_t debugcache;
debugcache.initialize(M);
jl_returninfo_t returninfo = {};
Function *f = NULL;
bool has_sret = false;
if (specsig) { // assumes !va and !needsparams
SmallVector<const char*,0> ArgNames(0);
if (ctx.emission_context.debug_level >= 2) {
if (!M->getContext().shouldDiscardValueNames()) {
ArgNames.resize(ctx.nargs, "");
for (int i = 0; i < ctx.nargs; i++) {
jl_sym_t *argname = slot_symbol(ctx, i);
Expand Down Expand Up @@ -8639,7 +8636,7 @@ static jl_llvm_functions_t
declarations.functionObject = needsparams ? "jl_fptr_sparam" : "jl_fptr_args";
}

if (ctx.emission_context.debug_level >= 2 && lam->def.method && jl_is_method(lam->def.method) && lam->specTypes != (jl_value_t*)jl_emptytuple_type) {
if (!params.getContext().shouldDiscardValueNames() && ctx.emission_context.params->debug_info_level >= 2 && lam->def.method && jl_is_method(lam->def.method) && lam->specTypes != (jl_value_t*)jl_emptytuple_type) {
ios_t sigbuf;
ios_mem(&sigbuf, 0);
jl_static_show_func_sig((JL_STREAM*) &sigbuf, (jl_value_t*)lam->specTypes);
Expand Down Expand Up @@ -8694,7 +8691,7 @@ static jl_llvm_functions_t
if (debug_enabled) {
topfile = dbuilder.createFile(ctx.file, ".");
DISubroutineType *subrty;
if (ctx.emission_context.debug_level <= 1)
if (ctx.emission_context.params->debug_info_level <= 1)
subrty = debugcache.jl_di_func_null_sig;
else if (!specsig)
subrty = debugcache.jl_di_func_sig;
Expand All @@ -8715,7 +8712,7 @@ static jl_llvm_functions_t
);
topdebugloc = DILocation::get(ctx.builder.getContext(), toplineno, 0, SP, NULL);
f->setSubprogram(SP);
if (ctx.emission_context.debug_level >= 2) {
if (ctx.emission_context.params->debug_info_level >= 2) {
const bool AlwaysPreserve = true;
// Go over all arguments and local variables and initialize their debug information
for (i = 0; i < nreq; i++) {
Expand Down Expand Up @@ -10161,7 +10158,7 @@ jl_llvm_functions_t jl_emit_codeinst(
if (// keep code when keeping everything
!(JL_DELETE_NON_INLINEABLE) ||
// aggressively keep code when debugging level >= 2
// note that this uses the global jl_options.debug_level, not the local emission_ctx.debug_level
// note that this uses the global jl_options.debug_level, not the local emission_ctx.debug_info_level
jl_options.debug_level > 1) {
// update the stored code
if (inferred != (jl_value_t*)src) {
Expand Down
7 changes: 4 additions & 3 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,9 +690,9 @@ static void jl_emit_codeinst_to_jit(
JL_TIMING(CODEINST_COMPILE, CODEINST_COMPILE);
// emit the code in LLVM IR form to the new context
jl_codegen_params_t params(std::make_unique<LLVMContext>(), jl_ExecutionEngine->getDataLayout(), jl_ExecutionEngine->getTargetTriple()); // Locks the context
params.getContext().setDiscardValueNames(true);
params.cache = true;
params.imaging_mode = imaging_default();
params.debug_level = jl_options.debug_level;
orc::ThreadSafeModule result_m =
jl_create_ts_module(name_from_method_instance(codeinst->def), params.tsctx, params.DL, params.TargetTriple);
params.temporary_roots = jl_alloc_array_1d(jl_array_any_type, 0);
Expand Down Expand Up @@ -795,9 +795,10 @@ int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void *
Module *M = into->getModuleUnlocked();
jl_codegen_params_t params(into->getContext(), M->getDataLayout(), Triple(M->getTargetTriple()));
params.imaging_mode = imaging_default();
params.debug_level = jl_options.debug_level;
if (pparams == NULL)
if (pparams == NULL) {
M->getContext().setDiscardValueNames(true);
pparams = &params;
}
assert(pparams->tsctx.getContext() == into->getContext().getContext());
const char *name = jl_generate_ccallable(wrap(into), sysimg, declrt, sigt, *pparams);
if (!sysimg) {
Expand Down
1 change: 0 additions & 1 deletion src/jitlayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,6 @@ struct jl_codegen_params_t {
bool cache = false;
bool external_linkage = false;
bool imaging_mode;
int debug_level;
bool use_swiftcc = true;
jl_codegen_params_t(orc::ThreadSafeContext ctx, DataLayout DL, Triple triple)
: tsctx(std::move(ctx)),
Expand Down
21 changes: 6 additions & 15 deletions src/llvm-late-gc-lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1944,36 +1944,27 @@ void LateLowerGCFrame::CleanupWriteBarriers(Function &F, State *S, const SmallVe
if (CFGModified) {
*CFGModified = true;
}
auto DebugInfoMeta = F.getParent()->getModuleFlag("julia.debug_level");
int debug_info = 1;
if (DebugInfoMeta != nullptr) {
debug_info = cast<ConstantInt>(cast<ConstantAsMetadata>(DebugInfoMeta)->getValue())->getZExtValue();
}

IRBuilder<> builder(CI);
builder.SetCurrentDebugLocation(CI->getDebugLoc());
auto parBits = builder.CreateAnd(EmitLoadTag(builder, T_size, parent), GC_OLD_MARKED);
setName(parBits, "parent_bits", debug_info);
auto parOldMarked = builder.CreateICmpEQ(parBits, ConstantInt::get(T_size, GC_OLD_MARKED));
setName(parOldMarked, "parent_old_marked", debug_info);
auto parBits = builder.CreateAnd(EmitLoadTag(builder, T_size, parent), GC_OLD_MARKED, "parent_bits");
auto parOldMarked = builder.CreateICmpEQ(parBits, ConstantInt::get(T_size, GC_OLD_MARKED), "parent_old_marked");
auto mayTrigTerm = SplitBlockAndInsertIfThen(parOldMarked, CI, false);
builder.SetInsertPoint(mayTrigTerm);
setName(mayTrigTerm->getParent(), "may_trigger_wb", debug_info);
mayTrigTerm->getParent()->setName("may_trigger_wb");
Value *anyChldNotMarked = NULL;
for (unsigned i = 1; i < CI->arg_size(); i++) {
Value *child = CI->getArgOperand(i);
Value *chldBit = builder.CreateAnd(EmitLoadTag(builder, T_size, child), GC_MARKED);
setName(chldBit, "child_bit", debug_info);
Value *chldNotMarked = builder.CreateICmpEQ(chldBit, ConstantInt::get(T_size, 0),"child_not_marked");
setName(chldNotMarked, "child_not_marked", debug_info);
Value *chldBit = builder.CreateAnd(EmitLoadTag(builder, T_size, child), GC_MARKED, "child_bit");
Value *chldNotMarked = builder.CreateICmpEQ(chldBit, ConstantInt::get(T_size, 0), "child_not_marked");
anyChldNotMarked = anyChldNotMarked ? builder.CreateOr(anyChldNotMarked, chldNotMarked) : chldNotMarked;
}
assert(anyChldNotMarked); // handled by all_of test above
MDBuilder MDB(parent->getContext());
SmallVector<uint32_t, 2> Weights{1, 9};
auto trigTerm = SplitBlockAndInsertIfThen(anyChldNotMarked, mayTrigTerm, false,
MDB.createBranchWeights(Weights));
setName(trigTerm->getParent(), "trigger_wb", debug_info);
trigTerm->getParent()->setName("trigger_wb");
builder.SetInsertPoint(trigTerm);
if (CI->getCalledOperand() == write_barrier_func) {
builder.CreateCall(getOrDeclare(jl_intrinsics::queueGCRoot), parent);
Expand Down
7 changes: 0 additions & 7 deletions src/llvm-pass-helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,3 @@ namespace jl_well_known {
return addGCAllocAttributes(allocTypedFunc);
});
}

void setName(llvm::Value *V, const llvm::Twine &Name, int debug_info)
{
if (debug_info >= 2 && !llvm::isa<llvm::Constant>(V)) {
V->setName(Name);
}
}

0 comments on commit c1f806d

Please sign in to comment.