https://github.com/AdityaSinha149 updated https://github.com/llvm/llvm-project/pull/218337
>From bc15cebb86a412e9a993216b33d1771a69c351e1 Mon Sep 17 00:00:00 2001 From: AdityaSinha149 <[email protected]> Date: Mon, 24 Aug 2026 12:58:31 +0530 Subject: [PATCH 1/2] [clang-repl] Made IncrementalHipDeviceParser class --- clang/include/clang/CodeGen/CodeGenAction.h | 5 + clang/lib/CodeGen/BackendConsumer.h | 8 + clang/lib/CodeGen/CodeGenAction.cpp | 9 + clang/lib/Interpreter/DeviceOffload.cpp | 205 ++++++++++++++++++-- clang/lib/Interpreter/DeviceOffload.h | 38 +++- 5 files changed, 247 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/CodeGen/CodeGenAction.h b/clang/include/clang/CodeGen/CodeGenAction.h index 84fa4549d5033..319cc8f2b14a1 100644 --- a/clang/include/clang/CodeGen/CodeGenAction.h +++ b/clang/include/clang/CodeGen/CodeGenAction.h @@ -63,6 +63,11 @@ class CodeGenAction : public ASTFrontendAction { CodeGenerator *getCodeGenerator() const; + /// Reload the -mlink-builtin-bitcode modules into the backend consumer. + /// LinkInModules() consumes them, so incremental compilation must reload them + /// before each translation unit (e.g. to re-link HIP device libraries). + void reloadLinkModules(CompilerInstance &CI); + BackendConsumer *BEConsumer = nullptr; }; diff --git a/clang/lib/CodeGen/BackendConsumer.h b/clang/lib/CodeGen/BackendConsumer.h index 708658d206baf..d6d713844a195 100644 --- a/clang/lib/CodeGen/BackendConsumer.h +++ b/clang/lib/CodeGen/BackendConsumer.h @@ -92,6 +92,14 @@ class BackendConsumer : public ASTConsumer { // Links each entry in LinkModules into our module. Returns true on error. bool LinkInModules(llvm::Module *M); + /// Replace the set of modules to link in. LinkInModules() consumes the + /// modules, so incremental compilation (clang-repl) must reload and reseed + /// them before each translation unit; otherwise later inputs would miss the + /// linked-in bitcode (e.g. HIP device libraries). + void setLinkModules(SmallVector<LinkModule, 4> LMs) { + LinkModules = std::move(LMs); + } + /// Get the best possible source location to represent a diagnostic that /// may have associated debug info. const FullSourceLoc getBestLocationFromDebugLoc( diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 6911cab379fdc..c8b4b9de48983 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -984,6 +984,15 @@ CodeGenerator *CodeGenAction::getCodeGenerator() const { return BEConsumer->getCodeGenerator(); } +void CodeGenAction::reloadLinkModules(CompilerInstance &CI) { + if (!BEConsumer) + return; + SmallVector<LinkModule, 4> LMs; + if (clang::loadLinkModules(CI, *VMContext, LMs)) + return; + BEConsumer->setLinkModules(std::move(LMs)); +} + bool CodeGenAction::BeginSourceFileAction(CompilerInstance &CI) { if (CI.getFrontendOpts().GenReducedBMI) CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface); diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp index 38cecd142a8e6..bfa733585b2a9 100644 --- a/clang/lib/Interpreter/DeviceOffload.cpp +++ b/clang/lib/Interpreter/DeviceOffload.cpp @@ -6,24 +6,205 @@ // //===----------------------------------------------------------------------===// // -// This file implements offloading to CUDA devices. +// This file implements offloading to HIP and CUDA devices. // //===----------------------------------------------------------------------===// #include "DeviceOffload.h" +#include "IncrementalAction.h" #include "clang/Basic/TargetOptions.h" +#include "clang/CodeGen/BackendUtil.h" +#include "clang/CodeGen/CodeGenAction.h" #include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Driver/OffloadBundler.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" #include "clang/Interpreter/PartialTranslationUnit.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/Transforms/IPO/Internalize.h" namespace clang { +static llvm::Expected<llvm::TargetMachine *> +getOrCreateTargetMachine(std::unique_ptr<llvm::TargetMachine> &Cache, + llvm::Module &M, llvm::StringRef CPU) { + if (!Cache) { + std::string Error; + const llvm::Target *Target = + llvm::TargetRegistry::lookupTarget(M.getTargetTriple(), Error); + if (!Target) + return llvm::make_error<llvm::StringError>(std::move(Error), + std::error_code()); + llvm::TargetOptions TO = llvm::TargetOptions(); + Cache.reset(Target->createTargetMachine(M.getTargetTriple(), CPU, "", TO, + llvm::Reloc::Model::PIC_)); + } + M.setDataLayout(Cache->createDataLayout()); + return Cache.get(); +} + +IncrementalHIPDeviceParser::IncrementalHIPDeviceParser( + CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS, + llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs) + : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs), + DeviceCI(DeviceInstance), VFS(FS), + CodeGenOpts(HostInstance.getCodeGenOpts()), + DeviceCodeGenOpts(DeviceInstance.getCodeGenOpts()), + TargetOpts(DeviceInstance.getTargetOpts()) { + if (Err) + return; + StringRef Arch = TargetOpts.CPU; + if (!Arch.starts_with("gfx")) { + Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>( + "Invalid HIP architecture", + llvm::inconvertibleErrorCode())); + return; + } +} + +llvm::Expected<TranslationUnitDecl *> +IncrementalHIPDeviceParser::Parse(llvm::StringRef Input) { + if (FrontendAction *WrappedAct = Act->getWrapped()) + if (WrappedAct->hasIRSupport()) + static_cast<CodeGenAction *>(WrappedAct)->reloadLinkModules(DeviceCI); + + return IncrementalParser::Parse(Input); +} + +llvm::Expected<llvm::StringRef> IncrementalHIPDeviceParser::GenerateHSACO() { + auto &PTU = PTUs.back(); + + llvm::SmallVector<char, 0> Object; + auto ObjOS = std::make_unique<llvm::raw_svector_ostream>(Object); + clang::emitBackendOutput( + DeviceCI, DeviceCI.getCodeGenOpts(), + DeviceCI.getTarget().getDataLayoutString(), PTU.TheModule.get(), + Backend_EmitObj, DeviceCI.getVirtualFileSystemPtr(), std::move(ObjOS)); + + std::string Exe = llvm::sys::fs::getMainExecutable(nullptr, nullptr); + llvm::StringRef ExeDir = llvm::sys::path::parent_path(Exe); + llvm::ErrorOr<std::string> LLDPath = + llvm::sys::findProgramByName("ld.lld", {ExeDir}); + if (!LLDPath) + LLDPath = llvm::sys::findProgramByName("ld.lld"); + if (!LLDPath) + return llvm::make_error<llvm::StringError>( + "Could not find ld.lld next to the executable or on PATH.", + llvm::inconvertibleErrorCode()); + + int ObjFD = -1; + llvm::SmallString<128> ObjFile; + if (llvm::sys::fs::createTemporaryFile("kernel", "o", ObjFD, ObjFile)) + return llvm::make_error<llvm::StringError>( + "Failed to create a temporary object file.", + llvm::inconvertibleErrorCode()); + llvm::FileRemover ObjRemover(ObjFile); + { + llvm::raw_fd_ostream OS(ObjFD, /*shouldClose=*/true); + OS << llvm::StringRef(Object.data(), Object.size()); + } + + llvm::SmallString<128> HsacoFile; + if (llvm::sys::fs::createTemporaryFile("kernel", "hsaco", HsacoFile)) + return llvm::make_error<llvm::StringError>( + "Failed to create a temporary code object file.", + llvm::inconvertibleErrorCode()); + llvm::FileRemover HsacoRemover(HsacoFile); + + llvm::StringRef Args[] = {"ld.lld", "-shared", "--no-undefined", + ObjFile, "-o", HsacoFile}; + if (llvm::sys::ExecuteAndWait(*LLDPath, Args) != 0) + return llvm::make_error<llvm::StringError>("ld.lld invocation failed.", + llvm::inconvertibleErrorCode()); + + auto HsacoBuf = llvm::MemoryBuffer::getFile(HsacoFile, /*IsText=*/false); + if (!HsacoBuf) + return llvm::make_error<llvm::StringError>( + "Failed to read the code object.", llvm::inconvertibleErrorCode()); + + llvm::StringRef Buffer = (*HsacoBuf)->getBuffer(); + HSACOContent.assign(Buffer.begin(), Buffer.end()); + return llvm::StringRef(HSACOContent.data(), HSACOContent.size()); +} + +llvm::Error IncrementalHIPDeviceParser::GenerateOffloadBundle() { + static constexpr unsigned CodeObjectAlign = 4096; + + const PartialTranslationUnit &PTU = PTUs.back(); + + llvm::SmallString<128> HostFile; + if (llvm::sys::fs::createTemporaryFile("hip-host", "", HostFile)) + return llvm::make_error<llvm::StringError>( + "Failed to create a temporary host bundle input.", + llvm::inconvertibleErrorCode()); + llvm::FileRemover HostRemover(HostFile); + + llvm::SmallString<128> DeviceFile; + int DeviceFD = -1; + if (llvm::sys::fs::createTemporaryFile("hip-device", "hsaco", DeviceFD, + DeviceFile)) + return llvm::make_error<llvm::StringError>( + "Failed to create a temporary code object file.", + llvm::inconvertibleErrorCode()); + llvm::FileRemover DeviceRemover(DeviceFile); + { + llvm::raw_fd_ostream OS(DeviceFD, /*shouldClose=*/true); + OS << llvm::StringRef(HSACOContent.data(), HSACOContent.size()); + } + + llvm::SmallString<128> BundleFile; + if (llvm::sys::fs::createTemporaryFile("hip-bundle", "hipfb", BundleFile)) + return llvm::make_error<llvm::StringError>( + "Failed to create a temporary offload bundle file.", + llvm::inconvertibleErrorCode()); + llvm::FileRemover BundleRemover(BundleFile); + + // Triples use the normalized 4-field form ending in a dash; the device entry + // additionally appends the offload arch, e.g. + // "hip-amdgcn-amd-amdhsa--gfx90a". + std::string HostTriple = "host-" + llvm::sys::getProcessTriple() + "-"; + std::string DeviceTriple = + "hip-" + PTU.TheModule->getTargetTriple().str() + "--" + TargetOpts.CPU; + + OffloadBundlerConfig Config; + Config.FilesType = "o"; + Config.BundleAlignment = CodeObjectAlign; + Config.HostInputIndex = 0; + Config.TargetNames = {HostTriple, DeviceTriple}; + Config.InputFileNames = {std::string(HostFile), std::string(DeviceFile)}; + Config.OutputFileNames = {std::string(BundleFile)}; + + if (llvm::Error Err = OffloadBundler(Config).BundleFiles()) + return Err; + + auto BundleBuf = llvm::MemoryBuffer::getFile(BundleFile, /*IsText=*/false); + if (!BundleBuf) + return llvm::make_error<llvm::StringError>( + "Failed to read the offload bundle.", llvm::inconvertibleErrorCode()); + + std::string BundleFileName = "/" + PTU.TheModule->getName().str() + ".hipfb"; + VFS->addFile(BundleFileName, 0, + llvm::MemoryBuffer::getMemBufferCopy((*BundleBuf)->getBuffer())); + + CodeGenOpts.OffloadBinaryToEmbedFile = std::move(BundleFileName); + return llvm::Error::success(); +} + +IncrementalHIPDeviceParser::~IncrementalHIPDeviceParser() {} + IncrementalCUDADeviceParser::IncrementalCUDADeviceParser( CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, IncrementalAction *DeviceAct, @@ -45,18 +226,12 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser( llvm::Expected<llvm::StringRef> IncrementalCUDADeviceParser::GeneratePTX() { auto &PTU = PTUs.back(); - std::string Error; - - const llvm::Target *Target = llvm::TargetRegistry::lookupTarget( - PTU.TheModule->getTargetTriple(), Error); - if (!Target) - return llvm::make_error<llvm::StringError>(std::move(Error), - std::error_code()); - llvm::TargetOptions TO = llvm::TargetOptions(); - llvm::TargetMachine *TargetMachine = Target->createTargetMachine( - PTU.TheModule->getTargetTriple(), TargetOpts.CPU, "", TO, - llvm::Reloc::Model::PIC_); - PTU.TheModule->setDataLayout(TargetMachine->createDataLayout()); + + llvm::Expected<llvm::TargetMachine *> TMOrErr = + getOrCreateTargetMachine(TM, *PTU.TheModule, TargetOpts.CPU); + if (!TMOrErr) + return TMOrErr.takeError(); + llvm::TargetMachine *TargetMachine = *TMOrErr; PTXCode.clear(); llvm::raw_svector_ostream dest(PTXCode); @@ -69,9 +244,7 @@ llvm::Expected<llvm::StringRef> IncrementalCUDADeviceParser::GeneratePTX() { llvm::inconvertibleErrorCode()); } - if (!PM.run(*PTU.TheModule)) - return llvm::make_error<llvm::StringError>("Failed to emit PTX code.", - llvm::inconvertibleErrorCode()); + PM.run(*PTU.TheModule); PTXCode += '\0'; while (PTXCode.size() % 8) diff --git a/clang/lib/Interpreter/DeviceOffload.h b/clang/lib/Interpreter/DeviceOffload.h index a31bd5a0499b8..3e326e566a5bb 100644 --- a/clang/lib/Interpreter/DeviceOffload.h +++ b/clang/lib/Interpreter/DeviceOffload.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements classes required for offloading to CUDA devices. +// This file implements classes required for offloading to HIP and CUDA devices. // //===----------------------------------------------------------------------===// @@ -14,9 +14,15 @@ #define LLVM_CLANG_LIB_INTERPRETER_DEVICE_OFFLOAD_H #include "IncrementalParser.h" -#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Error.h" #include "llvm/Support/VirtualFileSystem.h" +#include <memory> + +namespace llvm { +class TargetMachine; +} // namespace llvm + namespace clang { struct PartialTranslationUnit; class CompilerInstance; @@ -24,6 +30,33 @@ class CodeGenOptions; class TargetOptions; class IncrementalAction; +class IncrementalHIPDeviceParser : public IncrementalParser { + +public: + IncrementalHIPDeviceParser( + CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS, + llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs); + + llvm::Expected<TranslationUnitDecl *> Parse(llvm::StringRef Input) override; + + llvm::Expected<llvm::StringRef> GenerateHSACO(); + + llvm::Error GenerateOffloadBundle(); + + ~IncrementalHIPDeviceParser(); + +protected: + CompilerInstance &DeviceCI; + llvm::SmallVector<char, 1024> HSACOContent; + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS; + CodeGenOptions &CodeGenOpts; // Host opts, intentionally a reference. + const CodeGenOptions &DeviceCodeGenOpts; + const TargetOptions &TargetOpts; + std::unique_ptr<llvm::TargetMachine> TM; +}; + class IncrementalCUDADeviceParser : public IncrementalParser { public: @@ -48,6 +81,7 @@ class IncrementalCUDADeviceParser : public IncrementalParser { llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS; CodeGenOptions &CodeGenOpts; // Intentionally a reference. const TargetOptions &TargetOpts; + std::unique_ptr<llvm::TargetMachine> TM; }; } // namespace clang >From 50fe1c39a4c15733963cbf71eca710e172862ffb Mon Sep 17 00:00:00 2001 From: AdityaSinha149 <[email protected]> Date: Fri, 11 Sep 2026 12:09:57 +0530 Subject: [PATCH 2/2] diabled optimization in GenerateHSACO() --- clang/lib/Interpreter/DeviceOffload.cpp | 57 ++++++++++++++++++------- clang/lib/Interpreter/DeviceOffload.h | 51 ++++++++++++++-------- clang/unittests/Basic/CMakeLists.txt | 1 + clang/unittests/Basic/TargetIDTest.cpp | 37 ++++++++++++++++ 4 files changed, 114 insertions(+), 32 deletions(-) create mode 100644 clang/unittests/Basic/TargetIDTest.cpp diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp index bfa733585b2a9..ee2c49312f912 100644 --- a/clang/lib/Interpreter/DeviceOffload.cpp +++ b/clang/lib/Interpreter/DeviceOffload.cpp @@ -16,12 +16,12 @@ #include "clang/Basic/TargetOptions.h" #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/CodeGenAction.h" -#include "clang/CodeGen/ModuleBuilder.h" #include "clang/Driver/OffloadBundler.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Interpreter/PartialTranslationUnit.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/MC/TargetRegistry.h" @@ -31,8 +31,8 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/AMDGPUTargetParser.h" #include "llvm/TargetParser/Host.h" -#include "llvm/Transforms/IPO/Internalize.h" namespace clang { @@ -54,7 +54,7 @@ getOrCreateTargetMachine(std::unique_ptr<llvm::TargetMachine> &Cache, return Cache.get(); } -IncrementalHIPDeviceParser::IncrementalHIPDeviceParser( +IncrementalDeviceParser::IncrementalDeviceParser( CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, IncrementalAction *DeviceAct, llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS, @@ -62,8 +62,17 @@ IncrementalHIPDeviceParser::IncrementalHIPDeviceParser( : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs), DeviceCI(DeviceInstance), VFS(FS), CodeGenOpts(HostInstance.getCodeGenOpts()), - DeviceCodeGenOpts(DeviceInstance.getCodeGenOpts()), - TargetOpts(DeviceInstance.getTargetOpts()) { + TargetOpts(DeviceInstance.getTargetOpts()) {} + +IncrementalDeviceParser::~IncrementalDeviceParser() {} + +IncrementalHIPDeviceParser::IncrementalHIPDeviceParser( + CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS, + llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs) + : IncrementalDeviceParser(DeviceInstance, HostInstance, DeviceAct, FS, Err, + PTUs) { if (Err) return; StringRef Arch = TargetOpts.CPU; @@ -87,12 +96,15 @@ IncrementalHIPDeviceParser::Parse(llvm::StringRef Input) { llvm::Expected<llvm::StringRef> IncrementalHIPDeviceParser::GenerateHSACO() { auto &PTU = PTUs.back(); + CodeGenOptions CodeGenOptsForObj = DeviceCI.getCodeGenOpts(); + CodeGenOptsForObj.DisableLLVMPasses = true; + llvm::SmallVector<char, 0> Object; auto ObjOS = std::make_unique<llvm::raw_svector_ostream>(Object); clang::emitBackendOutput( - DeviceCI, DeviceCI.getCodeGenOpts(), - DeviceCI.getTarget().getDataLayoutString(), PTU.TheModule.get(), - Backend_EmitObj, DeviceCI.getVirtualFileSystemPtr(), std::move(ObjOS)); + DeviceCI, CodeGenOptsForObj, DeviceCI.getTarget().getDataLayoutString(), + PTU.TheModule.get(), Backend_EmitObj, DeviceCI.getVirtualFileSystemPtr(), + std::move(ObjOS)); std::string Exe = llvm::sys::fs::getMainExecutable(nullptr, nullptr); llvm::StringRef ExeDir = llvm::sys::path::parent_path(Exe); @@ -172,12 +184,14 @@ llvm::Error IncrementalHIPDeviceParser::GenerateOffloadBundle() { llvm::inconvertibleErrorCode()); llvm::FileRemover BundleRemover(BundleFile); - // Triples use the normalized 4-field form ending in a dash; the device entry - // additionally appends the offload arch, e.g. - // "hip-amdgcn-amd-amdhsa--gfx90a". + std::string TargetID = llvm::AMDGPU::TargetID::createFromSubtargetFeatures( + DeviceCI.getTarget().getTriple(), TargetOpts.CPU, + llvm::join(TargetOpts.Features, ",")) + .getCanonicalTargetIDString(); + std::string HostTriple = "host-" + llvm::sys::getProcessTriple() + "-"; std::string DeviceTriple = - "hip-" + PTU.TheModule->getTargetTriple().str() + "--" + TargetOpts.CPU; + "hip-" + PTU.TheModule->getTargetTriple().str() + "--" + TargetID; OffloadBundlerConfig Config; Config.FilesType = "o"; @@ -203,6 +217,13 @@ llvm::Error IncrementalHIPDeviceParser::GenerateOffloadBundle() { return llvm::Error::success(); } +llvm::Error IncrementalHIPDeviceParser::GenerateOffloadBinary() { + llvm::Expected<llvm::StringRef> HSACO = GenerateHSACO(); + if (!HSACO) + return HSACO.takeError(); + return GenerateOffloadBundle(); +} + IncrementalHIPDeviceParser::~IncrementalHIPDeviceParser() {} IncrementalCUDADeviceParser::IncrementalCUDADeviceParser( @@ -210,9 +231,8 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser( IncrementalAction *DeviceAct, llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS, llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs) - : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs), VFS(FS), - CodeGenOpts(HostInstance.getCodeGenOpts()), - TargetOpts(DeviceInstance.getTargetOpts()) { + : IncrementalDeviceParser(DeviceInstance, HostInstance, DeviceAct, FS, Err, + PTUs) { if (Err) return; StringRef Arch = TargetOpts.CPU; @@ -332,6 +352,13 @@ llvm::Error IncrementalCUDADeviceParser::GenerateFatbinary() { return llvm::Error::success(); } +llvm::Error IncrementalCUDADeviceParser::GenerateOffloadBinary() { + llvm::Expected<llvm::StringRef> PTX = GeneratePTX(); + if (!PTX) + return PTX.takeError(); + return GenerateFatbinary(); +} + IncrementalCUDADeviceParser::~IncrementalCUDADeviceParser() {} } // namespace clang diff --git a/clang/lib/Interpreter/DeviceOffload.h b/clang/lib/Interpreter/DeviceOffload.h index 3e326e566a5bb..8885f65f83801 100644 --- a/clang/lib/Interpreter/DeviceOffload.h +++ b/clang/lib/Interpreter/DeviceOffload.h @@ -30,7 +30,27 @@ class CodeGenOptions; class TargetOptions; class IncrementalAction; -class IncrementalHIPDeviceParser : public IncrementalParser { +class IncrementalDeviceParser : public IncrementalParser { + +public: + IncrementalDeviceParser( + CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS, + llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs); + + virtual llvm::Error GenerateOffloadBinary() = 0; + + ~IncrementalDeviceParser() override; + +protected: + CompilerInstance &DeviceCI; + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS; + CodeGenOptions &CodeGenOpts; + const TargetOptions &TargetOpts; +}; + +class IncrementalHIPDeviceParser : public IncrementalDeviceParser { public: IncrementalHIPDeviceParser( @@ -41,23 +61,21 @@ class IncrementalHIPDeviceParser : public IncrementalParser { llvm::Expected<TranslationUnitDecl *> Parse(llvm::StringRef Input) override; - llvm::Expected<llvm::StringRef> GenerateHSACO(); - - llvm::Error GenerateOffloadBundle(); + llvm::Error GenerateOffloadBinary() override; ~IncrementalHIPDeviceParser(); protected: - CompilerInstance &DeviceCI; + // Generate the HSACO code object for the last PTU. + llvm::Expected<llvm::StringRef> GenerateHSACO(); + + // Bundle the HSACO into a HIP offload bundle in memory. + llvm::Error GenerateOffloadBundle(); + llvm::SmallVector<char, 1024> HSACOContent; - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS; - CodeGenOptions &CodeGenOpts; // Host opts, intentionally a reference. - const CodeGenOptions &DeviceCodeGenOpts; - const TargetOptions &TargetOpts; - std::unique_ptr<llvm::TargetMachine> TM; }; -class IncrementalCUDADeviceParser : public IncrementalParser { +class IncrementalCUDADeviceParser : public IncrementalDeviceParser { public: IncrementalCUDADeviceParser( @@ -66,21 +84,20 @@ class IncrementalCUDADeviceParser : public IncrementalParser { llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS, llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs); + llvm::Error GenerateOffloadBinary() override; + + ~IncrementalCUDADeviceParser(); + +protected: // Generate PTX for the last PTU. llvm::Expected<llvm::StringRef> GeneratePTX(); // Generate fatbinary contents in memory llvm::Error GenerateFatbinary(); - ~IncrementalCUDADeviceParser(); - -protected: int SMVersion; llvm::SmallString<1024> PTXCode; llvm::SmallVector<char, 1024> FatbinContent; - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS; - CodeGenOptions &CodeGenOpts; // Intentionally a reference. - const TargetOptions &TargetOpts; std::unique_ptr<llvm::TargetMachine> TM; }; diff --git a/clang/unittests/Basic/CMakeLists.txt b/clang/unittests/Basic/CMakeLists.txt index 32dce09866892..3cd843736eb9b 100644 --- a/clang/unittests/Basic/CMakeLists.txt +++ b/clang/unittests/Basic/CMakeLists.txt @@ -13,6 +13,7 @@ add_distinct_clang_unittest(BasicTests SanitizersTest.cpp SarifTest.cpp SourceManagerTest.cpp + TargetIDTest.cpp CLANG_LIBS clangBasic clangLex diff --git a/clang/unittests/Basic/TargetIDTest.cpp b/clang/unittests/Basic/TargetIDTest.cpp new file mode 100644 index 0000000000000..4d220c8fdb54d --- /dev/null +++ b/clang/unittests/Basic/TargetIDTest.cpp @@ -0,0 +1,37 @@ +//===- unittests/Basic/TargetIDTest.cpp - Test TargetID -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/TargetParser/AMDGPUTargetParser.h" +#include "llvm/TargetParser/Triple.h" +#include "gtest/gtest.h" + +namespace { +static std::string canonicalTargetID(const llvm::Triple &T, llvm::StringRef CPU, + llvm::StringRef Features) { + return llvm::AMDGPU::TargetID::createFromSubtargetFeatures(T, CPU, Features) + .getCanonicalTargetIDString(); +} + +TEST(TargetIDTest, HIPBundleTargetIDPreservesXnack) { + llvm::Triple T("amdgcn-amd-amdhsa"); + // An unrelated feature must not leak into the target ID. + EXPECT_EQ(canonicalTargetID(T, "gfx90a", "+xnack,+wavefrontsize64"), + "gfx90a:xnack+"); +} + +TEST(TargetIDTest, HIPBundleTargetIDPreservesDisabledFeature) { + llvm::Triple T("amdgcn-amd-amdhsa"); + EXPECT_EQ(canonicalTargetID(T, "gfx90a", "-xnack"), "gfx90a:xnack-"); +} + +TEST(TargetIDTest, HIPBundleTargetIDWithoutFeatures) { + llvm::Triple T("amdgcn-amd-amdhsa"); + EXPECT_EQ(canonicalTargetID(T, "gfx90a", ""), "gfx90a"); +} + +} // namespace _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
