diff --git a/base/essentials.jl b/base/essentials.jl index 2c51076fb6f80..6d37fa179c4dd 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -106,6 +106,10 @@ macro specialize(vars...) return Expr(:meta, :specialize, vars...) end +macro optlevel(n::Int) + return Expr(:meta, :optlevel, n) +end + macro _pure_meta() return Expr(:meta, :pure) end diff --git a/src/ast.c b/src/ast.c index 6fe579e594be8..0bc475989084a 100644 --- a/src/ast.c +++ b/src/ast.c @@ -62,6 +62,7 @@ jl_sym_t *throw_undef_if_not_sym; jl_sym_t *getfield_undefref_sym; jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym; jl_sym_t *coverageeffect_sym; jl_sym_t *escape_sym; jl_sym_t *aliasscope_sym; jl_sym_t *popaliasscope_sym; +jl_sym_t *optlevel_sym; static uint8_t flisp_system_image[] = { #include @@ -380,6 +381,7 @@ void jl_init_frontend(void) isdefined_sym = jl_symbol("isdefined"); nospecialize_sym = jl_symbol("nospecialize"); specialize_sym = jl_symbol("specialize"); + optlevel_sym = jl_symbol("optlevel"); macrocall_sym = jl_symbol("macrocall"); escape_sym = jl_symbol("escape"); hygienicscope_sym = jl_symbol("hygienic-scope"); diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index d1f1846d98a31..44bd5abc092df 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -87,7 +87,13 @@ void jl_add_code_in_flight(StringRef name, jl_code_instance_t *codeinst, const D { ncode_in_flight[mangle(name, DL)] = codeinst; } - +jl_code_instance_t *jl_get_code_in_flight(StringRef name) +{ + StringMap::iterator linfo_it = ncode_in_flight.find(name); + if (linfo_it != ncode_in_flight.end()) + return linfo_it->second; + return NULL; +} #ifdef _OS_WINDOWS_ #if defined(_CPU_X86_64_) diff --git a/src/dump.c b/src/dump.c index 27ebab33fc8ce..1a379ebc2faaf 100644 --- a/src/dump.c +++ b/src/dump.c @@ -476,6 +476,7 @@ static void jl_serialize_module(jl_serializer_state *s, jl_module_t *m) write_uint64(s->s, m->build_id); write_int32(s->s, m->counter); write_int32(s->s, m->nospecialize); + write_int32(s->s, m->optlevel); } static int is_ast_node(jl_value_t *v) @@ -1895,6 +1896,7 @@ static jl_value_t *jl_deserialize_value_module(jl_serializer_state *s) JL_GC_DIS m->build_id = read_uint64(s->s); m->counter = read_int32(s->s); m->nospecialize = read_int32(s->s); + m->optlevel = read_int32(s->s); m->primary_world = jl_world_counter; return (jl_value_t*)m; } diff --git a/src/interpreter.c b/src/interpreter.c index 81ddcfd84e6f6..dda96bb3f3cc8 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -798,6 +798,12 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, if (jl_expr_nargs(stmt) == 1 && jl_exprarg(stmt, 0) == (jl_value_t*)specialize_sym) { jl_set_module_nospecialize(s->module, 0); } + if (jl_expr_nargs(stmt) == 2 && jl_exprarg(stmt, 0) == (jl_value_t*)optlevel_sym) { + if (jl_is_long(jl_exprarg(stmt, 1))) { + int n = jl_unbox_long(jl_exprarg(stmt, 1)); + jl_set_module_optlevel(s->module, n); + } + } } else { eval_stmt_value(stmt, s); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index b3882e656413e..6fa6314e863ee 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -332,11 +332,39 @@ void JuliaOJIT::DebugObjectRegistrar::operator()(RTDyldObjHandleT H, static_cast(&LOS)); } +jl_code_instance_t *jl_get_code_in_flight(StringRef name); CompilerResultT JuliaOJIT::CompilerT::operator()(Module &M) { JL_TIMING(LLVM_OPT); - jit.PM.run(M); + int optlevel = -1; + jl_method_t *meth = NULL; + jl_method_instance_t *mi = NULL; + for (Module::iterator fs = M.begin(); fs != M.end(); ) { + Function &F = *fs; + if (!F.getBasicBlockList().empty()) { + jl_code_instance_t *codeinst = jl_get_code_in_flight(F.getName()); + if (codeinst) { + mi = codeinst->def; + if (jl_is_method(mi->def.value)) { + meth = mi->def.method; + if (meth->module->optlevel == 0) { + optlevel = 0; + break; + } + } + else { + mi = NULL; + } + } + } + ++fs; + } + if (optlevel == -1) + jit.PM.run(M); + else + jit.fastPM.run(M); + std::unique_ptr ObjBuffer( new SmallVectorMemoryBuffer(std::move(jit.ObjBufferSV))); auto Obj = object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); @@ -391,6 +419,11 @@ JuliaOJIT::JuliaOJIT(TargetMachine &TM) if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) llvm_unreachable("Target does not support MC emission."); + addTargetPasses(&fastPM, &TM); + addOptimizationPasses(&fastPM, 0); + if (TM.addPassesToEmitMC(fastPM, Ctx, ObjStream)) + llvm_unreachable("Target does not support MC emission."); + // Make sure SectionMemoryManager::getSymbolAddressInProcess can resolve // symbols in the program as well. The nullptr argument to the function // tells DynamicLibrary to load the program, not a library. diff --git a/src/jitlayers.h b/src/jitlayers.h index 8b049bd751479..d7e206fbf8669 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -151,6 +151,7 @@ class JuliaOJIT { SmallVector ObjBufferSV; raw_svector_ostream ObjStream; legacy::PassManager PM; + legacy::PassManager fastPM; MCContext *Ctx; std::shared_ptr MemMgr; DebugObjectRegistrar registrar; diff --git a/src/julia.h b/src/julia.h index 3f4da989fb45b..a80de61bed335 100644 --- a/src/julia.h +++ b/src/julia.h @@ -503,6 +503,7 @@ typedef struct _jl_module_t { size_t primary_world; uint32_t counter; int32_t nospecialize; // global bit flags: initialization for new methods + int32_t optlevel; uint8_t istopmod; jl_mutex_t lock; } jl_module_t; @@ -1471,6 +1472,7 @@ extern JL_DLLEXPORT jl_module_t *jl_base_module JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_module_t *jl_top_module JL_GLOBALLY_ROOTED; JL_DLLEXPORT jl_module_t *jl_new_module(jl_sym_t *name); JL_DLLEXPORT void jl_set_module_nospecialize(jl_module_t *self, int on); +JL_DLLEXPORT void jl_set_module_optlevel(jl_module_t *self, int lvl); // get binding for reading JL_DLLEXPORT jl_binding_t *jl_get_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); JL_DLLEXPORT jl_binding_t *jl_get_binding_or_error(jl_module_t *m, jl_sym_t *var); diff --git a/src/julia_internal.h b/src/julia_internal.h index a5c71774a6895..9c3c7f55648a6 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1151,6 +1151,7 @@ extern jl_sym_t *throw_undef_if_not_sym; extern jl_sym_t *getfield_undefref_sym; extern jl_sym_t *gc_preserve_begin_sym; extern jl_sym_t *gc_preserve_end_sym; extern jl_sym_t *failed_sym; extern jl_sym_t *done_sym; extern jl_sym_t *runnable_sym; extern jl_sym_t *coverageeffect_sym; extern jl_sym_t *escape_sym; +extern jl_sym_t *optlevel_sym; struct _jl_sysimg_fptrs_t; diff --git a/src/module.c b/src/module.c index 33e7afedc1696..4f8b1661f50aa 100644 --- a/src/module.c +++ b/src/module.c @@ -35,6 +35,7 @@ JL_DLLEXPORT jl_module_t *jl_new_module(jl_sym_t *name) m->primary_world = 0; m->counter = 1; m->nospecialize = 0; + m->optlevel = -1; JL_MUTEX_INIT(&m->lock); htable_new(&m->bindings, 0); arraylist_new(&m->usings, 0); @@ -72,6 +73,11 @@ JL_DLLEXPORT void jl_set_module_nospecialize(jl_module_t *self, int on) self->nospecialize = (on ? -1 : 0); } +JL_DLLEXPORT void jl_set_module_optlevel(jl_module_t *self, int lvl) +{ + self->optlevel = lvl; +} + JL_DLLEXPORT void jl_set_istopmod(jl_module_t *self, uint8_t isprimary) { self->istopmod = 1;