Skip to content

Commit 38063aa

Browse files
committed
Increase the stack size limit for running llvm codegen threads to 8MB
Without this compilation may fail in llvm because we run out of stack space. The limit for the main thread is 8MB on mac osx but 512KB for other threads. rdar://47787344
1 parent d00dcaa commit 38063aa

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)