diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index d90c76e8738d2..b39362f693de5 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -75,6 +75,7 @@ class Action { OffloadWrapperJobClass, SPIRVTranslatorJobClass, SPIRCheckJobClass, + SYCLPostLinkJobClass, BackendCompileJobClass, JobClassFirst = PreprocessJobClass, @@ -667,6 +668,17 @@ class SPIRCheckJobAction : public JobAction { } }; +class SYCLPostLinkJobAction : public JobAction { + void anchor() override; + +public: + SYCLPostLinkJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == SYCLPostLinkJobClass; + } +}; + class BackendCompileJobAction : public JobAction { void anchor() override; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index c669c080b3e13..0d299e643e716 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1822,6 +1822,13 @@ def fsycl_add_targets_EQ : CommaJoined<["-"], "fsycl-add-targets=">, Flags<[Driv HelpText<"Specify comma-separated list of triple and device binary image pairs to add to the final SYCL binary">; def fsycl_link_targets_EQ : CommaJoined<["-"], "fsycl-link-targets=">, Flags<[DriverOption, CC1Option, CoreOption]>, HelpText<"Specify comma-separated list of triples SYCL offloading targets to produce linked device images">; +def fsycl_device_code_split_EQ : Joined<["-"], "fsycl-device-code-split=">, + Flags<[CC1Option, CoreOption]>, HelpText<"Perform SYCL device code split: per_kernel (device code module is " + "created for each SYCL kernel) | per_source (device code module is created for each source (translation unit)). " + "Default is no device code split - all kernels go into a single module`">, Values<"per_source,per_kernel">; +def fsycl_device_code_split : Flag<["-"], "fsycl-device-code-split">, Alias, + AliasArgs<["per_source"]>, Flags<[CC1Option, CoreOption]>, + HelpText<"Perform SYCL device code split in the per_source mode i.e. create a device code module for each source (translation unit)">; def fsycl_use_bitcode : Flag<["-"], "fsycl-use-bitcode">, Flags<[CC1Option, CoreOption]>, HelpText<"Use LLVM bitcode instead of SPIR-V in fat objects">; def fno_sycl_use_bitcode : Flag<["-"], "fno-sycl-use-bitcode">, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 4fa00c9d0892f..45649b0b9e9a2 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -142,6 +142,7 @@ class ToolChain { mutable std::unique_ptr OffloadWrapper; mutable std::unique_ptr SPIRVTranslator; mutable std::unique_ptr SPIRCheck; + mutable std::unique_ptr SYCLPostLink; mutable std::unique_ptr BackendCompiler; Tool *getClang() const; @@ -154,6 +155,7 @@ class ToolChain { Tool *getOffloadWrapper() const; Tool *getSPIRVTranslator() const; Tool *getSPIRCheck() const; + Tool *getSYCLPostLink() const; Tool *getBackendCompiler() const; mutable std::unique_ptr SanitizerArguments; diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index dc2f5475f4582..49196053835eb 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -102,7 +102,8 @@ TYPE("hip-fatbin", HIP_FATBIN, INVALID, "hipfb", phases TYPE("spirv", SPIRV, INVALID, "spv", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("sycl-header", SYCL_Header, INVALID, "h", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("sycl-fatbin", SYCL_FATBIN, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) -TYPE("tempfilelist", Tempfilelist, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("tempfilelist", Tempfilelist, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("tempentriesfilelist", TempEntriesfilelist, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("archive", Archive, INVALID, "a", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("fpga-aocx", FPGA_AOCX, INVALID, "aocx", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("fpga-aocr", FPGA_AOCR, INVALID, "aocr", phases::Compile, phases::Backend, phases::Assemble, phases::Link) diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index 6d92914dd8e81..062ef9216e15d 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -47,6 +47,8 @@ const char *Action::getClassName(ActionClass AC) { return "llvm-spirv"; case SPIRCheckJobClass: return "llvm-no-spir-kernel"; + case SYCLPostLinkJobClass: + return "sycl-post-link"; case BackendCompileJobClass: return "backend-compiler"; } @@ -443,6 +445,11 @@ void SPIRCheckJobAction::anchor() {} SPIRCheckJobAction::SPIRCheckJobAction(Action *Input, types::ID Type) : JobAction(SPIRCheckJobClass, Input, Type) {} +void SYCLPostLinkJobAction::anchor() {} + +SYCLPostLinkJobAction::SYCLPostLinkJobAction(Action *Input, types::ID Type) + : JobAction(SYCLPostLinkJobClass, Input, Type) {} + void BackendCompileJobAction::anchor() {} BackendCompileJobAction::BackendCompileJobAction(Action *Input, diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp index 1b6cdc26b0e95..b203dc388bff0 100644 --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -135,7 +135,8 @@ bool Compilation::CleanupFileList(const TempFileList &Files, for (const auto &File: Files) { // Temporary file lists contain files that need to be cleaned. The // file containing the information is also removed - if (File.second == types::TY_Tempfilelist) { + if (File.second == types::TY_Tempfilelist || + File.second == types::TY_TempEntriesfilelist) { std::ifstream ListFile(File.first); if (ListFile) { // These are temporary files and need to be removed. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index c8cf729b0369d..09f60ff38b7dc 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3195,9 +3195,12 @@ class OffloadingActionBuilder final { /// Flag to signal if the user requested device-only compilation. bool CompileDeviceOnly = false; - /// Flag to signal if the user requested the device object to be wrapped + /// Flag to signal if the user requested the device object to be wrapped. bool WrapDeviceOnlyBinary = false; + /// Flag to signal if the user requested device code split. + bool DeviceCodeSplit = false; + /// The SYCL actions for the current input. ActionList SYCLDeviceActions; @@ -3237,7 +3240,7 @@ class OffloadingActionBuilder final { phases::ID CurPhase, phases::ID FinalPhase, PhasesTy &Phases) override { - // FIXME: This adds the integrated header generation pass before the + // FIXME: This adds the integration header generation pass before the // Host compilation pass so the Host can use the header generated. This // can be improved upon to where the header generation and spv generation // is done in the same step. Currently, its not too efficient. @@ -3279,9 +3282,12 @@ class OffloadingActionBuilder final { SYCLLinkBinary = C.MakeAction(DeviceLinkAction, types::TY_Object); - } else - SYCLLinkBinary = C.MakeAction(SYCLLinkBinaryList, + } else { + auto *Link = C.MakeAction(SYCLLinkBinaryList, types::TY_Image); + SYCLLinkBinary = C.MakeAction( + Link, types::TY_Image); + } // Remove the SYCL actions as they are already connected to an host // action or fat binary. @@ -3458,19 +3464,38 @@ class OffloadingActionBuilder final { } } if (!DeviceObjects.empty()) { - // link and wrap the device binary, but do not perform the - // backend compile. + // When aocx or aocr is found, there is an expectation that none of + // the other objects processed have any kernel. So, there + // is no need in device code split and backend compile here. Just + // link and wrap the device binary. auto *DeviceLinkAction = - C.MakeAction(DeviceObjects, types::TY_SPIRV); + C.MakeAction(DeviceObjects, types::TY_LLVM_BC); + auto *SPIRVTranslateAction = C.MakeAction( + DeviceLinkAction, types::TY_SPIRV); auto *DeviceWrappingAction = C.MakeAction( - DeviceLinkAction, types::TY_Object); + SPIRVTranslateAction, types::TY_Object); DA.add(*DeviceWrappingAction, **TC, /*BoundArch=*/nullptr, Action::OFK_SYCL); } continue; } auto *DeviceLinkAction = - C.MakeAction(LI, types::TY_SPIRV); + C.MakeAction(LI, types::TY_LLVM_BC); + ActionList WrapperInputs; + Action *SPIRVInput = DeviceLinkAction; + types::ID OutType = types::TY_SPIRV; + if (DeviceCodeSplit) { + auto *SplitAction = C.MakeAction( + DeviceLinkAction, types::TY_Tempfilelist); + auto *EntryGenAction = C.MakeAction( + DeviceLinkAction, types::TY_TempEntriesfilelist); + SPIRVInput = SplitAction; + WrapperInputs.push_back(EntryGenAction); + OutType = types::TY_Tempfilelist; + } + auto *SPIRVTranslateAction = + C.MakeAction(SPIRVInput, OutType); + auto TT = SYCLTripleList[I]; bool SYCLAOTCompile = (TT.getSubArch() != llvm::Triple::NoSubArch && @@ -3480,21 +3505,26 @@ class OffloadingActionBuilder final { // After the Link, wrap the files before the final host link if (SYCLAOTCompile) { - types::ID OutType = types::TY_Image; - if (TT.getSubArch() == llvm::Triple::SPIRSubArch_fpga) - OutType = FPGAOutType; + OutType = types::TY_Tempfilelist; + if (!DeviceCodeSplit) { + OutType = (TT.getSubArch() == llvm::Triple::SPIRSubArch_fpga) + ? FPGAOutType + : types::TY_Image; + } // Do the additional Ahead of Time compilation when the specific // triple calls for it (provided a valid subarch). - auto *DeviceBECompileAction = - C.MakeAction(DeviceLinkAction, OutType); + auto *DeviceBECompileAction = C.MakeAction( + SPIRVTranslateAction, OutType); + WrapperInputs.push_back(DeviceBECompileAction); auto *DeviceWrappingAction = C.MakeAction( - DeviceBECompileAction, types::TY_Object); + WrapperInputs, types::TY_Object); DA.add(*DeviceWrappingAction, **TC, /*BoundArch=*/nullptr, Action::OFK_SYCL); } else { + WrapperInputs.push_back(SPIRVTranslateAction); auto *DeviceWrappingAction = C.MakeAction( - DeviceLinkAction, types::TY_Object); + WrapperInputs, types::TY_Object); DA.add(*DeviceWrappingAction, **TC, /*BoundArch=*/nullptr, Action::OFK_SYCL); } @@ -3538,6 +3568,7 @@ class OffloadingActionBuilder final { Arg *SYCLLinkTargets = Args.getLastArg( options::OPT_fsycl_link_targets_EQ); WrapDeviceOnlyBinary = Args.hasArg(options::OPT_fsycl_link_EQ); + DeviceCodeSplit = Args.hasArg(options::OPT_fsycl_device_code_split); // Device only compilation for -fsycl-link (no FPGA) and // -fsycl-link-targets CompileDeviceOnly = @@ -5407,7 +5438,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, } else { TmpName = GetTemporaryPath(Split.first, Suffix); } - return C.addTempFile(C.getArgs().MakeArgString(TmpName)); + return C.addTempFile(C.getArgs().MakeArgString(TmpName), JA.getType()); } SmallString<128> BasePath(BaseInput); diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index cf7a5e5f06e5d..d2f00a98a3ae7 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -322,6 +322,12 @@ Tool *ToolChain::getSPIRCheck() const { return SPIRCheck.get(); } +Tool *ToolChain::getSYCLPostLink() const { + if (!SYCLPostLink) + SYCLPostLink.reset(new tools::SYCLPostLink(*this)); + return SYCLPostLink.get(); +} + Tool *ToolChain::getBackendCompiler() const { if (!BackendCompiler) BackendCompiler.reset(buildBackendCompiler()); @@ -370,6 +376,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::SPIRCheckJobClass: return getSPIRCheck(); + case Action::SYCLPostLinkJobClass: + return getSYCLPostLink(); + case Action::BackendCompileJobClass: return getBackendCompiler(); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b690dc4a26a92..05eecfda2b5d7 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6994,15 +6994,70 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA, WrapperArgs.push_back( C.getArgs().MakeArgString(Twine("-kind=") + Twine(Kind))); + ArgStringList ForeachArgs; + for (const InputInfo &I : Inputs) { assert(I.isFilename() && "Invalid input."); - WrapperArgs.push_back(I.getFilename()); + std::string FileName(I.getFilename()); + if (I.getType() == types::TY_Tempfilelist || + I.getType() == types::TY_TempEntriesfilelist) { + ForeachArgs.push_back( + C.getArgs().MakeArgString("--in-file-list=" + FileName)); + ForeachArgs.push_back( + C.getArgs().MakeArgString("--in-replace=" + FileName)); + + if (I.getType() == types::TY_TempEntriesfilelist) { + WrapperArgs.push_back( + C.getArgs().MakeArgString("-entries=" + FileName)); + continue; + } + } + WrapperArgs.push_back(C.getArgs().MakeArgString(FileName)); } - C.addCommand(std::make_unique( + auto Cmd = std::make_unique( JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - WrapperArgs, None)); + WrapperArgs, None); + if (!ForeachArgs.empty()) { + std::string ForeachOutName = + C.getDriver().GetTemporaryPath("wrapper-linker", "txt"); + const char *ForeachOutput = + C.addTempFile(C.getArgs().MakeArgString(ForeachOutName)); + SmallString<128> OutOpt("--out-file-list="); + OutOpt += ForeachOutput; + + // Construct llvm-foreach command. + // The llvm-foreach command looks like this: + // llvm-foreach --in-file-list=a.list --in-replace='{}' -- echo '{}' + ForeachArgs.push_back(C.getArgs().MakeArgString(OutOpt)); + ForeachArgs.push_back( + C.getArgs().MakeArgString("--out-replace=" + OutTmpName)); + ForeachArgs.push_back(C.getArgs().MakeArgString("--")); + + ForeachArgs.push_back(Cmd->getExecutable()); + for (auto &Arg : WrapperArgs) + ForeachArgs.push_back(Arg); + + SmallString<128> ForeachPath(C.getDriver().Dir); + llvm::sys::path::append(ForeachPath, "llvm-foreach"); + const char *Foreach = C.getArgs().MakeArgString(ForeachPath); + C.addCommand( + std::make_unique(JA, *this, Foreach, ForeachArgs, None)); + + // Construct llvm-link command. + SmallString<128> InOpt("@"); + InOpt += ForeachOutName; + ArgStringList LLVMLinkArgs{C.getArgs().MakeArgString("-o"), + WrapperFileName, + C.getArgs().MakeArgString(InOpt)}; + SmallString<128> LLVMLinkPath(C.getDriver().Dir); + llvm::sys::path::append(LLVMLinkPath, "llvm-link"); + const char *LLVMLink = C.getArgs().MakeArgString(LLVMLinkPath); + C.addCommand( + std::make_unique(JA, *this, LLVMLink, LLVMLinkArgs, None)); + } else + C.addCommand(std::move(Cmd)); // Construct llc command. // The output is an object file @@ -7084,6 +7139,7 @@ void SPIRVTranslator::ConstructJob(Compilation &C, const JobAction &JA, // The translator command looks like this: // llvm-spirv -o .spv .bc + ArgStringList ForeachArgs; ArgStringList TranslatorArgs; TranslatorArgs.push_back("-o"); @@ -7093,12 +7149,44 @@ void SPIRVTranslator::ConstructJob(Compilation &C, const JobAction &JA, TranslatorArgs.push_back("-spirv-ext=+all"); } for (auto I : Inputs) { - TranslatorArgs.push_back(I.getFilename()); + std::string Filename(I.getFilename()); + if (I.getType() == types::TY_Tempfilelist) { + ForeachArgs.push_back( + C.getArgs().MakeArgString("--in-file-list=" + Filename)); + ForeachArgs.push_back( + C.getArgs().MakeArgString("--in-replace=" + Filename)); + ForeachArgs.push_back( + C.getArgs().MakeArgString("--out-ext=spv")); + } + TranslatorArgs.push_back(C.getArgs().MakeArgString(Filename)); } - C.addCommand(std::make_unique(JA, *this, + auto Cmd = std::make_unique(JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - TranslatorArgs, None)); + TranslatorArgs, None); + + if (!ForeachArgs.empty()) { + // Construct llvm-foreach command. + // The llvm-foreach command looks like this: + // llvm-foreach a.list --out-replace=out "cp {} out" + // --out-file-list=list + std::string OutputFileName(Output.getFilename()); + ForeachArgs.push_back( + TCArgs.MakeArgString("--out-file-list=" + OutputFileName)); + ForeachArgs.push_back( + TCArgs.MakeArgString("--out-replace=" + OutputFileName)); + ForeachArgs.push_back(TCArgs.MakeArgString("--")); + ForeachArgs.push_back(TCArgs.MakeArgString(Cmd->getExecutable())); + + for (auto &Arg : Cmd->getArguments()) + ForeachArgs.push_back(Arg); + + SmallString<128> ForeachPath(C.getDriver().Dir); + llvm::sys::path::append(ForeachPath, "llvm-foreach"); + const char *Foreach = C.getArgs().MakeArgString(ForeachPath); + C.addCommand(std::make_unique(JA, *this, Foreach, ForeachArgs, None)); + } else + C.addCommand(std::move(Cmd)); } void SPIRCheck::ConstructJob(Compilation &C, const JobAction &JA, @@ -7128,3 +7216,46 @@ void SPIRCheck::ConstructJob(Compilation &C, const JobAction &JA, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), CheckArgs, None)); } + +void SYCLPostLink::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const { + // Construct sycl-post-link command. + assert(isa(JA) && "Expecting SYCL post link job!"); + + // Variants of split command look like this: + // sycl-post-link input_file.bc -ir-files-list=ir.txt -o base_output - for + // IR files generation. + // sycl-post-link input_file.bc -txt-files-list=files.txt -o base_output - for + // entries files generation. + + ArgStringList CmdArgs; + InputInfo Input = Inputs.front(); + const char *InputFileName = Input.getFilename(); + + CmdArgs.push_back(InputFileName); + std::string OutputFileName(Output.getFilename()); + if (Output.getType() == types::TY_Tempfilelist) + CmdArgs.push_back(TCArgs.MakeArgString("-ir-files-list=" + OutputFileName)); + else if (Output.getType() == types::TY_TempEntriesfilelist) + CmdArgs.push_back( + TCArgs.MakeArgString("-txt-files-list=" + OutputFileName)); + SmallString<128> TmpName; + llvm::sys::fs::createUniquePath("split-%%%%%%", TmpName, + /*MakeAbsolute*/ true); + CmdArgs.push_back(TCArgs.MakeArgString("-o")); + CmdArgs.push_back(TCArgs.MakeArgString(TmpName)); + + if (Arg *A = TCArgs.getLastArg(options::OPT_fsycl_device_code_split_EQ)) + if (A->getValue() == StringRef("per_kernel")) + CmdArgs.push_back("-one-kernel"); + + // All the inputs are encoded as commands. + C.addCommand(std::make_unique( + JA, *this, + TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), + CmdArgs, None)); +} + diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h index 3163513139428..a7dec20d8dbfa 100644 --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -191,6 +191,19 @@ class LLVM_LIBRARY_VISIBILITY SPIRCheck final : public Tool { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; + +/// SYCL post-link device code processing tool. +class LLVM_LIBRARY_VISIBILITY SYCLPostLink final : public Tool { +public: + SYCLPostLink(const ToolChain &TC) + : Tool("SYCL post link", "sycl-post-link", TC) {} + + bool hasIntegratedCPP() const override { return false; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; } // end namespace tools } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp index b8d2a3cfa6411..84ac639ce3df2 100644 --- a/clang/lib/Driver/ToolChains/SYCL.cpp +++ b/clang/lib/Driver/ToolChains/SYCL.cpp @@ -53,9 +53,45 @@ const char *SYCL::Linker::constructLLVMSpirvCommand(Compilation &C, return OutputFileName; } +void SYCL::constructLLVMForeachCommand(Compilation &C, const JobAction &JA, + std::unique_ptr InputCommand, + const InputInfoList &InputFiles, + const InputInfo &Output, const Tool *T, + StringRef Ext = "out") { + // Construct llvm-foreach command. + // The llvm-foreach command looks like this: + // llvm-foreach --in-file-list=a.list --in-replace='{}' -- echo '{}' + ArgStringList ForeachArgs; + std::string OutputFileName(Output.getFilename()); + ForeachArgs.push_back(C.getArgs().MakeArgString("--out-ext=" + Ext)); + for (auto &I : InputFiles) { + std::string Filename(I.getFilename()); + ForeachArgs.push_back( + C.getArgs().MakeArgString("--in-file-list=" + Filename)); + ForeachArgs.push_back( + C.getArgs().MakeArgString("--in-replace=" + Filename)); + } + + ForeachArgs.push_back( + C.getArgs().MakeArgString("--out-file-list=" + OutputFileName)); + ForeachArgs.push_back( + C.getArgs().MakeArgString("--out-replace=" + OutputFileName)); + ForeachArgs.push_back(C.getArgs().MakeArgString("--")); + ForeachArgs.push_back( + C.getArgs().MakeArgString(InputCommand->getExecutable())); + + for (auto &Arg : InputCommand->getArguments()) + ForeachArgs.push_back(Arg); + + SmallString<128> ForeachPath(C.getDriver().Dir); + llvm::sys::path::append(ForeachPath, "llvm-foreach"); + const char *Foreach = C.getArgs().MakeArgString(ForeachPath); + C.addCommand(std::make_unique(JA, *T, Foreach, ForeachArgs, None)); +} + const char *SYCL::Linker::constructLLVMLinkCommand(Compilation &C, const JobAction &JA, const InputInfo &Output, const ArgList &Args, - StringRef SubArchName, StringRef OutputFilePrefix, bool ToBc, + StringRef SubArchName, StringRef OutputFilePrefix, const InputInfoList &InputFiles) const { ArgStringList CmdArgs; // Add the input bc's created by compile step. @@ -82,14 +118,8 @@ const char *SYCL::Linker::constructLLVMLinkCommand(Compilation &C, TranslateSYCLLinkerArgs(C, Args, getToolChain(), CmdArgs); // Add an intermediate output file. CmdArgs.push_back("-o"); - const char *OutputFileName = nullptr; - if (ToBc) { - SmallString<128> TmpName(C.getDriver().GetTemporaryPath( - OutputFilePrefix.str() + "-linked", "bc")); - OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName)); - CmdArgs.push_back(OutputFileName); - } else - CmdArgs.push_back(Output.getFilename()); + const char *OutputFileName = Output.getFilename(); + CmdArgs.push_back(OutputFileName); // TODO: temporary workaround for a problem with warnings reported by // llvm-link when driver links LLVM modules with empty modules CmdArgs.push_back("--suppress-warnings"); @@ -150,10 +180,8 @@ void SYCL::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - const char *LLVMLinkOutputFile = - constructLLVMLinkCommand(C, JA, Output, Args, SubArchName, Prefix, true, - SpirvInputs); - constructLLVMSpirvCommand(C, JA, Output, Prefix, false, LLVMLinkOutputFile); + constructLLVMLinkCommand(C, JA, Output, Args, SubArchName, Prefix, + SpirvInputs); } void SYCL::TranslateSYCLTargetArgs(Compilation &C, @@ -272,18 +300,24 @@ void SYCL::fpga::BackendCompiler::ConstructJob(Compilation &C, assert((getToolChain().getTriple().getArch() == llvm::Triple::spir || getToolChain().getTriple().getArch() == llvm::Triple::spir64) && "Unsupported target"); - assert((JA.getType() == types::TY_FPGA_AOCX || - JA.getType() == types::TY_FPGA_AOCR) && - "aoc type required"); + InputInfoList ForeachInputs; ArgStringList CmdArgs{"-o", Output.getFilename()}; for (const auto &II : Inputs) { - CmdArgs.push_back(II.getFilename()); + std::string Filename(II.getFilename()); + if (II.getType() == types::TY_Tempfilelist) + ForeachInputs.push_back(II); + CmdArgs.push_back(C.getArgs().MakeArgString(Filename)); } CmdArgs.push_back("-sycl"); + + StringRef ForeachExt = "aocx"; if (Arg *A = Args.getLastArg(options::OPT_fsycl_link_EQ)) - if (A->getValue() == StringRef("early")) + if (A->getValue() == StringRef("early")) { CmdArgs.push_back("-rtl"); + ForeachExt = "aocr"; + } + InputInfoList FPGADepFiles; for (auto *A : Args) { @@ -352,7 +386,12 @@ void SYCL::fpga::BackendCompiler::ConstructJob(Compilation &C, SmallString<128> ExecPath(getToolChain().GetProgramPath("aoc")); const char *Exec = C.getArgs().MakeArgString(ExecPath); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, None)); + auto Cmd = std::make_unique(JA, *this, Exec, CmdArgs, None); + if (!ForeachInputs.empty()) + constructLLVMForeachCommand(C, JA, std::move(Cmd), ForeachInputs, Output, + this, ForeachExt); + else + C.addCommand(std::move(Cmd)); } void SYCL::gen::BackendCompiler::ConstructJob(Compilation &C, @@ -365,9 +404,13 @@ void SYCL::gen::BackendCompiler::ConstructJob(Compilation &C, getToolChain().getTriple().getArch() == llvm::Triple::spir64) && "Unsupported target"); ArgStringList CmdArgs{"-output", Output.getFilename()}; + InputInfoList ForeachInputs; for (const auto &II : Inputs) { CmdArgs.push_back("-file"); - CmdArgs.push_back(II.getFilename()); + std::string Filename(II.getFilename()); + if (II.getType() == types::TY_Tempfilelist) + ForeachInputs.push_back(II); + CmdArgs.push_back(C.getArgs().MakeArgString(Filename)); } // The next line prevents ocloc from modifying the image name CmdArgs.push_back("-output_no_suffix"); @@ -375,7 +418,12 @@ void SYCL::gen::BackendCompiler::ConstructJob(Compilation &C, TranslateSYCLTargetArgs(C, Args, getToolChain(), CmdArgs); SmallString<128> ExecPath(getToolChain().GetProgramPath("ocloc")); const char *Exec = C.getArgs().MakeArgString(ExecPath); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, None)); + auto Cmd = std::make_unique(JA, *this, Exec, CmdArgs, None); + if (!ForeachInputs.empty()) + constructLLVMForeachCommand(C, JA, std::move(Cmd), ForeachInputs, Output, + this); + else + C.addCommand(std::move(Cmd)); } void SYCL::x86_64::BackendCompiler::ConstructJob(Compilation &C, @@ -387,13 +435,22 @@ void SYCL::x86_64::BackendCompiler::ConstructJob(Compilation &C, ArgStringList CmdArgs; CmdArgs.push_back(Args.MakeArgString(Twine("-ir=") + Output.getFilename())); CmdArgs.push_back("-device=cpu"); + InputInfoList ForeachInputs; for (const auto &II : Inputs) { - CmdArgs.push_back(Args.MakeArgString(Twine("-binary=") + II.getFilename())); + std::string Filename(II.getFilename()); + if (II.getType() == types::TY_Tempfilelist) + ForeachInputs.push_back(II); + CmdArgs.push_back(Args.MakeArgString(Twine("-binary=") + Filename)); } TranslateSYCLTargetArgs(C, Args, getToolChain(), CmdArgs); SmallString<128> ExecPath(getToolChain().GetProgramPath("ioc64")); const char *Exec = C.getArgs().MakeArgString(ExecPath); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, None)); + auto Cmd = std::make_unique(JA, *this, Exec, CmdArgs, None); + if (!ForeachInputs.empty()) + constructLLVMForeachCommand(C, JA, std::move(Cmd), ForeachInputs, Output, + this); + else + C.addCommand(std::move(Cmd)); } SYCLToolChain::SYCLToolChain(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains/SYCL.h b/clang/lib/Driver/ToolChains/SYCL.h index 351e5b85505dc..6515ef82697fc 100644 --- a/clang/lib/Driver/ToolChains/SYCL.h +++ b/clang/lib/Driver/ToolChains/SYCL.h @@ -15,6 +15,8 @@ namespace clang { namespace driver { +class Command; + namespace tools { namespace SYCL { @@ -26,6 +28,12 @@ void TranslateSYCLTargetArgs(Compilation &C, void TranslateSYCLLinkerArgs(Compilation &C, const llvm::opt::ArgList &Args, const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs); +void constructLLVMForeachCommand(Compilation &C, const JobAction &JA, + std::unique_ptr InputCommand, + const InputInfoList &InputFiles, + const InputInfo &Output, const Tool *T, + StringRef Ext); + // Runs llvm-spirv to convert spirv to bc, llvm-link, which links multiple LLVM // bitcode. Converts generated bc back to spirv using llvm-spirv, wraps with // offloading information. Finally compiles to object using llc @@ -51,7 +59,7 @@ class LLVM_LIBRARY_VISIBILITY Linker : public Tool { const InputInfo &Output, const llvm::opt::ArgList &Args, llvm::StringRef SubArchName, - llvm::StringRef OutputFilePrefix, bool isBc, + llvm::StringRef OutputFilePrefix, const InputInfoList &InputFiles) const; void constructLlcCommand(Compilation &C, const JobAction &JA, const InputInfo &Output, diff --git a/clang/test/Driver/sycl-offload-intelfpga.cpp b/clang/test/Driver/sycl-offload-intelfpga.cpp index 779ffbb1122ee..4c015445717a3 100644 --- a/clang/test/Driver/sycl-offload-intelfpga.cpp +++ b/clang/test/Driver/sycl-offload-intelfpga.cpp @@ -25,7 +25,7 @@ // CHK-FPGA-LINK-NOT: clang-offload-bundler{{.*}} "-check-section" // CHK-FPGA-LINK: clang-offload-bundler{{.*}} "-type=o" "-targets=sycl-spir64_fpga-unknown-unknown-sycldevice" "-inputs=[[INPUT:.+\.o]]" "-outputs=[[OUTPUT1:.+\.o]]" "-unbundle" // CHK-FPGA-LINK: llvm-link{{.*}} "[[OUTPUT1]]" "-o" "[[OUTPUT2:.+\.bc]]" -// CHK-FPGA-LINK: llvm-spirv{{.*}} "-spirv-max-version=1.1" "-spirv-ext=+all" "-o" "[[OUTPUT3:.+\.spv]]" "[[OUTPUT2]]" +// CHK-FPGA-LINK: llvm-spirv{{.*}} "-o" "[[OUTPUT3:.+\.spv]]" "-spirv-max-version=1.1" "-spirv-ext=+all" "[[OUTPUT2]]" // CHK-FPGA-EARLY: aoc{{.*}} "-o" "[[OUTPUT4:.+\.aocr]]" "[[OUTPUT3]]" "-sycl" "-rtl" // CHK-FPGA-IMAGE: aoc{{.*}} "-o" "[[OUTPUT5:.+\.aocx]]" "[[OUTPUT3]]" "-sycl" // CHK-FPGA-LINK: {{lib|llvm-ar}}{{.*}} "[[INPUT]]" @@ -36,7 +36,7 @@ // RUN: | FileCheck -check-prefixes=CHK-FPGA-LINK-WIN %s // CHK-FPGA-LINK-WIN: clang-offload-bundler{{.*}} "-type=o" "-targets=sycl-spir64_fpga-unknown-unknown-sycldevice{{.*}}" "-inputs=[[INPUT:.+\.obj]]" "-outputs=[[OUTPUT1:.+\.obj]]" "-unbundle" // CHK-FPGA-LINK-WIN: llvm-link{{.*}} "[[OUTPUT1]]" "-o" "[[OUTPUT2:.+\.bc]]" -// CHK-FPGA-LINK-WIN: llvm-spirv{{.*}} "-spirv-max-version=1.1" "-spirv-ext=+all" "-o" "[[OUTPUT3:.+\.spv]]" "[[OUTPUT2]]" +// CHK-FPGA-LINK-WIN: llvm-spirv{{.*}} "-o" "[[OUTPUT3:.+\.spv]]" "-spirv-max-version=1.1" "-spirv-ext=+all" "[[OUTPUT2]]" // CHK-FPGA-LINK-WIN: aoc{{.*}} "-o" "[[OUTPUT5:.+\.aocr]]" "[[OUTPUT3]]" "-sycl" "-rtl" // CHK-FPGA-LINK-WIN: lib.exe{{.*}} "[[INPUT]]" @@ -73,7 +73,7 @@ // CHK-FPGA: clang-offload-bundler{{.*}} "-type=o" "-targets=host-x86_64-unknown-linux-gnu,sycl-spir64_fpga-unknown-unknown-sycldevice" {{.*}} "-outputs=[[FINALLINK2:.+\.o]],[[OUTPUT1:.+\.o]]" "-unbundle" // CHK-FPGA: llvm-no-spir-kernel{{.*}} "[[OUTPUT1]]" "-o" "[[OUTPUT3:.+\.o]]" // CHK-FPGA: llvm-link{{.*}} "[[OUTPUT3]]" "-o" "[[OUTPUT4:.+\.bc]]" -// CHK-FPGA: llvm-spirv{{.*}} "-o" "[[OUTPUT5:.+\.spv]]" "[[OUTPUT4]]" +// CHK-FPGA: llvm-spirv{{.*}} "-o" "[[OUTPUT5:.+\.spv]]" "-spirv-max-version=1.1" "-spirv-ext=+all" "[[OUTPUT4]]" // CHK-FPGA: clang-offload-wrapper{{.*}} "-o=[[OUTPUT6:.+\.bc]]" "-host=x86_64-unknown-linux-gnu" "-target=spir64_fpga" "-kind=sycl" "[[OUTPUT5]]" // CHK-FPGA: llc{{.*}} "-filetype=obj" "-o" "[[FINALLINK3:.+\.o]]" "[[OUTPUT6]]" // CHK-FPGA: clang-offload-bundler{{.*}} "-type=aoo" "-targets=host-x86_64-unknown-linux-gnu" {{.*}} "-outputs=[[FINALLINK4:.+\.txt]]" "-unbundle" @@ -125,11 +125,12 @@ // CHK-FPGA-LINK-SRC: 10: compiler, {3}, ir, (device-sycl) // CHK-FPGA-LINK-SRC: 11: backend, {10}, assembler, (device-sycl) // CHK-FPGA-LINK-SRC: 12: assembler, {11}, object, (device-sycl) -// CHK-FPGA-LINK-SRC: 13: linker, {12}, spirv, (device-sycl) -// CHK-FPGA-LINK-SRC: 14: backend-compiler, {13}, fpga-aocr, (device-sycl) -// CHK-FPGA-LINK-SRC: 15: clang-offload-wrapper, {14}, object, (device-sycl) -// CHK-FPGA-LINK-SRC-DEFAULT: 16: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {15}, archive -// CHK-FPGA-LINK-SRC-CL: 16: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice-coff)" {15}, archive +// CHK-FPGA-LINK-SRC: 13: linker, {12}, ir, (device-sycl) +// CHK-FPGA-LINK-SRC: 14: llvm-spirv, {13}, spirv, (device-sycl) +// CHK-FPGA-LINK-SRC: 15: backend-compiler, {14}, fpga-aocr, (device-sycl) +// CHK-FPGA-LINK-SRC: 16: clang-offload-wrapper, {15}, object, (device-sycl) +// CHK-FPGA-LINK-SRC-DEFAULT: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {16}, archive +// CHK-FPGA-LINK-SRC-CL: 17: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice-coff)" {16}, archive /// -fintelfpga with -reuse-exe= // RUN: touch %t.cpp diff --git a/clang/test/Driver/sycl-offload-win.c b/clang/test/Driver/sycl-offload-win.c index e9cc238c1fbec..397da245166ab 100644 --- a/clang/test/Driver/sycl-offload-win.c +++ b/clang/test/Driver/sycl-offload-win.c @@ -79,10 +79,11 @@ // FOFFLOAD_STATIC_LIB_SRC: 12: assembler, {11}, object, (device-sycl) // FOFFLOAD_STATIC_LIB_SRC: 13: input, "[[LIB]]", archive // FOFFLOAD_STATIC_LIB_SRC: 14: clang-offload-unbundler, {13}, archive -// FOFFLOAD_STATIC_LIB_SRC: 15: linker, {12, 14}, spirv, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC: 16: clang-offload-wrapper, {15}, object, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC_DEFAULT: 17: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {16}, image -// FOFFLOAD_STATIC_LIB_SRC_CL: 17: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice-coff)" {16}, image +// FOFFLOAD_STATIC_LIB_SRC: 15: linker, {12, 14}, ir, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 16: llvm-spirv, {15}, spirv, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 17: clang-offload-wrapper, {16}, object, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC_DEFAULT: 18: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {17}, image +// FOFFLOAD_STATIC_LIB_SRC_CL: 18: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice-coff)" {17}, image /// ########################################################################### diff --git a/clang/test/Driver/sycl-offload.c b/clang/test/Driver/sycl-offload.c index 85059717e7fac..3b6913fc98ced 100644 --- a/clang/test/Driver/sycl-offload.c +++ b/clang/test/Driver/sycl-offload.c @@ -187,10 +187,11 @@ // CHK-PHASES: 10: compiler, {3}, ir, (device-sycl) // CHK-PHASES: 11: backend, {10}, assembler, (device-sycl) // CHK-PHASES: 12: assembler, {11}, object, (device-sycl) -// CHK-PHASES: 13: linker, {12}, spirv, (device-sycl) -// CHK-PHASES: 14: clang-offload-wrapper, {13}, object, (device-sycl) -// CHK-PHASES-DEFAULT-MODE: 15: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {14}, image -// CHK-PHASES-CL-MODE: 15: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice-coff)" {14}, image +// CHK-PHASES: 13: linker, {12}, ir, (device-sycl) +// CHK-PHASES: 14: llvm-spirv, {13}, spirv, (device-sycl) +// CHK-PHASES: 15: clang-offload-wrapper, {14}, object, (device-sycl) +// CHK-PHASES-DEFAULT-MODE: 16: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {15}, image +// CHK-PHASES-CL-MODE: 16: offload, "host-sycl (x86_64-pc-windows-msvc)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice-coff)" {15}, image /// ########################################################################### @@ -222,9 +223,10 @@ // CHK-PHASES-LIB: 11: compiler, {4}, ir, (device-sycl) // CHK-PHASES-LIB: 12: backend, {11}, assembler, (device-sycl) // CHK-PHASES-LIB: 13: assembler, {12}, object, (device-sycl) -// CHK-PHASES-LIB: 14: linker, {13}, spirv, (device-sycl) -// CHK-PHASES-LIB: 15: clang-offload-wrapper, {14}, object, (device-sycl) -// CHK-PHASES-LIB: 16: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64-unknown-unknown-sycldevice)" {15}, image +// CHK-PHASES-LIB: 14: linker, {13}, ir, (device-sycl) +// CHK-PHASES-LIB: 15: llvm-spirv, {14}, spirv, (device-sycl) +// CHK-PHASES-LIB: 16: clang-offload-wrapper, {15}, object, (device-sycl) +// CHK-PHASES-LIB: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64-unknown-unknown-sycldevice)" {16}, image /// Compilation check with -lstdc++ (treated differently than regular lib) // RUN: %clang -### -target x86_64-unknown-linux-gnu -lstdc++ -fsycl %s 2>&1 \ @@ -266,9 +268,10 @@ // CHK-PHASES-FILES: 23: compiler, {13}, ir, (device-sycl) // CHK-PHASES-FILES: 24: backend, {23}, assembler, (device-sycl) // CHK-PHASES-FILES: 25: assembler, {24}, object, (device-sycl) -// CHK-PHASES-FILES: 26: linker, {22, 25}, spirv, (device-sycl) -// CHK-PHASES-FILES: 27: clang-offload-wrapper, {26}, object, (device-sycl) -// CHK-PHASES-FILES: 28: offload, "host-sycl (x86_64-unknown-linux-gnu)" {19}, "device-sycl (spir64-unknown-unknown-sycldevice)" {27}, image +// CHK-PHASES-FILES: 26: linker, {22, 25}, ir, (device-sycl) +// CHK-PHASES-FILES: 27: llvm-spirv, {26}, spirv, (device-sycl) +// CHK-PHASES-FILES: 28: clang-offload-wrapper, {27}, object, (device-sycl) +// CHK-PHASES-FILES: 29: offload, "host-sycl (x86_64-unknown-linux-gnu)" {19}, "device-sycl (spir64-unknown-unknown-sycldevice)" {28}, image /// ########################################################################### @@ -304,9 +307,10 @@ // CHK-UBACTIONS: 1: input, "[[INPUT]]", object, (host-sycl) // CHK-UBACTIONS: 2: clang-offload-unbundler, {1}, object, (host-sycl) // CHK-UBACTIONS: 3: linker, {0, 2}, image, (host-sycl) -// CHK-UBACTIONS: 4: linker, {2}, spirv, (device-sycl) -// CHK-UBACTIONS: 5: clang-offload-wrapper, {4}, object, (device-sycl) -// CHK-UBACTIONS: 6: offload, "host-sycl (x86_64-unknown-linux-gnu)" {3}, "device-sycl (spir64-unknown-unknown-sycldevice)" {5}, image +// CHK-UBACTIONS: 4: linker, {2}, ir, (device-sycl) +// CHK-UBACTIONS: 5: llvm-spirv, {4}, spirv, (device-sycl) +// CHK-UBACTIONS: 6: clang-offload-wrapper, {5}, object, (device-sycl) +// CHK-UBACTIONS: 7: offload, "host-sycl (x86_64-unknown-linux-gnu)" {3}, "device-sycl (spir64-unknown-unknown-sycldevice)" {6}, image /// ########################################################################### @@ -330,9 +334,10 @@ // CHK-UBUACTIONS: 13: compiler, {6}, ir, (device-sycl) // CHK-UBUACTIONS: 14: backend, {13}, assembler, (device-sycl) // CHK-UBUACTIONS: 15: assembler, {14}, object, (device-sycl) -// CHK-UBUACTIONS: 16: linker, {2, 15}, spirv, (device-sycl) -// CHK-UBUACTIONS: 17: clang-offload-wrapper, {16}, object, (device-sycl) -// CHK-UBUACTIONS: 18: offload, "host-sycl (x86_64-unknown-linux-gnu)" {12}, "device-sycl (spir64-unknown-unknown-sycldevice)" {17}, image +// CHK-UBUACTIONS: 16: linker, {2, 15}, ir, (device-sycl) +// CHK-UBUACTIONS: 17: llvm-spirv, {16}, spirv, (device-sycl) +// CHK-UBUACTIONS: 18: clang-offload-wrapper, {17}, object, (device-sycl) +// CHK-UBUACTIONS: 19: offload, "host-sycl (x86_64-unknown-linux-gnu)" {12}, "device-sycl (spir64-unknown-unknown-sycldevice)" {18}, image /// ########################################################################### @@ -367,7 +372,8 @@ // CHK-LINK-TARGETS-UB: 0: input, "[[INPUT:.+\.o]]", object // CHK-LINK-TARGETS-UB: 1: clang-offload-unbundler, {0}, object // CHK-LINK-TARGETS-UB: 2: linker, {1}, image, (device-sycl) -// CHK-LINK-TARGETS-UB: 3: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {2}, image +// CHK-LINK-TARGETS-UB: 3: llvm-spirv, {2}, image, (device-sycl) +// CHK-LINK-TARGETS-UB: 4: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {3}, image /// ########################################################################### @@ -386,7 +392,8 @@ // CHK-LINK-TARGETS-UB2: 4: input, "[[INPUT:.+\c.o]]", object // CHK-LINK-TARGETS-UB2: 5: clang-offload-unbundler, {4}, object // CHK-LINK-TARGETS-UB2: 6: linker, {1, 3, 5}, image, (device-sycl) -// CHK-LINK-TARGETS-UB2: 7: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {6}, image +// CHK-LINK-TARGETS-UB2: 7: llvm-spirv, {6}, image, (device-sycl) +// CHK-LINK-TARGETS-UB2: 8: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {7}, image /// ########################################################################### @@ -401,7 +408,8 @@ // CHK-LINK-TARGETS: 3: backend, {2}, assembler, (device-sycl) // CHK-LINK-TARGETS: 4: assembler, {3}, object, (device-sycl) // CHK-LINK-TARGETS: 5: linker, {4}, image, (device-sycl) -// CHK-LINK-TARGETS: 6: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {5}, image +// CHK-LINK-TARGETS: 6: llvm-spirv, {5}, image, (device-sycl) +// CHK-LINK-TARGETS: 7: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {6}, image /// ########################################################################### @@ -512,11 +520,12 @@ // CHK-ADD-TARGETS-REG: 10: compiler, {3}, ir, (device-sycl) // CHK-ADD-TARGETS-REG: 11: backend, {10}, assembler, (device-sycl) // CHK-ADD-TARGETS-REG: 12: assembler, {11}, object, (device-sycl) -// CHK-ADD-TARGETS-REG: 13: linker, {12}, spirv, (device-sycl) -// CHK-ADD-TARGETS-REG: 14: clang-offload-wrapper, {13}, object, (device-sycl) -// CHK-ADD-TARGETS-REG: 15: input, "dummy.spv", sycl-fatbin, (device-sycl) -// CHK-ADD-TARGETS-REG: 16: clang-offload-wrapper, {15}, object, (device-sycl) -// CHK-ADD-TARGETS-REG: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {14}, "device-sycl (spir64-unknown-unknown-sycldevice)" {16}, image +// CHK-ADD-TARGETS-REG: 13: linker, {12}, ir, (device-sycl) +// CHK-ADD-TARGETS-REG: 14: llvm-spirv, {13}, spirv, (device-sycl) +// CHK-ADD-TARGETS-REG: 15: clang-offload-wrapper, {14}, object, (device-sycl) +// CHK-ADD-TARGETS-REG: 16: input, "dummy.spv", sycl-fatbin, (device-sycl) +// CHK-ADD-TARGETS-REG: 17: clang-offload-wrapper, {16}, object, (device-sycl) +// CHK-ADD-TARGETS-REG: 18: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {15}, "device-sycl (spir64-unknown-unknown-sycldevice)" {17}, image /// ########################################################################### @@ -538,15 +547,16 @@ // CHK-ADD-TARGETS-REG-MUL: 12: compiler, {11}, ir, (device-sycl) // CHK-ADD-TARGETS-REG-MUL: 13: backend, {12}, assembler, (device-sycl) // CHK-ADD-TARGETS-REG-MUL: 14: assembler, {13}, object, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 15: linker, {14}, spirv, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 16: clang-offload-wrapper, {15}, object, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 17: input, "dummy.aocx", sycl-fatbin, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 18: clang-offload-wrapper, {17}, object, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 19: input, "dummy_Gen9core.bin", sycl-fatbin, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 20: clang-offload-wrapper, {19}, object, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 21: input, "dummy.ir", sycl-fatbin, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 22: clang-offload-wrapper, {21}, object, (device-sycl) -// CHK-ADD-TARGETS-REG-MUL: 23: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {16}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {18}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {20}, "device-sycl (spir64_x86_64-unknown-unknown-sycldevice)" {22}, image +// CHK-ADD-TARGETS-REG-MUL: 15: linker, {14}, ir, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 16: llvm-spirv, {15}, spirv, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 17: clang-offload-wrapper, {16}, object, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 18: input, "dummy.aocx", sycl-fatbin, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 19: clang-offload-wrapper, {18}, object, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 20: input, "dummy_Gen9core.bin", sycl-fatbin, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 21: clang-offload-wrapper, {20}, object, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 22: input, "dummy.ir", sycl-fatbin, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 23: clang-offload-wrapper, {22}, object, (device-sycl) +// CHK-ADD-TARGETS-REG-MUL: 24: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {17}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {19}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {21}, "device-sycl (spir64_x86_64-unknown-unknown-sycldevice)" {23}, image /// ########################################################################### @@ -611,9 +621,10 @@ // FOFFLOAD_STATIC_LIB_SRC: 11: compiler, {3}, ir, (device-sycl) // FOFFLOAD_STATIC_LIB_SRC: 12: backend, {11}, assembler, (device-sycl) // FOFFLOAD_STATIC_LIB_SRC: 13: assembler, {12}, object, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC: 14: linker, {13, 9}, spirv, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC: 15: clang-offload-wrapper, {14}, object, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC: 16: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64-unknown-unknown-sycldevice)" {15}, image +// FOFFLOAD_STATIC_LIB_SRC: 14: linker, {13, 9}, ir, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 15: llvm-spirv, {14}, spirv, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 16: clang-offload-wrapper, {15}, object, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64-unknown-unknown-sycldevice)" {16}, image /// ########################################################################### @@ -677,13 +688,14 @@ // CHK-PHASES-AOT: 10: compiler, {3}, ir, (device-sycl) // CHK-PHASES-AOT: 11: backend, {10}, assembler, (device-sycl) // CHK-PHASES-AOT: 12: assembler, {11}, object, (device-sycl) -// CHK-PHASES-AOT: 13: linker, {12}, spirv, (device-sycl) -// CHK-PHASES-GEN: 14: backend-compiler, {13}, image, (device-sycl) -// CHK-PHASES-FPGA: 14: backend-compiler, {13}, fpga-aocx, (device-sycl) -// CHK-PHASES-AOT: 15: clang-offload-wrapper, {14}, object, (device-sycl) -// CHK-PHASES-FPGA: 16: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {15}, image -// CHK-PHASES-GEN: 16: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {15}, image -// CHK-PHASES-CPU: 16: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_x86_64-unknown-unknown-sycldevice)" {15}, image +// CHK-PHASES-AOT: 13: linker, {12}, ir, (device-sycl) +// CHK-PHASES-AOT: 14: llvm-spirv, {13}, spirv, (device-sycl) +// CHK-PHASES-GEN: 15: backend-compiler, {14}, image, (device-sycl) +// CHK-PHASES-FPGA: 15: backend-compiler, {14}, fpga-aocx, (device-sycl) +// CHK-PHASES-AOT: 16: clang-offload-wrapper, {15}, object, (device-sycl) +// CHK-PHASES-FPGA: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {16}, image +// CHK-PHASES-GEN: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {16}, image +// CHK-PHASES-CPU: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_x86_64-unknown-unknown-sycldevice)" {16}, image /// ########################################################################### @@ -698,7 +710,7 @@ // RUN: | FileCheck %s -check-prefixes=CHK-TOOLS-AOT,CHK-TOOLS-CPU // CHK-TOOLS-AOT: clang{{.*}} "-fsycl-is-device" {{.*}} "-o" "[[OUTPUT1:.+\.o]]" // CHK-TOOLS-AOT: llvm-link{{.*}} "[[OUTPUT1]]" "-o" "[[OUTPUT2:.+\.bc]]" -// CHK-TOOLS-AOT: llvm-spirv{{.*}} "-o" "[[OUTPUT3:.+\.spv]]" "[[OUTPUT2]]" +// CHK-TOOLS-AOT: llvm-spirv{{.*}} "-o" "[[OUTPUT3:.+\.spv]]" "-spirv-max-version=1.1" "-spirv-ext=+all" "[[OUTPUT2]]" // CHK-TOOLS-FPGA: aoc{{.*}} "-o" "[[OUTPUT4:.+\.aocx]]" "[[OUTPUT3]]" // CHK-TOOLS-GEN: ocloc{{.*}} "-output" "[[OUTPUT4:.+\.out]]" {{.*}} "[[OUTPUT3]]" // CHK-TOOLS-CPU: ioc{{.*}} "-ir=[[OUTPUT4:.+\.out]]" {{.*}} "-binary=[[OUTPUT3]]" @@ -752,23 +764,26 @@ // CHK-PHASE-MULTI-TARG: 12: compiler, {11}, ir, (device-sycl) // CHK-PHASE-MULTI-TARG: 13: backend, {12}, assembler, (device-sycl) // CHK-PHASE-MULTI-TARG: 14: assembler, {13}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG: 15: linker, {14}, spirv, (device-sycl) -// CHK-PHASE-MULTI-TARG: 16: clang-offload-wrapper, {15}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG: 17: input, "[[INPUT]]", c, (device-sycl) -// CHK-PHASE-MULTI-TARG: 18: preprocessor, {17}, cpp-output, (device-sycl) -// CHK-PHASE-MULTI-TARG: 19: compiler, {18}, ir, (device-sycl) -// CHK-PHASE-MULTI-TARG: 20: backend, {19}, assembler, (device-sycl) -// CHK-PHASE-MULTI-TARG: 21: assembler, {20}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG: 22: linker, {21}, spirv, (device-sycl) -// CHK-PHASE-MULTI-TARG: 23: backend-compiler, {22}, fpga-aocx, (device-sycl) -// CHK-PHASE-MULTI-TARG: 24: clang-offload-wrapper, {23}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG: 25: compiler, {3}, ir, (device-sycl) -// CHK-PHASE-MULTI-TARG: 26: backend, {25}, assembler, (device-sycl) -// CHK-PHASE-MULTI-TARG: 27: assembler, {26}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG: 28: linker, {27}, spirv, (device-sycl) -// CHK-PHASE-MULTI-TARG: 29: backend-compiler, {28}, image, (device-sycl) -// CHK-PHASE-MULTI-TARG: 30: clang-offload-wrapper, {29}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG: 31: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {16}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {24}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {30}, image +// CHK-PHASE-MULTI-TARG: 15: linker, {14}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG: 16: llvm-spirv, {15}, spirv, (device-sycl) +// CHK-PHASE-MULTI-TARG: 17: clang-offload-wrapper, {16}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG: 18: input, "[[INPUT]]", c, (device-sycl) +// CHK-PHASE-MULTI-TARG: 19: preprocessor, {18}, cpp-output, (device-sycl) +// CHK-PHASE-MULTI-TARG: 20: compiler, {19}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG: 21: backend, {20}, assembler, (device-sycl) +// CHK-PHASE-MULTI-TARG: 22: assembler, {21}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG: 23: linker, {22}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG: 24: llvm-spirv, {23}, spirv, (device-sycl) +// CHK-PHASE-MULTI-TARG: 25: backend-compiler, {24}, fpga-aocx, (device-sycl) +// CHK-PHASE-MULTI-TARG: 26: clang-offload-wrapper, {25}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG: 27: compiler, {3}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG: 28: backend, {27}, assembler, (device-sycl) +// CHK-PHASE-MULTI-TARG: 29: assembler, {28}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG: 30: linker, {29}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG: 31: llvm-spirv, {30}, spirv, (device-sycl) +// CHK-PHASE-MULTI-TARG: 32: backend-compiler, {31}, image, (device-sycl) +// CHK-PHASE-MULTI-TARG: 33: clang-offload-wrapper, {32}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG: 34: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64-unknown-unknown-sycldevice)" {17}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {26}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {33}, image /// ########################################################################### @@ -791,24 +806,26 @@ // CHK-PHASE-MULTI-TARG-W-ADD: 12: compiler, {11}, ir, (device-sycl) // CHK-PHASE-MULTI-TARG-W-ADD: 13: backend, {12}, assembler, (device-sycl) // CHK-PHASE-MULTI-TARG-W-ADD: 14: assembler, {13}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 15: linker, {14}, spirv, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 16: backend-compiler, {15}, fpga-aocx, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 17: clang-offload-wrapper, {16}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 18: input, "[[INPUT]]", c, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 19: preprocessor, {18}, cpp-output, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 20: compiler, {19}, ir, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 21: backend, {20}, assembler, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 22: assembler, {21}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 23: linker, {22}, spirv, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 24: backend-compiler, {23}, image, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 25: clang-offload-wrapper, {24}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 26: input, "dummy.ir", sycl-fatbin, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 15: linker, {14}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 16: llvm-spirv, {15}, spirv, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 17: backend-compiler, {16}, fpga-aocx, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 18: clang-offload-wrapper, {17}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 19: input, "[[INPUT]]", c, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 20: preprocessor, {19}, cpp-output, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 21: compiler, {20}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 22: backend, {21}, assembler, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 23: assembler, {22}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 24: linker, {23}, ir, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 25: llvm-spirv, {24}, spirv, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 26: backend-compiler, {25}, image, (device-sycl) // CHK-PHASE-MULTI-TARG-W-ADD: 27: clang-offload-wrapper, {26}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 28: input, "dummy.aocx", sycl-fatbin, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 28: input, "dummy.ir", sycl-fatbin, (device-sycl) // CHK-PHASE-MULTI-TARG-W-ADD: 29: clang-offload-wrapper, {28}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 30: input, "dummy_Gen9core.bin", sycl-fatbin, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 30: input, "dummy.aocx", sycl-fatbin, (device-sycl) // CHK-PHASE-MULTI-TARG-W-ADD: 31: clang-offload-wrapper, {30}, object, (device-sycl) -// CHK-PHASE-MULTI-TARG-W-ADD: 32: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {17}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {25}, "device-sycl (spir64_x86_64-unknown-unknown-sycldevice)" {27}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {29}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {31}, image +// CHK-PHASE-MULTI-TARG-W-ADD: 32: input, "dummy_Gen9core.bin", sycl-fatbin, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 33: clang-offload-wrapper, {32}, object, (device-sycl) +// CHK-PHASE-MULTI-TARG-W-ADD: 34: offload, "host-sycl (x86_64-unknown-linux-gnu)" {9}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {18}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {27}, "device-sycl (spir64_x86_64-unknown-unknown-sycldevice)" {29}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {31}, "device-sycl (spir64_gen-unknown-unknown-sycldevice)" {33}, image /// ########################################################################### /// Verify that -save-temps does not crash diff --git a/llvm/tools/sycl-post-link/sycl-post-link.cpp b/llvm/tools/sycl-post-link/sycl-post-link.cpp index d0bd2e646f834..73f40d364a61a 100644 --- a/llvm/tools/sycl-post-link/sycl-post-link.cpp +++ b/llvm/tools/sycl-post-link/sycl-post-link.cpp @@ -24,6 +24,7 @@ #include "llvm/IRReader/IRReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/Path.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Utils/Cloning.h" @@ -226,10 +227,29 @@ static void saveResults(std::vector> &ResModules, ++NumOfFile; } - if (OutputIRFilesList != "-") + if (OutputIRFilesList != "-") { + // TODO: Figure out what can be added to the output list if there are no + // kernels in the input module. + // Just pass input module to next tools if there was nothing to split. + if (IRFilesList.empty()) + IRFilesList = + (Twine(InputFilename) + Twine("\n")).str(); writeToFile(OutputIRFilesList, IRFilesList); - if (OutputTxtFilesList != "-") + } + if (OutputTxtFilesList != "-") { + // TODO: Figure out what can be added to output list if there are no kernels + // in the input module. + if (TxtFilesList.empty()) { + // Just create an empty temporary file if there was nothing to split + std::string TempFileNameBase = sys::path::stem(BaseOutputFilename); + SmallString<128> Path; + std::error_code EC = + sys::fs::createTemporaryFile(TempFileNameBase, "txt", Path); + error(EC, "Could not create a file for command output."); + TxtFilesList = (Twine(Path) + Twine("\n")).str(); + } writeToFile(OutputTxtFilesList, TxtFilesList); + } } int main(int argc, char **argv) {