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