Skip to content

Commit

Permalink
Towards being able to run GC frame lowering after LLVM optimizations
Browse files Browse the repository at this point in the history
* Make the pass more robust against dead code elimination
* Remove module level setup code (so that the the GC frame lowering can be
  a `FunctionPass`)
* Create PTLS lowering (module) pass since it needs to be run after the GC frame
  lowering
* Set DLLImport attribute for `jl_tls_states` on windows,
  since it is not handled by module merger anymore
  • Loading branch information
yuyichao committed Jul 21, 2016
1 parent c8f1b62 commit b27d520
Show file tree
Hide file tree
Showing 6 changed files with 364 additions and 202 deletions.
4 changes: 2 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ SRCS := \
alloc dlload sys init task array dump toplevel jl_uv \
simplevector APInt-C runtime_intrinsics runtime_ccall \
threadgroup threading stackwalk gc gc-debug gc-pages \
jlapi signal-handling safepoint jloptions timing
jlapi signal-handling safepoint jloptions timing

ifeq ($(USEMSVC), 1)
SRCS += getopt
Expand All @@ -49,7 +49,7 @@ endif
LLVMLINK :=

ifeq ($(JULIACODEGEN),LLVM)
SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-gcroot cgmemmgr
SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-gcroot cgmemmgr
FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --includedir)
LLVM_LIBS := all
ifeq ($(USE_POLLY),1)
Expand Down
95 changes: 4 additions & 91 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/CommandLine.h>

#if defined(_CPU_ARM_) || defined(_CPU_AARCH64_) || \
(defined(LLVM37) && defined(JULIA_ENABLE_THREADING))
#if defined(_CPU_ARM_) || defined(_CPU_AARCH64_)
# include <llvm/IR/InlineAsm.h>
#endif
#if defined(USE_POLLY)
Expand Down Expand Up @@ -257,7 +256,7 @@ static MDNode *tbaa_arrayptr; // The pointer inside a jl_array_t
static MDNode *tbaa_arraysize; // A size in a jl_array_t
static MDNode *tbaa_arraylen; // The len in a jl_array_t
static MDNode *tbaa_arrayflags; // The flags in a jl_array_t
static MDNode *tbaa_const; // Memory that is immutable by the time LLVM can see it
MDNode *tbaa_const; // Memory that is immutable by the time LLVM can see it

// Basic DITypes
#ifdef LLVM37
Expand Down Expand Up @@ -388,7 +387,6 @@ static Function *jlarray_data_owner_func;

// placeholder functions
static Function *gcroot_func;
static Function *gcstore_func;
static Function *gckill_func;
static Function *jlcall_frame_func;
static Function *gcroot_flush_func;
Expand Down Expand Up @@ -3399,87 +3397,15 @@ static void allocate_gc_frame(BasicBlock *b0, jl_codectx_t *ctx)
PointerType::get(T_psize, 0));
}

void jl_codegen_finalize_temp_arg(CallInst *ptlsStates, Type *T_pjlvalue,
MDNode *tbaa_gcframe);
static void finalize_gc_frame(Function *F)
{
Module *M = F->getParent();
M->getOrInsertFunction(gcroot_func->getName(), gcroot_func->getFunctionType());
M->getOrInsertFunction(gckill_func->getName(), gckill_func->getFunctionType());
M->getOrInsertFunction(gcstore_func->getName(), gcstore_func->getFunctionType());
M->getOrInsertFunction(jlcall_frame_func->getName(), jlcall_frame_func->getFunctionType());
M->getOrInsertFunction(gcroot_flush_func->getName(), gcroot_flush_func->getFunctionType());
Function *jl_get_ptls_states = M->getFunction("jl_get_ptls_states");

CallInst *ptlsStates = NULL;
for (BasicBlock::iterator i = F->getEntryBlock().begin(), e = F->getEntryBlock().end(); i != e; ++i) {
if (CallInst *callInst = dyn_cast<CallInst>(&*i)) {
if (callInst->getCalledFunction() == jl_get_ptls_states) {
ptlsStates = callInst;
break;
}
}
}
if (!ptlsStates)
return;

jl_codegen_finalize_temp_arg(ptlsStates, T_pjlvalue, tbaa_gcframe);

#ifdef JULIA_ENABLE_THREADING
if (imaging_mode) {
GlobalVariable *GV = prepare_global(jltls_states_func_ptr, M);
Value *getter = tbaa_decorate(tbaa_const,
new LoadInst(GV, "", ptlsStates));
ptlsStates->setCalledFunction(getter);
ptlsStates->setAttributes(jltls_states_func->getAttributes());
}
else if (jl_tls_offset != -1) {
#ifdef LLVM37
// Replace the function call with inline assembly if we know
// how to generate it.
const char *asm_str = nullptr;
# if defined(_CPU_X86_64_)
asm_str = "movq %fs:0, $0";
# elif defined(_CPU_X86_)
asm_str = "movl %gs:0, $0";
# elif defined(_CPU_AARCH64_)
asm_str = "mrs $0, tpidr_el0";
# endif
assert(asm_str && "Cannot emit thread pointer for this architecture.");
static auto offset = ConstantInt::getSigned(T_size, jl_tls_offset);
static auto tp = InlineAsm::get(FunctionType::get(T_pint8, false),
asm_str, "=r", false);
Value *tls = CallInst::Create(tp, "thread_ptr", ptlsStates);
tls = GetElementPtrInst::Create(T_int8, tls, {offset},
"ptls_i8", ptlsStates);
tls = new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0),
"ptls", ptlsStates);
ptlsStates->replaceAllUsesWith(tls);
ptlsStates->eraseFromParent();
#endif
}
#else
ptlsStates->replaceAllUsesWith(prepare_global(jltls_states_var, M));
ptlsStates->eraseFromParent();
#endif
}

void jl_codegen_finalize_temp_arg(Function *F, MDNode *tbaa_gcframe);
void finalize_gc_frame(Module *m)
{
for (Module::iterator I = m->begin(), E = m->end(); I != E; ++I) {
Function *F = &*I;
if (F->isDeclaration())
continue;
finalize_gc_frame(F);
jl_codegen_finalize_temp_arg(F, tbaa_gcframe);
}
#ifndef JULIA_ENABLE_THREADING
m->getFunction("jl_get_ptls_states")->eraseFromParent();
#endif
m->getFunction("julia.gc_root_decl")->eraseFromParent();
m->getFunction("julia.gc_root_kill")->eraseFromParent();
m->getFunction("julia.gc_store")->eraseFromParent();
m->getFunction("julia.jlcall_frame_decl")->eraseFromParent();
m->getFunction("julia.gcroot_flush")->eraseFromParent();
}

static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_tupletype_t *argt,
Expand Down Expand Up @@ -5186,12 +5112,6 @@ static void init_julia_llvm_env(Module *m)
jltls_states_func = Function::Create(FunctionType::get(PointerType::get(T_ppjlvalue, 0), false),
Function::ExternalLinkage,
"jl_get_ptls_states", m);
jltls_states_func->setAttributes(
jltls_states_func->getAttributes()
.addAttribute(jltls_states_func->getContext(),
AttributeSet::FunctionIndex, Attribute::ReadNone)
.addAttribute(jltls_states_func->getContext(),
AttributeSet::FunctionIndex, Attribute::NoUnwind));
add_named_global(jltls_states_func, jl_get_ptls_states_getter());
if (imaging_mode) {
PointerType *pfunctype = jltls_states_func->getFunctionType()->getPointerTo();
Expand Down Expand Up @@ -5608,13 +5528,6 @@ static void init_julia_llvm_env(Module *m)
"julia.gc_root_kill", m);
add_named_global(gckill_func, (void*)NULL, /*dllimport*/false);

Type* gc_store_args[2] = { T_ppjlvalue, T_pjlvalue }; // [1] <= [2]
gcstore_func =
Function::Create(FunctionType::get(T_void, makeArrayRef(gc_store_args), false),
Function::ExternalLinkage,
"julia.gc_store", m);
add_named_global(gcstore_func, (void*)NULL, /*dllimport*/false);

jlcall_frame_func =
Function::Create(FunctionType::get(T_ppjlvalue, ArrayRef<Type*>(T_int32), false),
Function::ExternalLinkage,
Expand Down
4 changes: 4 additions & 0 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ void addOptimizationPasses(PassManager *PM)
# endif
#endif
if (jl_options.opt_level == 0) {
PM->add(createLowerPTLSPass(imaging_mode, tbaa_const));
return;
}
#ifdef LLVM37
Expand All @@ -140,6 +141,9 @@ void addOptimizationPasses(PassManager *PM)
#ifndef INSTCOMBINE_BUG
PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
#endif
// Let the InstCombine pass remove the unnecessary load of
// safepoint address first
PM->add(createLowerPTLSPass(imaging_mode, tbaa_const));
PM->add(createSROAPass()); // Break up aggregate allocas
#ifndef INSTCOMBINE_BUG
PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
Expand Down
4 changes: 4 additions & 0 deletions src/jitlayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,7 @@ JL_DLLEXPORT extern LLVMContext jl_LLVMContext;
#else
JL_DLLEXPORT extern LLVMContext &jl_LLVMContext;
#endif

extern MDNode *tbaa_const;

Pass *createLowerPTLSPass(bool imaging_mode, MDNode *tbaa_const);
Loading

0 comments on commit b27d520

Please sign in to comment.