@@ -494,58 +494,6 @@ static auto countBasicBlocks(const Function &F)
494
494
return std::distance (F.begin (), F.end ());
495
495
}
496
496
497
- OptimizerResultT JuliaOJIT::OptimizerT::operator ()(orc::ThreadSafeModule TSM, orc::MaterializationResponsibility &R) {
498
- TSM.withModuleDo ([&](Module &M) {
499
- uint64_t start_time = 0 ;
500
- if (dump_llvm_opt_stream != NULL ) {
501
- // Print LLVM function statistics _before_ optimization
502
- // Print all the information about this invocation as a YAML object
503
- jl_printf (dump_llvm_opt_stream, " - \n " );
504
- // We print the name and some statistics for each function in the module, both
505
- // before optimization and again afterwards.
506
- jl_printf (dump_llvm_opt_stream, " before: \n " );
507
- for (auto &F : M.functions ()) {
508
- if (F.isDeclaration () || F.getName ().startswith (" jfptr_" )) {
509
- continue ;
510
- }
511
- // Each function is printed as a YAML object with several attributes
512
- jl_printf (dump_llvm_opt_stream, " \" %s\" :\n " , F.getName ().str ().c_str ());
513
- jl_printf (dump_llvm_opt_stream, " instructions: %u\n " , F.getInstructionCount ());
514
- jl_printf (dump_llvm_opt_stream, " basicblocks: %lu\n " , countBasicBlocks (F));
515
- }
516
-
517
- start_time = jl_hrtime ();
518
- }
519
-
520
- JL_TIMING (LLVM_OPT);
521
-
522
- {
523
- // Lock around our pass manager
524
- std::lock_guard<std::mutex> lock (this ->mutex );
525
- PM.run (M);
526
- }
527
-
528
- uint64_t end_time = 0 ;
529
- if (dump_llvm_opt_stream != NULL ) {
530
- end_time = jl_hrtime ();
531
- jl_printf (dump_llvm_opt_stream, " time_ns: %" PRIu64 " \n " , end_time - start_time);
532
- jl_printf (dump_llvm_opt_stream, " optlevel: %d\n " , optlevel);
533
-
534
- // Print LLVM function statistics _after_ optimization
535
- jl_printf (dump_llvm_opt_stream, " after: \n " );
536
- for (auto &F : M.functions ()) {
537
- if (F.isDeclaration () || F.getName ().startswith (" jfptr_" )) {
538
- continue ;
539
- }
540
- jl_printf (dump_llvm_opt_stream, " \" %s\" :\n " , F.getName ().str ().c_str ());
541
- jl_printf (dump_llvm_opt_stream, " instructions: %u\n " , F.getInstructionCount ());
542
- jl_printf (dump_llvm_opt_stream, " basicblocks: %lu\n " , countBasicBlocks (F));
543
- }
544
- }
545
- });
546
- return Expected<orc::ThreadSafeModule>{std::move (TSM)};
547
- }
548
-
549
497
void JuliaOJIT::OptSelLayerT::emit (std::unique_ptr<orc::MaterializationResponsibility> R, orc::ThreadSafeModule TSM) {
550
498
size_t optlevel = ~0ull ;
551
499
TSM.withModuleDo ([&](Module &M) {
@@ -570,7 +518,7 @@ void JuliaOJIT::OptSelLayerT::emit(std::unique_ptr<orc::MaterializationResponsib
570
518
}
571
519
});
572
520
assert (optlevel != ~0ull && " Failed to select a valid optimization level!" );
573
- this ->optimizers [optlevel].emit (std::move (R), std::move (TSM));
521
+ this ->optimizers [optlevel]-> OptimizeLayer .emit (std::move (R), std::move (TSM));
574
522
}
575
523
576
524
void jl_register_jit_object (const object::ObjectFile &debugObj,
@@ -911,6 +859,106 @@ namespace {
911
859
.setCodeModel (TM.getCodeModel ())
912
860
.setCodeGenOptLevel (CodeGenOptLevelFor (optlevel));
913
861
}
862
+
863
+ struct TMCreator {
864
+ orc::JITTargetMachineBuilder JTMB;
865
+
866
+ TMCreator (TargetMachine &TM, int optlevel) : JTMB(createJTMBFromTM(TM, optlevel)) {}
867
+
868
+ std::unique_ptr<TargetMachine> operator ()() {
869
+ return cantFail (JTMB.createTargetMachine ());
870
+ }
871
+ };
872
+
873
+ struct PMCreator {
874
+ std::unique_ptr<TargetMachine> TM;
875
+ int optlevel;
876
+ PMCreator (TargetMachine &TM, int optlevel) : TM(cantFail(createJTMBFromTM(TM, optlevel).createTargetMachine())), optlevel(optlevel) {}
877
+ PMCreator (const PMCreator &other) : PMCreator(*other.TM, other.optlevel) {}
878
+ PMCreator (PMCreator &&other) : TM(std::move(other.TM)), optlevel(other.optlevel) {}
879
+ friend void swap (PMCreator &self, PMCreator &other) {
880
+ using std::swap;
881
+ swap (self.TM , other.TM );
882
+ swap (self.optlevel , other.optlevel );
883
+ }
884
+ PMCreator &operator =(PMCreator other) {
885
+ swap (*this , other);
886
+ return *this ;
887
+ }
888
+ std::unique_ptr<legacy::PassManager> operator ()() {
889
+ auto PM = std::make_unique<legacy::PassManager>();
890
+ addPassesForOptLevel (*PM, *TM, optlevel);
891
+ return PM;
892
+ }
893
+ };
894
+
895
+ struct OptimizerT {
896
+ OptimizerT (TargetMachine &TM, int optlevel) : optlevel(optlevel), PMs(PMCreator(TM, optlevel)) {}
897
+
898
+ OptimizerResultT operator ()(orc::ThreadSafeModule TSM, orc::MaterializationResponsibility &R) {
899
+ TSM.withModuleDo ([&](Module &M) {
900
+ uint64_t start_time = 0 ;
901
+ if (dump_llvm_opt_stream != NULL ) {
902
+ // Print LLVM function statistics _before_ optimization
903
+ // Print all the information about this invocation as a YAML object
904
+ jl_printf (dump_llvm_opt_stream, " - \n " );
905
+ // We print the name and some statistics for each function in the module, both
906
+ // before optimization and again afterwards.
907
+ jl_printf (dump_llvm_opt_stream, " before: \n " );
908
+ for (auto &F : M.functions ()) {
909
+ if (F.isDeclaration () || F.getName ().startswith (" jfptr_" )) {
910
+ continue ;
911
+ }
912
+ // Each function is printed as a YAML object with several attributes
913
+ jl_printf (dump_llvm_opt_stream, " \" %s\" :\n " , F.getName ().str ().c_str ());
914
+ jl_printf (dump_llvm_opt_stream, " instructions: %u\n " , F.getInstructionCount ());
915
+ jl_printf (dump_llvm_opt_stream, " basicblocks: %lu\n " , countBasicBlocks (F));
916
+ }
917
+
918
+ start_time = jl_hrtime ();
919
+ }
920
+
921
+ JL_TIMING (LLVM_OPT);
922
+
923
+ // Run the optimization
924
+ (***PMs).run (M);
925
+
926
+ uint64_t end_time = 0 ;
927
+ if (dump_llvm_opt_stream != NULL ) {
928
+ end_time = jl_hrtime ();
929
+ jl_printf (dump_llvm_opt_stream, " time_ns: %" PRIu64 " \n " , end_time - start_time);
930
+ jl_printf (dump_llvm_opt_stream, " optlevel: %d\n " , optlevel);
931
+
932
+ // Print LLVM function statistics _after_ optimization
933
+ jl_printf (dump_llvm_opt_stream, " after: \n " );
934
+ for (auto &F : M.functions ()) {
935
+ if (F.isDeclaration () || F.getName ().startswith (" jfptr_" )) {
936
+ continue ;
937
+ }
938
+ jl_printf (dump_llvm_opt_stream, " \" %s\" :\n " , F.getName ().str ().c_str ());
939
+ jl_printf (dump_llvm_opt_stream, " instructions: %u\n " , F.getInstructionCount ());
940
+ jl_printf (dump_llvm_opt_stream, " basicblocks: %lu\n " , countBasicBlocks (F));
941
+ }
942
+ }
943
+ });
944
+ return Expected<orc::ThreadSafeModule>{std::move (TSM)};
945
+ }
946
+ private:
947
+ int optlevel;
948
+ JuliaOJIT::ResourcePool<std::unique_ptr<legacy::PassManager>> PMs;
949
+ };
950
+
951
+ struct CompilerT : orc::IRCompileLayer::IRCompiler {
952
+
953
+ CompilerT (orc::IRSymbolMapper::ManglingOptions MO, TargetMachine &TM, int optlevel)
954
+ : orc::IRCompileLayer::IRCompiler(MO), TMs(TMCreator(TM, optlevel)) {}
955
+
956
+ Expected<std::unique_ptr<MemoryBuffer>> operator ()(Module &M) override {
957
+ return orc::SimpleCompiler (***TMs)(M);
958
+ }
959
+
960
+ JuliaOJIT::ResourcePool<std::unique_ptr<TargetMachine>> TMs;
961
+ };
914
962
}
915
963
916
964
llvm::DataLayout jl_create_datalayout (TargetMachine &TM) {
@@ -920,15 +968,14 @@ llvm::DataLayout jl_create_datalayout(TargetMachine &TM) {
920
968
return jl_data_layout;
921
969
}
922
970
971
+ JuliaOJIT::PipelineT::PipelineT (orc::ObjectLayer &BaseLayer, TargetMachine &TM, int optlevel)
972
+ : CompileLayer(BaseLayer.getExecutionSession(), BaseLayer,
973
+ std::make_unique<CompilerT>(orc::irManglingOptionsFromTargetOptions(TM.Options), TM, optlevel)),
974
+ OptimizeLayer(CompileLayer.getExecutionSession(), CompileLayer, OptimizerT(TM, optlevel)) {}
975
+
923
976
JuliaOJIT::JuliaOJIT ()
924
977
: TM(createTargetMachine()),
925
978
DL(jl_create_datalayout(*TM)),
926
- TMs{
927
- cantFail (createJTMBFromTM (*TM, 0 ).createTargetMachine ()),
928
- cantFail (createJTMBFromTM (*TM, 1 ).createTargetMachine ()),
929
- cantFail (createJTMBFromTM (*TM, 2 ).createTargetMachine ()),
930
- cantFail (createJTMBFromTM (*TM, 3 ).createTargetMachine ())
931
- },
932
979
#if JL_LLVM_VERSION >= 130000
933
980
ES (cantFail(orc::SelfExecutorProcessControl::Create())),
934
981
#else
@@ -955,17 +1002,13 @@ JuliaOJIT::JuliaOJIT()
955
1002
}
956
1003
),
957
1004
#endif
958
- CompileLayer0 (ES, ObjectLayer, std::make_unique<orc::ConcurrentIRCompiler>(createJTMBFromTM(*TM, 0 ))),
959
- CompileLayer1(ES, ObjectLayer, std::make_unique<orc::ConcurrentIRCompiler>(createJTMBFromTM(*TM, 1 ))),
960
- CompileLayer2(ES, ObjectLayer, std::make_unique<orc::ConcurrentIRCompiler>(createJTMBFromTM(*TM, 2 ))),
961
- CompileLayer3(ES, ObjectLayer, std::make_unique<orc::ConcurrentIRCompiler>(createJTMBFromTM(*TM, 3 ))),
962
- OptimizeLayers{
963
- {ES, CompileLayer0, OptimizerT (PM0, PM_mutexes[0 ], 0 )},
964
- {ES, CompileLayer1, OptimizerT (PM1, PM_mutexes[1 ], 1 )},
965
- {ES, CompileLayer2, OptimizerT (PM2, PM_mutexes[2 ], 2 )},
966
- {ES, CompileLayer3, OptimizerT (PM3, PM_mutexes[3 ], 3 )},
1005
+ Pipelines{
1006
+ std::make_unique<PipelineT>(ObjectLayer, *TM, 0 ),
1007
+ std::make_unique<PipelineT>(ObjectLayer, *TM, 1 ),
1008
+ std::make_unique<PipelineT>(ObjectLayer, *TM, 2 ),
1009
+ std::make_unique<PipelineT>(ObjectLayer, *TM, 3 ),
967
1010
},
968
- OptSelLayer (OptimizeLayers )
1011
+ OptSelLayer (Pipelines )
969
1012
{
970
1013
#ifdef JL_USE_JITLINK
971
1014
# if defined(_OS_DARWIN_) && defined(LLVM_SHLIB)
@@ -987,10 +1030,6 @@ JuliaOJIT::JuliaOJIT()
987
1030
registerRTDyldJITObject (Object, LO, MemMgr);
988
1031
});
989
1032
#endif
990
- addPassesForOptLevel (PM0, *TMs[0 ], 0 );
991
- addPassesForOptLevel (PM1, *TMs[1 ], 1 );
992
- addPassesForOptLevel (PM2, *TMs[2 ], 2 );
993
- addPassesForOptLevel (PM3, *TMs[3 ], 3 );
994
1033
995
1034
// Make sure SectionMemoryManager::getSymbolAddressInProcess can resolve
996
1035
// symbols in the program as well. The nullptr argument to the function
0 commit comments