Skip to content

Commit

Permalink
codegen: reduce dependence on globalUnique counter
Browse files Browse the repository at this point in the history
Moving these values private lets us use a local count instead.
  • Loading branch information
vtjnash committed Jul 1, 2020
1 parent ad94873 commit ab8f0f2
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 94 deletions.
2 changes: 0 additions & 2 deletions src/anticodegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

#include "intrinsics.h"

int globalUnique = 0;

#define UNAVAILABLE { jl_errorf("%s: not available in this build of Julia", __func__); }

void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *asm_fname, const char *sysimg_data, size_t sysimg_len) UNAVAILABLE
Expand Down
7 changes: 0 additions & 7 deletions src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,13 +565,6 @@ void jl_dump_native(void *native_code,
sysimage->setDataLayout(data->M->getDataLayout());
data->M.reset(); // free memory for data->M

addComdat(new GlobalVariable(*sysimage,
T_size,
true,
GlobalVariable::ExternalLinkage,
ConstantInt::get(T_size, globalUnique + 1),
"jl_globalUnique"));

if (sysimg_data) {
Constant *data = ConstantDataArray::get(Context,
ArrayRef<uint8_t>((const unsigned char*)sysimg_data, sysimg_len));
Expand Down
2 changes: 0 additions & 2 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ static bool runtime_sym_gvs(jl_codegen_params_t &emission_context, const char *f

GlobalVariable *&llvmgv = (*symMap)[f_name];
if (llvmgv == NULL) {
// MCJIT forces this to have external linkage eventually, so we would clobber
// the symbol of the actual function.
std::string name = "ccall_";
name += f_name;
name += "_";
Expand Down
66 changes: 30 additions & 36 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,27 +94,16 @@ static Value *stringConstPtr(
IRBuilder<> &irbuilder,
const std::string &txt)
{
StringRef ctxt(txt.c_str(), txt.size() + 1);
StringMap<GlobalVariable*>::iterator pooledval =
emission_context.stringConstants.insert(std::pair<StringRef, GlobalVariable*>(ctxt, NULL)).first;
Module *M = jl_builderModule(irbuilder);
if (pooledval->second == NULL) {
static int strno = 0;
std::stringstream ssno;
ssno << "_j_str" << strno++;
GlobalVariable *gv = get_pointer_to_constant(
ConstantDataArray::get(jl_LLVMContext, ArrayRef<char>(ctxt.data(), ctxt.size())),
ssno.str(), *M);
pooledval->second = gv;
}
GlobalVariable *v = prepare_global_in(M, pooledval->second);
if (v != pooledval->second)
v->setInitializer(pooledval->second->getInitializer());
StringRef ctxt(txt.c_str(), txt.size() + 1);
Constant *Data = ConstantDataArray::get(jl_LLVMContext, arrayRefFromStringRef(ctxt));
GlobalVariable *gv = get_pointer_to_constant(emission_context, Data, "_j_str", *M);
Value *zero = ConstantInt::get(Type::getInt32Ty(jl_LLVMContext), 0);
Value *Args[] = { zero, zero };
return irbuilder.CreateInBoundsGEP(v->getValueType(), v, Args);
return irbuilder.CreateInBoundsGEP(gv->getValueType(), gv, Args);
}


// --- MDNode ---
Metadata *to_md_tree(jl_value_t *val) {
if (val == jl_nothing)
Expand Down Expand Up @@ -170,8 +159,8 @@ static DIType *_julia_type_to_di(jl_codegen_params_t *ctx, jl_value_t *jt, DIBui
Elements[i] = di;
}
DINodeArray ElemArray = dbuilder->getOrCreateArray(Elements);
std::stringstream unique_name;
unique_name << (uintptr_t)jdt;
std::string unique_name;
llvm::raw_string_ostream(unique_name) << (uintptr_t)jdt;
ditype = dbuilder->createStructType(
NULL, // Scope
tname, // Name
Expand All @@ -184,7 +173,7 @@ static DIType *_julia_type_to_di(jl_codegen_params_t *ctx, jl_value_t *jt, DIBui
ElemArray, // Elements
dwarf::DW_LANG_Julia, // RuntimeLanguage
nullptr, // VTableHolder
unique_name.str() // UniqueIdentifier
unique_name // UniqueIdentifier
);
}
else {
Expand Down Expand Up @@ -237,23 +226,28 @@ static inline Constant *literal_static_pointer_val(const void *p, Type *T = T_pj

static Value *julia_pgv(jl_codectx_t &ctx, const char *cname, void *addr)
{
// first see if there already is a GlobalVariable for this address
// emit a GlobalVariable for a jl_value_t named "cname"
// store the name given so we can reuse it (facilitating merging later)
// so first see if there already is a GlobalVariable for this address
GlobalVariable* &gv = ctx.global_targets[addr];
Module *M = jl_Module;
StringRef localname;
std::string gvname;
if (!gv) {
// otherwise emit a new GlobalVariable for a jl_value_t named "cname"
std::stringstream gvname;
gvname << cname << globalUnique++;
// no existing GlobalVariable, create one and store it
gv = new GlobalVariable(*M, T_pjlvalue,
false, GlobalVariable::ExternalLinkage,
NULL, gvname.str());
llvm::raw_string_ostream(gvname) << cname << ctx.global_targets.size();
localname = StringRef(gvname);
}
else if (gv->getParent() != M) {
// re-use the same name, but move it to the new module
// this will help simplify merging them later
gv = prepare_global_in(M, gv);
else {
localname = gv->getName();
if (gv->getParent() != M)
gv = cast_or_null<GlobalVariable>(M->getNamedValue(localname));
}
if (gv == nullptr)
gv = new GlobalVariable(*M, T_pjlvalue,
false, GlobalVariable::PrivateLinkage,
NULL, localname);
assert(localname == gv->getName());
assert(!gv->hasInitializer());
return gv;
}

Expand Down Expand Up @@ -291,6 +285,8 @@ static Value *literal_pointer_val_slot(jl_codectx_t &ctx, jl_value_t *p)
// emit a pointer to a jl_value_t* which will allow it to be valid across reloading code
// also, try to give it a nice name for gdb, for easy identification
if (!imaging_mode) {
// TODO: this is an optimization, but is it useful or premature
// (it'll block any attempt to cache these, but can be simply deleted)
Module *M = jl_Module;
GlobalVariable *gv = new GlobalVariable(
*M, T_pjlvalue, true, GlobalVariable::PrivateLinkage,
Expand Down Expand Up @@ -1423,12 +1419,10 @@ static Value *data_pointer(jl_codectx_t &ctx, const jl_cgval_t &x)
Value *data = x.V;
if (x.constant) {
Constant *val = julia_const_to_llvm(ctx, x.constant);
if (val) {
data = get_pointer_to_constant(val, "", *jl_Module);
}
else {
if (val)
data = get_pointer_to_constant(ctx.emission_context, val, "_j_const", *jl_Module);
else
data = literal_pointer_val(ctx, x.constant);
}
}
return data;
}
Expand Down
50 changes: 30 additions & 20 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -809,10 +809,10 @@ static const std::map<jl_fptr_args_t, JuliaFunction*> builtin_func_map = {
{ &jl_f_apply_type, new JuliaFunction{"jl_f_apply_type", get_func_sig, get_func_attrs} },
};

static int globalUnique = 0;

// --- code generation ---
extern "C" {
int globalUnique = 0;
int jl_default_debug_info_kind = (int) DICompileUnit::DebugEmissionKind::FullDebug;
jl_cgparams_t jl_default_cgparams = {1, 1, 1, 0,
#ifdef _OS_WINDOWS_
Expand Down Expand Up @@ -1100,16 +1100,32 @@ static inline GlobalVariable *prepare_global_in(Module *M, GlobalVariable *G)

// --- convenience functions for tagging llvm values with julia types ---

static GlobalVariable *get_pointer_to_constant(Constant *val, StringRef name, Module &M)
static GlobalVariable *get_pointer_to_constant(jl_codegen_params_t &emission_context, Constant *val, StringRef name, Module &M)
{
GlobalVariable *gv = new GlobalVariable(
M,
val->getType(),
true,
GlobalVariable::ExternalLinkage,
val,
name);
gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GlobalVariable *&gv = emission_context.mergedConstants[val];
StringRef localname;
std::string ssno;
if (gv == nullptr) {
raw_string_ostream(ssno) << name << emission_context.mergedConstants.size();
localname = StringRef(ssno);
}
else {
localname = gv->getName();
if (gv->getParent() != &M)
gv = cast_or_null<GlobalVariable>(M.getNamedValue(localname));
}
if (gv == nullptr) {
gv = new GlobalVariable(
M,
val->getType(),
true,
GlobalVariable::PrivateLinkage,
val,
localname);
gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
}
assert(localname == gv->getName());
assert(val == gv->getInitializer());
return gv;
}

Expand Down Expand Up @@ -1198,7 +1214,7 @@ static inline jl_cgval_t value_to_pointer(jl_codectx_t &ctx, Value *v, jl_value_
{
Value *loc;
if (valid_as_globalinit(v)) { // llvm can't handle all the things that could be inside a ConstantExpr
loc = get_pointer_to_constant(cast<Constant>(v), "", *jl_Module);
loc = get_pointer_to_constant(ctx.emission_context, cast<Constant>(v), "_j_const", *jl_Module);
}
else {
loc = emit_static_alloca(ctx, v->getType());
Expand Down Expand Up @@ -3454,12 +3470,9 @@ static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t
b = jl_get_binding(m, s);
if (b == NULL) {
// var not found. switch to delayed lookup.
std::stringstream name;
name << "delayedvar" << globalUnique++;
Constant *initnul = V_null;
GlobalVariable *bindinggv = new GlobalVariable(*ctx.f->getParent(), T_pjlvalue,
false, GlobalVariable::InternalLinkage,
initnul, name.str());
false, GlobalVariable::PrivateLinkage, initnul);
Value *cachedval = ctx.builder.CreateLoad(T_pjlvalue, bindinggv);
BasicBlock *have_val = BasicBlock::Create(jl_LLVMContext, "found"),
*not_found = BasicBlock::Create(jl_LLVMContext, "notfound");
Expand Down Expand Up @@ -5175,13 +5188,10 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con
}
jl_add_method_root(ctx, (jl_value_t*)fill);
}
std::stringstream cname;
cname << "trampolines" << globalUnique++;
Type *T_htable = ArrayType::get(T_size, sizeof(htable_t) / sizeof(void*));
Value *cache = new GlobalVariable(*jl_Module, T_htable, false,
GlobalVariable::InternalLinkage,
ConstantAggregateZero::get(T_htable),
cname.str());
GlobalVariable::PrivateLinkage,
ConstantAggregateZero::get(T_htable));
F = ctx.builder.CreateCall(prepare_call(jlgetcfunctiontrampoline_func), {
fobj,
literal_pointer_val(ctx, output_type),
Expand Down
51 changes: 28 additions & 23 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,26 +62,6 @@ void jl_jit_globals(std::map<void *, GlobalVariable*> &globals)
}
}

// turn long strings into memoized copies, instead of making a copy per object file of output.
void jl_jit_strings(jl_codegen_params_t::SymMapGV &stringConstants)
{
for (auto &it : stringConstants) {
GlobalVariable *GV = it.second;
Constant *CDA = GV->getInitializer();
StringRef data = cast<ConstantDataSequential>(CDA)->getRawDataValues();
if (data.size() > 8) { // only for long strings: keep short ones as values
Type *T_size = Type::getIntNTy(GV->getContext(), sizeof(void*) * 8);
Constant *v = ConstantExpr::getIntToPtr(
ConstantInt::get(T_size, (uintptr_t)data.data()),
GV->getType());
GV->replaceAllUsesWith(v);
GV->eraseFromParent();
it.second = nullptr;
}
}
}


// this generates llvm code for the lambda info
// and adds the result to the jitlayers
// (and the shadow module),
Expand Down Expand Up @@ -119,7 +99,6 @@ static jl_callptr_t _jl_compile_codeinst(
emitted[codeinst] = std::move(result);
jl_compile_workqueue(emitted, params, CompilationPolicy::Default);

jl_jit_strings(params.stringConstants);
if (params._shared_module)
jl_add_to_ee(std::unique_ptr<Module>(params._shared_module));
StringMap<std::unique_ptr<Module>*> NewExports;
Expand Down Expand Up @@ -237,7 +216,6 @@ void jl_compile_extern_c(void *llvmmod, void *p, void *sysimg, jl_value_t *declr
if (!sysimg) {
if (p == NULL) {
jl_jit_globals(params.globals);
jl_jit_strings(params.stringConstants);
assert(params.workqueue.empty());
if (params._shared_module)
jl_add_to_ee(std::unique_ptr<Module>(params._shared_module));
Expand Down Expand Up @@ -741,6 +719,7 @@ uint64_t JuliaOJIT::getFunctionAddress(StringRef Name)
return addr ? addr.get() : 0;
}

static int globalUniqueGeneratedNames;
StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_code_instance_t *codeinst)
{
auto &fname = ReverseLocalSymbolTable[(void*)(uintptr_t)Addr];
Expand All @@ -760,7 +739,7 @@ StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_code_instance_t *cod
stream_fname << "jlsys_";
}
const char* unadorned_name = jl_symbol_name(codeinst->def->def.method->name);
stream_fname << unadorned_name << "_" << globalUnique++;
stream_fname << unadorned_name << "_" << globalUniqueGeneratedNames++;
std::string string_fname = stream_fname.str();
fname = strdup(string_fname.c_str());
LocalSymbolTable[getMangledName(string_fname)] = (void*)(uintptr_t)Addr;
Expand Down Expand Up @@ -895,6 +874,31 @@ void jl_merge_module(Module *dest, std::unique_ptr<Module> src)
}
}

// optimize memory by turning long strings into memoized copies, instead of
// making a copy per object file of output.
void jl_jit_share_data(Module &M)
{
std::vector<GlobalVariable*> erase;
for (auto &GV : M.globals()) {
if (!GV.hasInitializer() || !GV.isConstant())
continue;
ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer());
if (CDS == nullptr)
continue;
StringRef data = CDS->getRawDataValues();
if (data.size() > 16) { // only for long strings: keep short ones as values
Type *T_size = Type::getIntNTy(GV.getContext(), sizeof(void*) * 8);
Constant *v = ConstantExpr::getIntToPtr(
ConstantInt::get(T_size, (uintptr_t)data.data()),
GV.getType());
GV.replaceAllUsesWith(v);
erase.push_back(&GV);
}
}
for (auto GV : erase)
GV->eraseFromParent();
}

static void jl_add_to_ee(std::unique_ptr<Module> m)
{
JL_TIMING(LLVM_EMIT);
Expand All @@ -909,6 +913,7 @@ static void jl_add_to_ee(std::unique_ptr<Module> m)
false, GlobalVariable::InternalLinkage,
ConstantAggregateZero::get(atype), "__catchjmp"))->setSection(".text");
#endif
jl_jit_share_data(*m);
assert(jl_ExecutionEngine);
jl_ExecutionEngine->addModule(std::move(m));
}
Expand Down
5 changes: 1 addition & 4 deletions src/jitlayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

using namespace llvm;

extern "C" {
extern int globalUnique;
}
extern TargetMachine *jl_TargetMachine;
extern bool imaging_mode;

Expand Down Expand Up @@ -62,7 +59,7 @@ typedef struct {
std::map<void*, GlobalVariable*> globals;
std::map<jl_datatype_t*, DIType*> ditypes;
std::map<jl_datatype_t*, Type*> llvmtypes;
SymMapGV stringConstants;
DenseMap<Constant*, GlobalVariable*> mergedConstants;
// Map from symbol name (in a certain library) to its GV in sysimg and the
// DL handle address in the current session.
StringMap<std::pair<GlobalVariable*,SymMapGV>> libMapGV;
Expand Down

0 comments on commit ab8f0f2

Please sign in to comment.