@@ -112,6 +112,7 @@ static std::list<claimed_file> Modules;
112
112
static StringMap<ResolutionInfo> ResInfo;
113
113
static std::vector<std::string> Cleanup;
114
114
static llvm::TargetOptions TargetOpts;
115
+ static std::string DefaultTriple = sys::getDefaultTargetTriple();
115
116
116
117
namespace options {
117
118
enum OutputType {
@@ -123,7 +124,10 @@ namespace options {
123
124
static bool generate_api_file = false ;
124
125
static OutputType TheOutputType = OT_NORMAL;
125
126
static unsigned OptLevel = 2 ;
126
- static unsigned Parallelism = 1 ;
127
+ // Default parallelism of 0 used to indicate that user did not specify.
128
+ // Actual parallelism default value depends on implementation.
129
+ // Currently, code generation defaults to no parallelism.
130
+ static unsigned Parallelism = 0 ;
127
131
#ifdef NDEBUG
128
132
static bool DisableVerify = true ;
129
133
#else
@@ -568,8 +572,8 @@ static void freeSymName(ld_plugin_symbol &Sym) {
568
572
Sym.comdat_key = nullptr ;
569
573
}
570
574
571
- static std::unique_ptr<FunctionInfoIndex>
572
- getFunctionIndexForFile (claimed_file &F, ld_plugin_input_file &Info ) {
575
+ // / Helper to get a file's symbols and a view into it via gold callbacks.
576
+ static const void * getSymbolsAndView (claimed_file &F) {
573
577
ld_plugin_status status = get_symbols (F.handle , F.syms .size (), &F.syms [0 ]);
574
578
if (status == LDPS_NO_SYMS)
575
579
return nullptr ;
@@ -581,6 +585,13 @@ getFunctionIndexForFile(claimed_file &F, ld_plugin_input_file &Info) {
581
585
if (get_view (F.handle , &View) != LDPS_OK)
582
586
message (LDPL_FATAL, " Failed to get a view of file" );
583
587
588
+ return View;
589
+ }
590
+
591
+ static std::unique_ptr<FunctionInfoIndex>
592
+ getFunctionIndexForFile (claimed_file &F, ld_plugin_input_file &Info) {
593
+ const void *View = getSymbolsAndView (F);
594
+
584
595
MemoryBufferRef BufferRef (StringRef ((const char *)View, Info.filesize ),
585
596
Info.name );
586
597
@@ -603,22 +614,10 @@ getFunctionIndexForFile(claimed_file &F, ld_plugin_input_file &Info) {
603
614
}
604
615
605
616
static std::unique_ptr<Module>
606
- getModuleForFile (LLVMContext &Context, claimed_file &F,
617
+ getModuleForFile (LLVMContext &Context, claimed_file &F, const void *View,
607
618
ld_plugin_input_file &Info, raw_fd_ostream *ApiFile,
608
619
StringSet<> &Internalize, StringSet<> &Maybe,
609
620
std::vector<GlobalValue *> &Keep) {
610
-
611
- ld_plugin_status status = get_symbols (F.handle , F.syms .size (), F.syms .data ());
612
- if (status == LDPS_NO_SYMS)
613
- return nullptr ;
614
-
615
- if (status != LDPS_OK)
616
- message (LDPL_FATAL, " Failed to get symbol information" );
617
-
618
- const void *View;
619
- if (get_view (F.handle , &View) != LDPS_OK)
620
- message (LDPL_FATAL, " Failed to get a view of file" );
621
-
622
621
MemoryBufferRef BufferRef (StringRef ((const char *)View, Info.filesize ),
623
622
Info.name );
624
623
ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
@@ -745,26 +744,6 @@ getModuleForFile(LLVMContext &Context, claimed_file &F,
745
744
return Obj.takeModule ();
746
745
}
747
746
748
- static void runLTOPasses (Module &M, TargetMachine &TM) {
749
- M.setDataLayout (TM.createDataLayout ());
750
-
751
- legacy::PassManager passes;
752
- passes.add (createTargetTransformInfoWrapperPass (TM.getTargetIRAnalysis ()));
753
-
754
- PassManagerBuilder PMB;
755
- PMB.LibraryInfo = new TargetLibraryInfoImpl (Triple (TM.getTargetTriple ()));
756
- PMB.Inliner = createFunctionInliningPass ();
757
- // Unconditionally verify input since it is not verified before this
758
- // point and has unknown origin.
759
- PMB.VerifyInput = true ;
760
- PMB.VerifyOutput = !options::DisableVerify;
761
- PMB.LoopVectorize = true ;
762
- PMB.SLPVectorize = true ;
763
- PMB.OptLevel = options::OptLevel;
764
- PMB.populateLTOPassManager (passes);
765
- passes.run (M);
766
- }
767
-
768
747
static void saveBCFile (StringRef Path, Module &M) {
769
748
std::error_code EC;
770
749
raw_fd_ostream OS (Path, EC, sys::fs::OpenFlags::F_None);
@@ -773,24 +752,56 @@ static void saveBCFile(StringRef Path, Module &M) {
773
752
WriteBitcodeToFile (&M, OS, /* ShouldPreserveUseListOrder */ false );
774
753
}
775
754
776
- static void codegen (std::unique_ptr<Module> M) {
777
- const std::string &TripleStr = M->getTargetTriple ();
778
- Triple TheTriple (TripleStr);
755
+ static void recordFile (std::string Filename, bool TempOutFile) {
756
+ if (add_input_file (Filename.c_str ()) != LDPS_OK)
757
+ message (LDPL_FATAL,
758
+ " Unable to add .o file to the link. File left behind in: %s" ,
759
+ Filename.c_str ());
760
+ if (TempOutFile)
761
+ Cleanup.push_back (Filename.c_str ());
762
+ }
779
763
780
- std::string ErrMsg;
781
- const Target *TheTarget = TargetRegistry::lookupTarget (TripleStr, ErrMsg);
782
- if (!TheTarget)
783
- message (LDPL_FATAL, " Target not found: %s" , ErrMsg.c_str ());
764
+ namespace {
765
+ // / Class to manage optimization and code generation for a module.
766
+ class CodeGen {
767
+ // / The module for which this will generate code.
768
+ std::unique_ptr<llvm::Module> M;
769
+
770
+ // / The target machine for generating code for this module.
771
+ std::unique_ptr<TargetMachine> TM;
772
+
773
+ public:
774
+ // / Constructor used by full LTO.
775
+ CodeGen (std::unique_ptr<llvm::Module> M) : M(std::move(M)) {
776
+ initTargetMachine ();
777
+ }
784
778
785
- if (unsigned NumOpts = options::extra.size ())
786
- cl::ParseCommandLineOptions (NumOpts, &options::extra[0 ]);
779
+ // / Invoke LTO passes and the code generator for the module.
780
+ void runAll ();
781
+
782
+ private:
783
+ // / Create a target machine for the module. Must be unique for each
784
+ // / module/task.
785
+ void initTargetMachine ();
786
+
787
+ // / Run all LTO passes on the module.
788
+ void runLTOPasses ();
789
+
790
+ // / Sets up output files necessary to perform optional multi-threaded
791
+ // / split code generation, and invokes the code generation implementation.
792
+ void runSplitCodeGen ();
793
+ };
794
+ }
787
795
796
+ static SubtargetFeatures getFeatures (Triple &TheTriple) {
788
797
SubtargetFeatures Features;
789
798
Features.getDefaultSubtargetFeatures (TheTriple);
790
799
for (const std::string &A : MAttrs)
791
800
Features.AddFeature (A);
801
+ return Features;
802
+ }
792
803
793
- TargetOptions Options = InitTargetOptionsFromCodeGenFlags ();
804
+ static CodeGenOpt::Level getCGOptLevel () {
794
805
CodeGenOpt::Level CGOptLevel;
795
806
switch (options::OptLevel) {
796
807
case 0 :
@@ -806,62 +817,146 @@ static void codegen(std::unique_ptr<Module> M) {
806
817
CGOptLevel = CodeGenOpt::Aggressive;
807
818
break ;
808
819
}
809
- std::unique_ptr<TargetMachine> TM (TheTarget->createTargetMachine (
820
+ return CGOptLevel;
821
+ }
822
+
823
+ void CodeGen::initTargetMachine () {
824
+ const std::string &TripleStr = M->getTargetTriple ();
825
+ Triple TheTriple (TripleStr);
826
+
827
+ std::string ErrMsg;
828
+ const Target *TheTarget = TargetRegistry::lookupTarget (TripleStr, ErrMsg);
829
+ if (!TheTarget)
830
+ message (LDPL_FATAL, " Target not found: %s" , ErrMsg.c_str ());
831
+
832
+ SubtargetFeatures Features = getFeatures (TheTriple);
833
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags ();
834
+ CodeGenOpt::Level CGOptLevel = getCGOptLevel ();
835
+
836
+ TM.reset (TheTarget->createTargetMachine (
810
837
TripleStr, options::mcpu, Features.getString (), Options, RelocationModel,
811
838
CodeModel::Default, CGOptLevel));
839
+ }
812
840
813
- runLTOPasses (*M, *TM);
841
+ void CodeGen::runLTOPasses () {
842
+ M->setDataLayout (TM->createDataLayout ());
814
843
815
- if (options::TheOutputType == options::OT_SAVE_TEMPS)
816
- saveBCFile (output_name + " .opt.bc" , *M);
844
+ legacy::PassManager passes;
845
+ passes.add (createTargetTransformInfoWrapperPass (TM->getTargetIRAnalysis ()));
846
+
847
+ PassManagerBuilder PMB;
848
+ PMB.LibraryInfo = new TargetLibraryInfoImpl (Triple (TM->getTargetTriple ()));
849
+ PMB.Inliner = createFunctionInliningPass ();
850
+ // Unconditionally verify input since it is not verified before this
851
+ // point and has unknown origin.
852
+ PMB.VerifyInput = true ;
853
+ PMB.VerifyOutput = !options::DisableVerify;
854
+ PMB.LoopVectorize = true ;
855
+ PMB.SLPVectorize = true ;
856
+ PMB.OptLevel = options::OptLevel;
857
+ PMB.populateLTOPassManager (passes);
858
+ passes.run (*M);
859
+ }
860
+
861
+ // / Open a file and return the new file descriptor given a base input
862
+ // / file name, a flag indicating whether a temp file should be generated,
863
+ // / and an optional task id. The new filename generated is
864
+ // / returned in \p NewFilename.
865
+ static int openOutputFile (SmallString<128 > InFilename, bool TempOutFile,
866
+ SmallString<128 > &NewFilename, int TaskID = -1 ) {
867
+ int FD;
868
+ if (TempOutFile) {
869
+ std::error_code EC =
870
+ sys::fs::createTemporaryFile (" lto-llvm" , " o" , FD, NewFilename);
871
+ if (EC)
872
+ message (LDPL_FATAL, " Could not create temporary file: %s" ,
873
+ EC.message ().c_str ());
874
+ } else {
875
+ NewFilename = InFilename;
876
+ if (TaskID >= 0 )
877
+ NewFilename += utostr (TaskID);
878
+ std::error_code EC =
879
+ sys::fs::openFileForWrite (NewFilename, FD, sys::fs::F_None);
880
+ if (EC)
881
+ message (LDPL_FATAL, " Could not open file: %s" , EC.message ().c_str ());
882
+ }
883
+ return FD;
884
+ }
885
+
886
+ void CodeGen::runSplitCodeGen () {
887
+ const std::string &TripleStr = M->getTargetTriple ();
888
+ Triple TheTriple (TripleStr);
889
+
890
+ SubtargetFeatures Features = getFeatures (TheTriple);
891
+
892
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags ();
893
+ CodeGenOpt::Level CGOptLevel = getCGOptLevel ();
817
894
818
895
SmallString<128 > Filename;
896
+ // Note that openOutputFile will append a unique ID for each task
819
897
if (!options::obj_path.empty ())
820
898
Filename = options::obj_path;
821
899
else if (options::TheOutputType == options::OT_SAVE_TEMPS)
822
900
Filename = output_name + " .o" ;
823
901
824
- std::vector<SmallString<128 >> Filenames (options::Parallelism);
902
+ // Note that the default parallelism is 1 instead of the
903
+ // hardware_concurrency, as there are behavioral differences between
904
+ // parallelism levels (e.g. symbol ordering will be different, and some uses
905
+ // of inline asm currently have issues with parallelism >1).
906
+ unsigned int MaxThreads = options::Parallelism ? options::Parallelism : 1 ;
907
+
908
+ std::vector<SmallString<128 >> Filenames (MaxThreads);
825
909
bool TempOutFile = Filename.empty ();
826
910
{
827
- // Open a file descriptor for each backend thread . This is done in a block
911
+ // Open a file descriptor for each backend task . This is done in a block
828
912
// so that the output file descriptors are closed before gold opens them.
829
913
std::list<llvm::raw_fd_ostream> OSs;
830
- std::vector<llvm::raw_pwrite_stream *> OSPtrs (options::Parallelism);
831
- for (unsigned I = 0 ; I != options::Parallelism; ++I) {
832
- int FD;
833
- if (TempOutFile) {
834
- std::error_code EC =
835
- sys::fs::createTemporaryFile (" lto-llvm" , " o" , FD, Filenames[I]);
836
- if (EC)
837
- message (LDPL_FATAL, " Could not create temporary file: %s" ,
838
- EC.message ().c_str ());
839
- } else {
840
- Filenames[I] = Filename;
841
- if (options::Parallelism != 1 )
842
- Filenames[I] += utostr (I);
843
- std::error_code EC =
844
- sys::fs::openFileForWrite (Filenames[I], FD, sys::fs::F_None);
845
- if (EC)
846
- message (LDPL_FATAL, " Could not open file: %s" , EC.message ().c_str ());
847
- }
914
+ std::vector<llvm::raw_pwrite_stream *> OSPtrs (MaxThreads);
915
+ for (unsigned I = 0 ; I != MaxThreads; ++I) {
916
+ int FD = openOutputFile (Filename, TempOutFile, Filenames[I], I);
848
917
OSs.emplace_back (FD, true );
849
918
OSPtrs[I] = &OSs.back ();
850
919
}
851
920
852
- // Run backend threads .
921
+ // Run backend tasks .
853
922
splitCodeGen (std::move (M), OSPtrs, options::mcpu, Features.getString (),
854
923
Options, RelocationModel, CodeModel::Default, CGOptLevel);
855
924
}
856
925
857
- for (auto &Filename : Filenames) {
858
- if (add_input_file (Filename.c_str ()) != LDPS_OK)
859
- message (LDPL_FATAL,
860
- " Unable to add .o file to the link. File left behind in: %s" ,
861
- Filename.c_str ());
862
- if (TempOutFile)
863
- Cleanup.push_back (Filename.c_str ());
926
+ for (auto &Filename : Filenames)
927
+ recordFile (Filename.c_str (), TempOutFile);
928
+ }
929
+
930
+ void CodeGen::runAll () {
931
+ runLTOPasses ();
932
+
933
+ if (options::TheOutputType == options::OT_SAVE_TEMPS) {
934
+ saveBCFile (output_name + " .opt.bc" , *M);
864
935
}
936
+
937
+ runSplitCodeGen ();
938
+ }
939
+
940
+ // / Links the module in \p View from file \p F into the combined module
941
+ // / saved in the IRMover \p L. Returns true on error, false on success.
942
+ static bool linkInModule (LLVMContext &Context, IRMover &L, claimed_file &F,
943
+ const void *View, ld_plugin_input_file &File,
944
+ raw_fd_ostream *ApiFile, StringSet<> &Internalize,
945
+ StringSet<> &Maybe) {
946
+ std::vector<GlobalValue *> Keep;
947
+ std::unique_ptr<Module> M = getModuleForFile (Context, F, View, File, ApiFile,
948
+ Internalize, Maybe, Keep);
949
+ if (!M.get ())
950
+ return false ;
951
+ if (!options::triple.empty ())
952
+ M->setTargetTriple (options::triple.c_str ());
953
+ else if (M->getTargetTriple ().empty ()) {
954
+ M->setTargetTriple (DefaultTriple);
955
+ }
956
+
957
+ if (L.move (std::move (M), Keep, [](GlobalValue &, IRMover::ValueAdder) {}))
958
+ return true ;
959
+ return false ;
865
960
}
866
961
867
962
// / gold informs us that all symbols have been read. At this point, we use
@@ -871,6 +966,9 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
871
966
if (Modules.empty ())
872
967
return LDPS_OK;
873
968
969
+ if (unsigned NumOpts = options::extra.size ())
970
+ cl::ParseCommandLineOptions (NumOpts, &options::extra[0 ]);
971
+
874
972
// If we are doing ThinLTO compilation, simply build the combined
875
973
// function index/summary and emit it. We don't need to parse the modules
876
974
// and link them in this case.
@@ -907,23 +1005,13 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
907
1005
std::unique_ptr<Module> Combined (new Module (" ld-temp.o" , Context));
908
1006
IRMover L (*Combined);
909
1007
910
- std::string DefaultTriple = sys::getDefaultTargetTriple ();
911
-
912
1008
StringSet<> Internalize;
913
1009
StringSet<> Maybe;
914
1010
for (claimed_file &F : Modules) {
915
1011
PluginInputFile InputFile (F.handle );
916
- std::vector<GlobalValue *> Keep;
917
- std::unique_ptr<Module> M = getModuleForFile (
918
- Context, F, InputFile.file (), ApiFile, Internalize, Maybe, Keep);
919
- if (!M.get ())
920
- continue ;
921
- if (!options::triple.empty ())
922
- M->setTargetTriple (options::triple.c_str ());
923
- else if (M->getTargetTriple ().empty ())
924
- M->setTargetTriple (DefaultTriple);
925
-
926
- if (L.move (std::move (M), Keep, [](GlobalValue &, IRMover::ValueAdder) {}))
1012
+ const void *View = getSymbolsAndView (F);
1013
+ if (linkInModule (Context, L, F, View, InputFile.file (), ApiFile,
1014
+ Internalize, Maybe))
927
1015
message (LDPL_FATAL, " Failed to link module" );
928
1016
}
929
1017
@@ -956,7 +1044,8 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
956
1044
return LDPS_OK;
957
1045
}
958
1046
959
- codegen (std::move (Combined));
1047
+ CodeGen codeGen (std::move (Combined));
1048
+ codeGen.runAll ();
960
1049
961
1050
if (!options::extra_library_path.empty () &&
962
1051
set_extra_library_path (options::extra_library_path.c_str ()) != LDPS_OK)
0 commit comments