@@ -873,26 +873,109 @@ performIRGeneration(IRGenOptions &Opts, ModuleDecl *M,
873
873
return std::unique_ptr<llvm::Module>(IGM.releaseModule ());
874
874
}
875
875
876
- static void ThreadEntryPoint (IRGenerator *irgen,
877
- llvm::sys::Mutex *DiagMutex, int ThreadIdx) {
878
- while (IRGenModule *IGM = irgen->fetchFromQueue ()) {
879
- LLVM_DEBUG (DiagMutex->lock (); dbgs () << " thread " << ThreadIdx
880
- << " : fetched "
881
- << IGM->OutputFilename << " \n " ;
882
- DiagMutex->unlock (););
883
- embedBitcode (IGM->getModule (), irgen->Opts );
884
- performLLVM (irgen->Opts , &IGM->Context .Diags , DiagMutex, IGM->ModuleHash ,
885
- IGM->getModule (), IGM->TargetMachine .get (),
886
- IGM->Context .LangOpts .EffectiveLanguageVersion ,
887
- IGM->OutputFilename , IGM->Context .Stats );
888
- if (IGM->Context .Diags .hadAnyError ())
876
+ namespace {
877
+ struct LLVMCodeGenThreads {
878
+
879
+ struct Thread {
880
+ LLVMCodeGenThreads &parent;
881
+ unsigned threadIndex;
882
+ #ifdef __APPLE__
883
+ pthread_t threadId;
884
+ #else
885
+ std::thread *thread;
886
+ #endif
887
+
888
+ Thread (LLVMCodeGenThreads &parent, unsigned threadIndex)
889
+ : parent(parent), threadIndex(threadIndex)
890
+ #ifndef __APPLE__
891
+ , thread(nullptr )
892
+ #endif
893
+ {}
894
+
895
+ // / Run llvm codegen.
896
+ void run () {
897
+ auto *diagMutex = parent.diagMutex ;
898
+ while (IRGenModule *IGM = parent.irgen ->fetchFromQueue ()) {
899
+ LLVM_DEBUG (diagMutex->lock ();
900
+ dbgs () << " thread " << threadIndex << " : fetched "
901
+ << IGM->OutputFilename << " \n " ;
902
+ diagMutex->unlock (););
903
+ embedBitcode (IGM->getModule (), parent.irgen ->Opts );
904
+ performLLVM (parent.irgen ->Opts , &IGM->Context .Diags , diagMutex,
905
+ IGM->ModuleHash , IGM->getModule (), IGM->TargetMachine .get (),
906
+ IGM->Context .LangOpts .EffectiveLanguageVersion ,
907
+ IGM->OutputFilename , IGM->Context .Stats );
908
+ if (IGM->Context .Diags .hadAnyError ())
909
+ return ;
910
+ }
911
+ LLVM_DEBUG (diagMutex->lock ();
912
+ dbgs () << " thread " << threadIndex << " : done\n " ;
913
+ diagMutex->unlock (););
889
914
return ;
915
+ }
916
+ };
917
+
918
+ IRGenerator *irgen;
919
+ llvm::sys::Mutex *diagMutex;
920
+ std::vector<Thread> threads;
921
+
922
+ LLVMCodeGenThreads (IRGenerator *irgen, llvm::sys::Mutex *diagMutex,
923
+ unsigned numThreads)
924
+ : irgen(irgen), diagMutex(diagMutex) {
925
+ threads.reserve (numThreads);
926
+ for (unsigned idx = 0 ; idx < numThreads; ++idx) {
927
+ // the 0-th thread is executed by the main thread.
928
+ threads.push_back (Thread (*this , idx + 1 ));
929
+ }
930
+ }
931
+
932
+ static void *runThread (void *arg) {
933
+ auto *thread = reinterpret_cast <Thread *>(arg);
934
+ thread->run ();
935
+ return nullptr ;
936
+ }
937
+
938
+ void startThreads () {
939
+ #ifdef __APPLE__
940
+ // Increase the thread stack size on macosx to 8MB (default is 512KB). This
941
+ // matches the main thread.
942
+ pthread_attr_t stackSizeAttribute;
943
+ int err = pthread_attr_init (&stackSizeAttribute);
944
+ assert (!err);
945
+ err = pthread_attr_setstacksize (&stackSizeAttribute, 8 * 1024 * 1024 );
946
+ assert (!err);
947
+
948
+ for (auto &thread : threads) {
949
+ pthread_create (&thread.threadId , &stackSizeAttribute,
950
+ LLVMCodeGenThreads::runThread, &thread);
951
+ }
952
+
953
+ pthread_attr_destroy (&stackSizeAttribute);
954
+ #else
955
+ for (auto &thread : threads) {
956
+ thread.thread = new std::thread (runThread, &thread);
957
+ }
958
+ #endif
959
+
960
+ }
961
+
962
+ void runMainThread () {
963
+ Thread mainThread (*this , 0 );
964
+ mainThread.run ();
890
965
}
891
- LLVM_DEBUG (
892
- DiagMutex->lock ();
893
- dbgs () << " thread " << ThreadIdx << " : done\n " ;
894
- DiagMutex->unlock ();
895
- );
966
+
967
+ void join () {
968
+ #ifdef __APPLE__
969
+ for (auto &thread : threads)
970
+ pthread_join (thread.threadId , 0 );
971
+ #else
972
+ for (auto &thread: threads) {
973
+ thread.thread ->join ();
974
+ delete thread.thread ;
975
+ }
976
+ #endif
977
+ }
978
+ };
896
979
}
897
980
898
981
// / Generates LLVM IR, runs the LLVM passes and produces the output files.
@@ -1071,26 +1154,22 @@ static void performParallelIRGeneration(
1071
1154
1072
1155
SharedTimer timer (" LLVM pipeline" );
1073
1156
1074
- std::vector<std::thread> Threads;
1075
1157
llvm::sys::Mutex DiagMutex;
1076
1158
1077
1159
// Start all the threads and do the LLVM compilation.
1078
- for (int ThreadIdx = 1 ; ThreadIdx < numThreads; ++ThreadIdx) {
1079
- Threads.push_back (std::thread (ThreadEntryPoint, &irgen, &DiagMutex,
1080
- ThreadIdx));
1081
- }
1160
+ LLVMCodeGenThreads codeGenThreads (&irgen, &DiagMutex, numThreads - 1 );
1161
+ codeGenThreads.startThreads ();
1082
1162
1083
1163
// Free the memory occupied by the SILModule.
1084
1164
// Execute this task in parallel to the LLVM compilation.
1085
1165
auto SILModuleRelease = [&SILMod]() { SILMod.reset (nullptr ); };
1086
- Threads. push_back ( std::thread (SILModuleRelease) );
1166
+ auto releaseModuleThread = std::thread (SILModuleRelease);
1087
1167
1088
- ThreadEntryPoint (&irgen, &DiagMutex, 0 );
1168
+ codeGenThreads. runMainThread ( );
1089
1169
1090
1170
// Wait for all threads.
1091
- for (std::thread &Thread : Threads) {
1092
- Thread.join ();
1093
- }
1171
+ releaseModuleThread.join ();
1172
+ codeGenThreads.join ();
1094
1173
}
1095
1174
1096
1175
std::unique_ptr<llvm::Module> swift::performIRGeneration (
0 commit comments