@@ -442,62 +442,100 @@ static void jl_do_dump_compile(jl_code_instance_t *codeinst, uint64_t time)
442442 julia_double_to_half (orig_time + time * 1e-9 ));
443443}
444444
445+ static constexpr size_t N_optlevels = 4 ;
446+
447+ static int jl_clamp_optlevel (int requested) JL_NOTSAFEPOINT
448+ {
449+ int opt_level = std::max (static_cast <int >(jl_options.opt_level ), 0 );
450+ if (requested >= 0 && requested < opt_level)
451+ opt_level = requested;
452+ int opt_level_min = std::max (static_cast <int >(jl_options.opt_level_min ), 0 );
453+ if (opt_level < opt_level_min)
454+ opt_level = opt_level_min;
455+ return std::min (opt_level, static_cast <int >(N_optlevels) - 1 );
456+ }
457+
458+ static int jl_codeinst_optlevel (jl_code_instance_t *ci) JL_NOTSAFEPOINT
459+ {
460+ jl_method_instance_t *mi = jl_get_ci_mi (ci);
461+ jl_value_t *def = mi->def .value ;
462+ int raw = jl_get_module_optlevel (jl_is_method (def) ? ((jl_method_t *)def)->module
463+ : mi->def .module );
464+ return jl_clamp_optlevel (raw);
465+ }
466+
445467extern " C" JL_DLLEXPORT_CODEGEN void
446468jl_emit_codeinsts_to_jit_impl (jl_code_instance_t **codeinsts, jl_code_info_t **srcs, int len)
447469{
448470 if (len == 0 )
449471 return ;
450472
451473 JL_TIMING (CODEINST_COMPILE , CODEINST_COMPILE );
452- const char *name = name_from_method_instance (jl_get_ci_mi (codeinsts[len - 1 ]));
453- auto ctx = std::make_unique<LLVMContext>();
454- auto &dl = jl_ExecutionEngine->getDataLayout ();
455- auto &tt = jl_ExecutionEngine->getTargetTriple ();
456- auto mod = jl_create_llvm_module (name, *ctx, dl, tt);
457- jl_codegen_output_t out{*mod};
458- out.get_context ().setDiscardValueNames (true );
459- out.imaging_mode = false ;
460- JL_GC_PUSH1 (&out.temporary_roots );
461474
475+ // Partition the batch by effective optimization level and emit each group as
476+ // its own LLVM module.
477+ std::map<int , SmallVector<int , 0 >> groups;
462478 for (int i = 0 ; i < len; ++i) {
463- jl_code_instance_t *codeinst = codeinsts[i];
464- jl_code_info_t *src = srcs[i];
465- jl_method_instance_t *mi = jl_get_ci_mi (codeinst);
466-
467- if (jl_atomic_load_relaxed (&codeinst->invoke ))
468- continue ;
479+ if (jl_atomic_load_relaxed (&codeinsts[i]->invoke ))
480+ continue ; // already compiled
481+ groups[jl_codeinst_optlevel (codeinsts[i])].push_back (i);
482+ }
483+
484+ for (auto &group : groups) {
485+ SmallVector<int , 0 > &idxs = group.second ;
486+ const char *name = name_from_method_instance (jl_get_ci_mi (codeinsts[idxs.back ()]));
487+ auto ctx = std::make_unique<LLVMContext>();
488+ auto &dl = jl_ExecutionEngine->getDataLayout ();
489+ auto &tt = jl_ExecutionEngine->getTargetTriple ();
490+ auto mod = jl_create_llvm_module (name, *ctx, dl, tt);
491+ jl_codegen_output_t out{*mod};
492+ out.get_context ().setDiscardValueNames (true );
493+ out.imaging_mode = false ;
494+ JL_GC_PUSH1 (&out.temporary_roots );
495+
496+ bool failed = false ;
497+ for (int i : idxs) {
498+ jl_code_instance_t *codeinst = codeinsts[i];
499+ jl_code_info_t *src = srcs[i];
500+ jl_method_instance_t *mi = jl_get_ci_mi (codeinst);
501+
502+ if (jl_atomic_load_relaxed (&codeinst->invoke ))
503+ continue ;
469504
470- out.temporary_roots = jl_alloc_array_1d (jl_array_any_type, 0 );
471- out.temporary_roots_set .clear ();
472- if (!jl_emit_codeinst (out, codeinst, src)) { // contains safepoints
473- JL_GC_POP () ;
474- return ;
475- }
505+ out.temporary_roots = jl_alloc_array_1d (jl_array_any_type, 0 );
506+ out.temporary_roots_set .clear ();
507+ if (!jl_emit_codeinst (out, codeinst, src)) { // contains safepoints
508+ failed = true ;
509+ break ;
510+ }
476511
477- // contains safepoints
478- jl_promote_method_roots (out, mi);
479- emit_always_inline (out, jl_get_method_ir); // contains safepoints
512+ // contains safepoints
513+ jl_promote_method_roots (out, mi);
514+ emit_always_inline (out, jl_get_method_ir); // contains safepoints
480515
481- // Non-opaque-closure MethodInstances are considered globally rooted
482- // through their methods, but for OC, we need to create a global root
483- // here.
484- if (jl_is_method (mi->def .value ) && mi->def .method ->is_for_opaque_closure )
485- jl_as_global_root ((jl_value_t *)mi, 1 );
486- }
516+ // Non-opaque-closure MethodInstances are considered globally rooted
517+ // through their methods, but for OC, we need to create a global root
518+ // here.
519+ if (jl_is_method (mi->def .value ) && mi->def .method ->is_for_opaque_closure )
520+ jl_as_global_root ((jl_value_t *)mi, 1 );
521+ }
487522
488- out.temporary_roots = nullptr ;
489- out.temporary_roots_set .clear ();
490- JL_GC_POP ();
523+ out.temporary_roots = nullptr ;
524+ out.temporary_roots_set .clear ();
525+ JL_GC_POP ();
491526
492- if (out.ci_funcs .empty ())
493- return ;
527+ if (failed)
528+ return ;
529+ if (out.ci_funcs .empty ())
530+ continue ;
494531
495- emit_llvmcall_modules (out);
532+ emit_llvmcall_modules (out);
496533
497- auto &ES = jl_ExecutionEngine->getExecutionSession ();
498- jl_emitted_output_t emitted =
499- out.finish (std::move (ctx), std::move (mod), *ES .getSymbolStringPool ());
500- jl_ExecutionEngine->addOutput (std::move (emitted));
534+ auto &ES = jl_ExecutionEngine->getExecutionSession ();
535+ jl_emitted_output_t emitted =
536+ out.finish (std::move (ctx), std::move (mod), *ES .getSymbolStringPool ());
537+ jl_ExecutionEngine->addOutput (std::move (emitted));
538+ }
501539}
502540
503541extern " C" JL_DLLEXPORT_CODEGEN
@@ -625,32 +663,26 @@ static auto countBasicBlocks(const Function &F) JL_NOTSAFEPOINT
625663 return std::distance (F.begin (), F.end ());
626664}
627665
628- static constexpr size_t N_optlevels = 4 ;
629-
630666static void selectOptLevel (Module &M) JL_NOTSAFEPOINT {
631- size_t opt_level = std::max (static_cast <int >(jl_options.opt_level ), 0 );
632- do {
633- if (jl_generating_output ()) {
634- opt_level = 0 ;
635- break ;
636- }
637- size_t opt_level_min = std::max (static_cast <int >(jl_options.opt_level_min ), 0 );
667+ size_t opt_level;
668+ if (jl_generating_output ()) {
669+ opt_level = 0 ;
670+ }
671+ else {
672+ int requested = -1 ;
638673 for (auto &F : M) {
639674 if (!F.isDeclaration ()) {
640675 Attribute attr = F.getFnAttribute (" julia-optimization-level" );
641676 StringRef val = attr.getValueAsString ();
642677 if (val != " " ) {
643- size_t ol = (size_t )val[0 ] - ' 0' ;
644- if (ol < opt_level )
645- opt_level = ol;
678+ int ol = (int )val[0 ] - ' 0' ;
679+ if (ol >= 0 && (requested < 0 || ol < requested) )
680+ requested = ol;
646681 }
647682 }
648683 }
649- if (opt_level < opt_level_min)
650- opt_level = opt_level_min;
651- } while (0 );
652- // currently -O3 is max
653- opt_level = std::min (opt_level, N_optlevels - 1 );
684+ opt_level = jl_clamp_optlevel (requested);
685+ }
654686 M.addModuleFlag (Module::Warning, " julia.optlevel" , opt_level);
655687}
656688
0 commit comments