Skip to content

Commit f6aaf8a

Browse files
Merge pull request #23102 from aschwaighofer/increase_stack_size_llvm_codegen_threads
Increase the stack size limit for running llvm codegen threads to 8MB
2 parents 1aa18c9 + 38063aa commit f6aaf8a

File tree

1 file changed

+107
-28
lines changed

1 file changed

+107
-28
lines changed

lib/IRGen/IRGen.cpp

Lines changed: 107 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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

10941173
std::unique_ptr<llvm::Module> swift::performIRGeneration(

0 commit comments

Comments
 (0)