diff options
Diffstat (limited to 'clang/lib/Driver/Driver.cpp')
| -rw-r--r-- | clang/lib/Driver/Driver.cpp | 91 |
1 files changed, 55 insertions, 36 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index fa7780fa577..56d1afbc08c 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1233,11 +1233,13 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, } } -// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE input -// action and then wraps each in CudaDeviceAction paired with appropriate GPU -// arch name. If we're only building device-side code, each action remains -// independent. Otherwise we pass device-side actions as inputs to a new -// CudaHostAction which combines both host and device side actions. +// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE +// input action and then wraps each in CudaDeviceAction paired with +// appropriate GPU arch name. In case of partial (i.e preprocessing +// only) or device-only compilation, each device action is added to /p +// Actions and /p Current is released. Otherwise the function creates +// and returns a new CudaHostAction which wraps /p Current and device +// side actions. static std::unique_ptr<Action> buildCudaActions(const Driver &D, const ToolChain &TC, DerivedArgList &Args, const Arg *InputArg, std::unique_ptr<Action> HostAction, @@ -1421,22 +1423,14 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, } phases::ID CudaInjectionPhase; - if (isSaveTempsEnabled()) { - // All phases are done independently, inject GPU blobs during compilation - // phase as that's where we generate glue code to init them. - CudaInjectionPhase = phases::Compile; - } else { - // Assumes that clang does everything up until linking phase, so we inject - // cuda device actions at the last step before linking. Otherwise CUDA - // host action forces preprocessor into a separate invocation. - CudaInjectionPhase = FinalPhase; - if (FinalPhase == phases::Link) - for (auto PI = PL.begin(), PE = PL.end(); PI != PE; ++PI) { - auto next = PI + 1; - if (next != PE && *next == phases::Link) - CudaInjectionPhase = *PI; - } - } + bool InjectCuda = (InputType == types::TY_CUDA && + !Args.hasArg(options::OPT_cuda_host_only)); + CudaInjectionPhase = FinalPhase; + for (auto &Phase : PL) + if (Phase <= FinalPhase && Phase == phases::Compile) { + CudaInjectionPhase = Phase; + break; + } // Build the pipeline for this file. std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType)); @@ -1464,8 +1458,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, // Otherwise construct the appropriate action. Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current)); - if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase && - !Args.hasArg(options::OPT_cuda_host_only)) { + if (InjectCuda && Phase == CudaInjectionPhase) { Current = buildCudaActions(*this, TC, Args, InputArg, std::move(Current), Actions); if (!Current) @@ -1679,10 +1672,17 @@ void Driver::BuildJobs(Compilation &C) const { } } -static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps, +// Returns a Tool for a given JobAction. In case the action and its +// predecessors can be combined, updates Inputs with the inputs of the +// first combined action. If one of the collapsed actions is a +// CudaHostAction, updates CollapsedCHA with the pointer to it so the +// caller can deal with extra handling such action requires. +static const Tool *selectToolForJob(Compilation &C, bool SaveTemps, const ToolChain *TC, const JobAction *JA, - const ActionList *&Inputs) { + const ActionList *&Inputs, + const CudaHostAction *&CollapsedCHA) { const Tool *ToolForJob = nullptr; + CollapsedCHA = nullptr; // See if we should look for a compiler with an integrated assembler. We match // bottom up, so what we are actually looking for is an assembler job with a @@ -1699,13 +1699,19 @@ static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps, // checking the backend tool, check if the tool for the CompileJob // has an integrated assembler. const ActionList *BackendInputs = &(*Inputs)[0]->getInputs(); - JobAction *CompileJA = cast<CompileJobAction>(*BackendInputs->begin()); + // Compile job may be wrapped in CudaHostAction, extract it if + // that's the case and update CollapsedCHA if we combine phases. + CudaHostAction *CHA = dyn_cast<CudaHostAction>(*BackendInputs->begin()); + JobAction *CompileJA = + cast<CompileJobAction>(CHA ? *CHA->begin() : *BackendInputs->begin()); + assert(CompileJA && "Backend job is not preceeded by compile job."); const Tool *Compiler = TC->SelectTool(*CompileJA); if (!Compiler) return nullptr; if (Compiler->hasIntegratedAssembler()) { - Inputs = &(*BackendInputs)[0]->getInputs(); + Inputs = &CompileJA->getInputs(); ToolForJob = Compiler; + CollapsedCHA = CHA; } } @@ -1715,19 +1721,19 @@ static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps, if (isa<BackendJobAction>(JA)) { // Check if the compiler supports emitting LLVM IR. assert(Inputs->size() == 1); - JobAction *CompileJA; - // Extract real host action, if it's a CudaHostAction. - if (CudaHostAction *CudaHA = dyn_cast<CudaHostAction>(*Inputs->begin())) - CompileJA = cast<CompileJobAction>(*CudaHA->begin()); - else - CompileJA = cast<CompileJobAction>(*Inputs->begin()); - + // Compile job may be wrapped in CudaHostAction, extract it if + // that's the case and update CollapsedCHA if we combine phases. + CudaHostAction *CHA = dyn_cast<CudaHostAction>(*Inputs->begin()); + JobAction *CompileJA = + cast<CompileJobAction>(CHA ? *CHA->begin() : *Inputs->begin()); + assert(CompileJA && "Backend job is not preceeded by compile job."); const Tool *Compiler = TC->SelectTool(*CompileJA); if (!Compiler) return nullptr; if (!Compiler->canEmitIR() || !SaveTemps) { - Inputs = &(*Inputs)[0]->getInputs(); + Inputs = &CompileJA->getInputs(); ToolForJob = Compiler; + CollapsedCHA = CHA; } } @@ -1811,10 +1817,23 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A, const ActionList *Inputs = &A->getInputs(); const JobAction *JA = cast<JobAction>(A); - const Tool *T = SelectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs); + const CudaHostAction *CollapsedCHA = nullptr; + const Tool *T = + selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA); if (!T) return; + // If we've collapsed action list that contained CudaHostAction we + // need to build jobs for device-side inputs it may have held. + if (CollapsedCHA) { + InputInfo II; + for (const Action *DA : CollapsedCHA->getDeviceActions()) { + BuildJobsForAction(C, DA, TC, "", AtTopLevel, + /*MultipleArchs*/ false, LinkingOutput, II); + CudaDeviceInputInfos.push_back(II); + } + } + // Only use pipes when there is exactly one input. InputInfoList InputInfos; for (const Action *Input : *Inputs) { |

