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