Index: include/clang/Driver/Driver.h =================================================================== --- include/clang/Driver/Driver.h +++ include/clang/Driver/Driver.h @@ -380,15 +380,14 @@ phases::ID Phase, std::shared_ptr Input) const; /// BuildJobsForAction - Construct the jobs to perform for the - /// action \p A. - void BuildJobsForAction(Compilation &C, - const Action *A, - const ToolChain *TC, - const char *BoundArch, - bool AtTopLevel, - bool MultipleArchs, - const char *LinkingOutput, - InputInfo &Result) const; + /// action \p A. Will only construct jobs for a given (Action, + /// ToolChain) pair once. + void BuildJobsForAction( + Compilation &C, const Action *A, const ToolChain *TC, + const char *BoundArch, bool AtTopLevel, bool MultipleArchs, + const char *LinkingOutput, + std::set> &VisitedActions, + InputInfo &Result) const; /// Returns the default name for linked images (e.g., "a.out"). const char *getDefaultImageName() const; Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -1644,6 +1644,8 @@ if (A->getOption().matches(options::OPT_arch)) ArchNames.insert(A->getValue()); + // Set of (Action, canonical ToolChain triple) pairs we've built jobs for. + std::set> VisitedActions; for (const std::shared_ptr& A : C.getActions()) { // If we are linking an image for multiple archs then the linker wants // -arch_multiple and -final_output . Unfortunately, this @@ -1664,7 +1666,7 @@ /*BoundArch*/ nullptr, /*AtTopLevel*/ true, /*MultipleArchs*/ ArchNames.size() > 1, - /*LinkingOutput*/ LinkingOutput, II); + /*LinkingOutput*/ LinkingOutput, VisitedActions, II); } // If the user passed -Qunused-arguments or there were errors, don't warn @@ -1792,20 +1794,27 @@ return ToolForJob; } -void Driver::BuildJobsForAction(Compilation &C, const Action *A, - const ToolChain *TC, const char *BoundArch, - bool AtTopLevel, bool MultipleArchs, - const char *LinkingOutput, - InputInfo &Result) const { +void Driver::BuildJobsForAction( + Compilation &C, const Action *A, const ToolChain *TC, const char *BoundArch, + bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput, + std::set> &VisitedActions, + InputInfo &Result) const { llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); + std::pair ActionTC = { + A, TC->getTriple().normalize()}; + if (VisitedActions.find(ActionTC) != VisitedActions.end()) + return; + VisitedActions.insert(ActionTC); + InputInfoList CudaDeviceInputInfos; if (const CudaHostAction *CHA = dyn_cast(A)) { InputInfo II; // Append outputs of device jobs to the input list. for (const std::shared_ptr &DA : CHA->getDeviceActions()) { BuildJobsForAction(C, DA.get(), TC, nullptr, AtTopLevel, - /*MultipleArchs*/ false, LinkingOutput, II); + /*MultipleArchs*/ false, LinkingOutput, VisitedActions, + II); CudaDeviceInputInfos.push_back(II); } // Override current action with a real host compile action and continue @@ -1839,7 +1848,7 @@ TC = &C.getDefaultToolChain(); BuildJobsForAction(C, BAA->begin()->get(), TC, ArchName, AtTopLevel, - MultipleArchs, LinkingOutput, Result); + MultipleArchs, LinkingOutput, VisitedActions, Result); return; } @@ -1849,7 +1858,8 @@ assert(CDA->getGpuArchName() && "No GPU name in device action."); BuildJobsForAction(C, CDA->begin()->get(), C.getCudaDeviceToolChain(), CDA->getGpuArchName(), CDA->isAtTopLevel(), - /*MultipleArchs*/ true, LinkingOutput, Result); + /*MultipleArchs*/ true, LinkingOutput, VisitedActions, + Result); return; } @@ -1868,7 +1878,8 @@ InputInfo II; for (const std::shared_ptr &DA : CollapsedCHA->getDeviceActions()) { BuildJobsForAction(C, DA.get(), TC, "", AtTopLevel, - /*MultipleArchs*/ false, LinkingOutput, II); + /*MultipleArchs*/ false, LinkingOutput, VisitedActions, + II); CudaDeviceInputInfos.push_back(II); } } @@ -1885,7 +1896,7 @@ InputInfo II; BuildJobsForAction(C, Input.get(), TC, BoundArch, SubJobAtTopLevel, - MultipleArchs, LinkingOutput, II); + MultipleArchs, LinkingOutput, VisitedActions, II); InputInfos.push_back(II); }