diff options
Diffstat (limited to 'clang/lib/Driver/Driver.cpp')
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 129 |
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 |