diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -128,6 +128,9 @@ /// The Offloading architecture associated with this action. const char *OffloadingArch = nullptr; + /// The Offloading toolchain associated with this device action. + const ToolChain *OffloadingToolChain = nullptr; + Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {} Action(ActionClass Kind, Action *Input, types::ID Type) : Action(Kind, ActionList({Input}), Type) {} @@ -184,7 +187,8 @@ /// Set the device offload info of this action and propagate it to its /// dependences. - void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch); + void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch, + const ToolChain *OToolChain); /// Append the host offload info of this action and propagate it to its /// dependences. @@ -205,10 +209,13 @@ OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; } const char *getOffloadingArch() const { return OffloadingArch; } + const ToolChain *getOffloadingToolChain() const { + return OffloadingToolChain; + } /// Check if this action have any offload kinds. Note that host offload kinds /// are only set if the action is a dependence to a host offload action. - bool isHostOffloading(OffloadKind OKind) const { + bool isHostOffloading(unsigned int OKind) const { return ActiveOffloadKindMask & OKind; } bool isDeviceOffloading(OffloadKind OKind) const { diff --git a/clang/include/clang/Driver/Compilation.h b/clang/include/clang/Driver/Compilation.h --- a/clang/include/clang/Driver/Compilation.h +++ b/clang/include/clang/Driver/Compilation.h @@ -139,7 +139,7 @@ const ToolChain &getDefaultToolChain() const { return DefaultToolChain; } - unsigned isOffloadingHostKind(Action::OffloadKind Kind) const { + unsigned isOffloadingHostKind(unsigned int Kind) const { return ActiveOffloadMask & Kind; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2523,6 +2523,8 @@ HelpText<"Use the new driver for OpenMP offloading.">; def fno_openmp_new_driver : Flag<["-"], "fno-openmp-new-driver">, Flags<[CC1Option]>, Group, HelpText<"Don't use the new driver for OpenMP offloading.">; +def foffload_new_driver : Flag<["-"], "foffload-new-driver">, Flags<[CC1Option]>, Group, + HelpText<"Use the new driver for offloading.">; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group, Flags<[CC1Option]>, HelpText<"Disable tail call optimization, keeping the call stack accurate">, MarshallingInfoFlag>; diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -54,7 +54,8 @@ llvm_unreachable("invalid class"); } -void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) { +void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch, + const ToolChain *OToolChain) { // Offload action set its own kinds on their dependences. if (Kind == OffloadClass) return; @@ -67,9 +68,10 @@ assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??"); OffloadingDeviceKind = OKind; OffloadingArch = OArch; + OffloadingToolChain = OToolChain; for (auto *A : Inputs) - A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch); + A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain); } void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) { @@ -91,7 +93,8 @@ propagateHostOffloadInfo(HK, A->getOffloadingArch()); else propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(), - A->getOffloadingArch()); + A->getOffloadingArch(), + A->getOffloadingToolChain()); } std::string Action::getOffloadingKindPrefix() const { @@ -192,6 +195,7 @@ DevToolChains(DDeps.getToolChains()) { auto &OKinds = DDeps.getOffloadKinds(); auto &BArchs = DDeps.getBoundArchs(); + auto &OTCs = DDeps.getToolChains(); // If all inputs agree on the same kind, use it also for this action. if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); })) @@ -203,7 +207,7 @@ // Propagate info to the dependencies. for (unsigned i = 0, e = getInputs().size(); i != e; ++i) - getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]); + getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i], OTCs[i]); } OffloadAction::OffloadAction(const HostDependence &HDep, @@ -222,7 +226,8 @@ if (auto *A = DDeps.getActions()[i]) { getInputs().push_back(A); A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i], - DDeps.getBoundArchs()[i]); + DDeps.getBoundArchs()[i], + DDeps.getToolChains()[i]); } } diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3891,16 +3891,17 @@ // Builder to be used to build offloading actions. OffloadingActionBuilder OffloadBuilder(C, Args, Inputs); + bool UseNewOffloadingDriver = + (C.isOffloadingHostKind(Action::OFK_OpenMP) && + !Args.hasArg(options::OPT_fno_openmp_new_driver)) || + Args.hasArg(options::OPT_foffload_new_driver); + // Construct the actions to perform. HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; ExtractAPIJobAction *ExtractAPIAction = nullptr; ActionList LinkerInputs; ActionList MergerInputs; - bool UseNewOffloadingDriver = - C.isOffloadingHostKind(Action::OFK_OpenMP) && - !Args.hasArg(options::OPT_fno_openmp_new_driver); - for (auto &I : Inputs) { types::ID InputType = I.first; const Arg *InputArg = I.second; @@ -4024,8 +4025,7 @@ // Check if this Linker Job should emit a static library. if (ShouldEmitStaticLibrary(Args)) { LA = C.MakeAction(LinkerInputs, types::TY_Image); - } else if (UseNewOffloadingDriver && - C.getActiveOffloadKinds() != Action::OFK_None) { + } else if (UseNewOffloadingDriver) { LA = C.MakeAction(LinkerInputs, types::TY_Image); LA->propagateHostOffloadInfo(C.getActiveOffloadKinds(), /*BoundArch=*/nullptr); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4376,11 +4376,14 @@ bool IsHIP = JA.isOffloading(Action::OFK_HIP); bool IsHIPDevice = JA.isDeviceOffloading(Action::OFK_HIP); bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); - bool IsOpenMPHost = JA.isHostOffloading(Action::OFK_OpenMP); bool IsHeaderModulePrecompile = isa(JA); bool IsExtractAPI = isa(JA); bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) || JA.isDeviceOffloading(Action::OFK_Host)); + bool IsHostOffloadingAction = + JA.isHostOffloading(Action::OFK_OpenMP) && + !Args.hasArg(options::OPT_fno_openmp_new_driver) || + Args.hasArg(options::OPT_foffload_new_driver); bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction); auto LTOMode = D.getLTOMode(IsDeviceOffloadAction); @@ -4407,7 +4410,7 @@ InputInfoList ModuleHeaderInputs; InputInfoList ExtractAPIInputs; - InputInfoList OpenMPHostInputs; + InputInfoList HostOffloadingInputs; const InputInfo *CudaDeviceInput = nullptr; const InputInfo *OpenMPDeviceInput = nullptr; for (const InputInfo &I : Inputs) { @@ -4430,12 +4433,12 @@ << types::getTypeName(ExpectedInputType); } ExtractAPIInputs.push_back(I); + } else if (IsHostOffloadingAction) { + HostOffloadingInputs.push_back(I); } else if ((IsCuda || IsHIP) && !CudaDeviceInput) { CudaDeviceInput = &I; } else if (IsOpenMPDevice && !OpenMPDeviceInput) { OpenMPDeviceInput = &I; - } else if (IsOpenMPHost) { - OpenMPHostInputs.push_back(I); } else { llvm_unreachable("unexpectedly given multiple inputs"); } @@ -4672,6 +4675,7 @@ // Only AMDGPU supports device-side LTO. if (IsDeviceOffloadAction && Args.hasArg(options::OPT_fno_openmp_new_driver) && + !Args.hasArg(options::OPT_foffload_new_driver) && !Triple.isAMDGPU()) { D.Diag(diag::err_drv_unsupported_opt_for_target) << Args.getLastArg(options::OPT_foffload_lto, @@ -6931,24 +6935,23 @@ } } - // Host-side OpenMP offloading recieves the device object files and embeds it - // in a named section including the associated target triple and architecture. - if (IsOpenMPHost && !OpenMPHostInputs.empty()) { - auto InputFile = OpenMPHostInputs.begin(); - auto OpenMPTCs = C.getOffloadToolChains(); - for (auto TI = OpenMPTCs.first, TE = OpenMPTCs.second; TI != TE; - ++TI, ++InputFile) { - const ToolChain *TC = TI->second; - const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP); - StringRef File = - C.getArgs().MakeArgString(TC->getInputFilename(*InputFile)); + // Host-side offloading recieves the device object files and embeds it in a + // named section including the associated target triple and architecture. + for (const InputInfo Input : HostOffloadingInputs) { + const Action *OffloadAction = Input.getAction(); + const ToolChain *TC = OffloadAction->getOffloadingToolChain(); + const ArgList &TCArgs = + C.getArgsForToolChain(TC, OffloadAction->getOffloadingArch(), + OffloadAction->getOffloadingDeviceKind()); + StringRef File = C.getArgs().MakeArgString(TC->getInputFilename(Input)); + StringRef Arch = (OffloadAction->getOffloadingArch()) + ? OffloadAction->getOffloadingArch() + : TCArgs.getLastArgValue(options::OPT_march_EQ); - CmdArgs.push_back( - Args.MakeArgString("-fembed-offload-object=" + File + "," + - Action::GetOffloadKindName(Action::OFK_OpenMP) + - "," + TC->getTripleString() + "," + - TCArgs.getLastArgValue(options::OPT_march_EQ))); - } + CmdArgs.push_back(Args.MakeArgString( + "-fembed-offload-object=" + File + "," + + Action::GetOffloadKindName(OffloadAction->getOffloadingDeviceKind()) + + "," + TC->getTripleString() + "," + Arch)); } if (Triple.isAMDGPU()) {