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.cpp129
1 files changed, 123 insertions, 6 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index bdf3e0ebe85..514c0008287 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1544,8 +1544,9 @@ class OffloadingActionBuilder final {
/// added to the provided host action \a HostAction. By default it is
/// inactive.
virtual ActionBuilderReturnCode
- getDeviceDepences(OffloadAction::DeviceDependences &DA, phases::ID CurPhase,
- phases::ID FinalPhase, PhasesTy &Phases) {
+ getDeviceDependences(OffloadAction::DeviceDependences &DA,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ PhasesTy &Phases) {
return ABRT_Inactive;
}
@@ -1603,8 +1604,9 @@ class OffloadingActionBuilder final {
: DeviceActionBuilder(C, Args, Inputs, Action::OFK_Cuda) {}
ActionBuilderReturnCode
- getDeviceDepences(OffloadAction::DeviceDependences &DA, phases::ID CurPhase,
- phases::ID FinalPhase, PhasesTy &Phases) override {
+ getDeviceDependences(OffloadAction::DeviceDependences &DA,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ PhasesTy &Phases) override {
if (!IsActive)
return ABRT_Inactive;
@@ -1828,7 +1830,118 @@ class OffloadingActionBuilder final {
}
};
- /// Add the implementation for other specialized builders here.
+ /// OpenMP action builder. The host bitcode is passed to the device frontend
+ /// and all the device linked images are passed to the host link phase.
+ class OpenMPActionBuilder final : public DeviceActionBuilder {
+ /// The OpenMP actions for the current input.
+ ActionList OpenMPDeviceActions;
+
+ /// The linker inputs obtained for each toolchain.
+ SmallVector<ActionList, 8> DeviceLinkerInputs;
+
+ public:
+ OpenMPActionBuilder(Compilation &C, DerivedArgList &Args,
+ const Driver::InputList &Inputs)
+ : DeviceActionBuilder(C, Args, Inputs, Action::OFK_OpenMP) {}
+
+ ActionBuilderReturnCode
+ getDeviceDependences(OffloadAction::DeviceDependences &DA,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ PhasesTy &Phases) override {
+
+ // We should always have an action for each input.
+ assert(OpenMPDeviceActions.size() == ToolChains.size() &&
+ "Number of OpenMP actions and toolchains do not match.");
+
+ // The host only depends on device action in the linking phase, when all
+ // the device images have to be embedded in the host image.
+ if (CurPhase == phases::Link) {
+ assert(ToolChains.size() == DeviceLinkerInputs.size() &&
+ "Toolchains and linker inputs sizes do not match.");
+ auto LI = DeviceLinkerInputs.begin();
+ for (auto *A : OpenMPDeviceActions) {
+ LI->push_back(A);
+ ++LI;
+ }
+
+ // We passed the device action as a host dependence, so we don't need to
+ // do anything else with them.
+ OpenMPDeviceActions.clear();
+ return ABRT_Success;
+ }
+
+ // By default, we produce an action for each device arch.
+ for (Action *&A : OpenMPDeviceActions)
+ A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);
+
+ return ABRT_Success;
+ }
+
+ ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override {
+
+ // If this is an input action replicate it for each OpenMP toolchain.
+ if (auto *IA = dyn_cast<InputAction>(HostAction)) {
+ OpenMPDeviceActions.clear();
+ for (unsigned I = 0; I < ToolChains.size(); ++I)
+ OpenMPDeviceActions.push_back(
+ C.MakeAction<InputAction>(IA->getInputArg(), IA->getType()));
+ return ABRT_Success;
+ }
+
+ // When generating code for OpenMP we use the host compile phase result as
+ // a dependence to the device compile phase so that it can learn what
+ // declarations should be emitted. However, this is not the only use for
+ // the host action, so we prevent it from being collapsed.
+ if (isa<CompileJobAction>(HostAction)) {
+ HostAction->setCannotBeCollapsedWithNextDependentAction();
+ assert(ToolChains.size() == OpenMPDeviceActions.size() &&
+ "Toolchains and device action sizes do not match.");
+ OffloadAction::HostDependence HDep(
+ *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
+ /*BoundArch=*/nullptr, Action::OFK_OpenMP);
+ auto TC = ToolChains.begin();
+ for (Action *&A : OpenMPDeviceActions) {
+ assert(isa<CompileJobAction>(A));
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*A, **TC, /*BoundArch=*/nullptr, Action::OFK_OpenMP);
+ A = C.MakeAction<OffloadAction>(HDep, DDep);
+ ++TC;
+ }
+ }
+ return ABRT_Success;
+ }
+
+ void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {
+ assert(ToolChains.size() == DeviceLinkerInputs.size() &&
+ "Toolchains and linker inputs sizes do not match.");
+
+ // Append a new link action for each device.
+ auto TC = ToolChains.begin();
+ for (auto &LI : DeviceLinkerInputs) {
+ auto *DeviceLinkAction =
+ C.MakeAction<LinkJobAction>(LI, types::TY_Image);
+ DA.add(*DeviceLinkAction, **TC, /*BoundArch=*/nullptr,
+ Action::OFK_OpenMP);
+ ++TC;
+ }
+ }
+
+ bool initialize() override {
+ // Get the OpenMP toolchains. If we don't get any, the action builder will
+ // know there is nothing to do related to OpenMP offloading.
+ auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
+ for (auto TI = OpenMPTCRange.first, TE = OpenMPTCRange.second; TI != TE;
+ ++TI)
+ ToolChains.push_back(TI->second);
+
+ DeviceLinkerInputs.resize(ToolChains.size());
+ return false;
+ }
+ };
+
+ ///
+ /// TODO: Add the implementation for other specialized builders here.
+ ///
/// Specialized builders being used by this offloading action builder.
SmallVector<DeviceActionBuilder *, 4> SpecializedBuilders;
@@ -1844,6 +1957,9 @@ public:
// Create a specialized builder for CUDA.
SpecializedBuilders.push_back(new CudaActionBuilder(C, Args, Inputs));
+ // Create a specialized builder for OpenMP.
+ SpecializedBuilders.push_back(new OpenMPActionBuilder(C, Args, Inputs));
+
//
// TODO: Build other specialized builders here.
//
@@ -1886,7 +2002,8 @@ public:
continue;
}
- auto RetCode = SB->getDeviceDepences(DDeps, CurPhase, FinalPhase, Phases);
+ auto RetCode =
+ SB->getDeviceDependences(DDeps, CurPhase, FinalPhase, Phases);
// If the builder explicitly says the host action should be ignored,
// we need to increment the variable that tracks the builders that request
OpenPOWER on IntegriCloud