@@ -871,26 +871,109 @@ performIRGeneration(IRGenOptions &Opts, ModuleDecl *M,
871871 return std::unique_ptr<llvm::Module>(IGM.releaseModule ());
872872}
873873
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 (););
887912 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 ();
888963 }
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+ };
894977}
895978
896979// / Generates LLVM IR, runs the LLVM passes and produces the output files.
@@ -1069,26 +1152,22 @@ static void performParallelIRGeneration(
10691152
10701153 SharedTimer timer (" LLVM pipeline" );
10711154
1072- std::vector<std::thread> Threads;
10731155 llvm::sys::Mutex DiagMutex;
10741156
10751157 // 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 ();
10801160
10811161 // Free the memory occupied by the SILModule.
10821162 // Execute this task in parallel to the LLVM compilation.
10831163 auto SILModuleRelease = [&SILMod]() { SILMod.reset (nullptr ); };
1084- Threads. push_back ( std::thread (SILModuleRelease) );
1164+ auto releaseModuleThread = std::thread (SILModuleRelease);
10851165
1086- ThreadEntryPoint (&irgen, &DiagMutex, 0 );
1166+ codeGenThreads. runMainThread ( );
10871167
10881168 // Wait for all threads.
1089- for (std::thread &Thread : Threads) {
1090- Thread.join ();
1091- }
1169+ releaseModuleThread.join ();
1170+ codeGenThreads.join ();
10921171}
10931172
10941173std::unique_ptr<llvm::Module> swift::performIRGeneration (
0 commit comments