Skip to content

Commit e97ed4a

Browse files
committed
[5.1] 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 a13f412 commit e97ed4a

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
@@ -870,26 +870,109 @@ performIRGeneration(IRGenOptions &Opts, ModuleDecl *M,
870870
return std::unique_ptr<llvm::Module>(IGM.releaseModule());
871871
}
872872

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(););
886911
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();
887962
}
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+
};
893976
}
894977

895978
/// Generates LLVM IR, runs the LLVM passes and produces the output files.
@@ -1068,26 +1151,22 @@ static void performParallelIRGeneration(
10681151

10691152
SharedTimer timer("LLVM pipeline");
10701153

1071-
std::vector<std::thread> Threads;
10721154
llvm::sys::Mutex DiagMutex;
10731155

10741156
// 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();
10791159

10801160
// Free the memory occupied by the SILModule.
10811161
// Execute this task in parallel to the LLVM compilation.
10821162
auto SILModuleRelease = [&SILMod]() { SILMod.reset(nullptr); };
1083-
Threads.push_back(std::thread(SILModuleRelease));
1163+
auto releaseModuleThread = std::thread(SILModuleRelease);
10841164

1085-
ThreadEntryPoint(&irgen, &DiagMutex, 0);
1165+
codeGenThreads.runMainThread();
10861166

10871167
// Wait for all threads.
1088-
for (std::thread &Thread : Threads) {
1089-
Thread.join();
1090-
}
1168+
releaseModuleThread.join();
1169+
codeGenThreads.join();
10911170
}
10921171

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

0 commit comments

Comments
 (0)