summaryrefslogtreecommitdiffstats
path: root/clang/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver/Driver.cpp')
-rw-r--r--clang/lib/Driver/Driver.cpp91
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) {
OpenPOWER on IntegriCloud