[clang] releand "[clang-repl] Implement IncrementalHIPDeviceParser for HIP device compilation" (PR #226930)
Aditya Sinha via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 28 03:52:52 PDT 2026
https://github.com/AdityaSinha149 updated https://github.com/llvm/llvm-project/pull/226930
>From b9e49347a48780dfa7ab701c1c0052186eb94d85 Mon Sep 17 00:00:00 2001
From: AdityaSinha149 <adsinha at amd.com>
Date: Sat, 26 Sep 2026 01:54:47 +0530
Subject: [PATCH] [clang-repl] Made IncrementalHipDeviceParser class
---
clang/include/clang/CodeGen/CodeGenAction.h | 5 +
clang/include/clang/Interpreter/Interpreter.h | 4 +-
clang/lib/CodeGen/BackendConsumer.h | 8 +
clang/lib/CodeGen/CodeGenAction.cpp | 9 +
clang/lib/Interpreter/CMakeLists.txt | 2 +
clang/lib/Interpreter/DeviceOffload.cpp | 217 +++++++++++++++++-
clang/lib/Interpreter/DeviceOffload.h | 64 +++++-
clang/lib/Interpreter/Interpreter.cpp | 7 +-
clang/unittests/Basic/CMakeLists.txt | 1 +
clang/unittests/Basic/TargetIDTest.cpp | 50 ++++
10 files changed, 342 insertions(+), 25 deletions(-)
create mode 100644 clang/unittests/Basic/TargetIDTest.cpp
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/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 4504b679504e0..b45c61a199f35 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -44,7 +44,7 @@ class CompilerInstance;
class CXXRecordDecl;
class Decl;
class IncrementalParser;
-class IncrementalCUDADeviceParser;
+class IncrementalDeviceParser;
enum class OffloadType { CUDA, HIP };
@@ -131,7 +131,7 @@ class Interpreter {
std::unique_ptr<IncrementalExecutor> IncrExecutor;
// An optional parser for CUDA offloading
- std::unique_ptr<IncrementalCUDADeviceParser> DeviceParser;
+ std::unique_ptr<IncrementalDeviceParser> DeviceParser;
// An optional action for CUDA offloading
std::unique_ptr<IncrementalAction> DeviceAct;
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 21e58c4aea8c8..c6020dc04a9c2 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -983,6 +983,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/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt
index 01d3295d1ac30..bbe1e804209c8 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -38,6 +38,8 @@ add_clang_library(clangInterpreter
intrinsics_gen
ClangDriverOptions
+ target_parser_gen
+
LINK_LIBS
clangAST
clangAnalysis
diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp
index bf7653c518c30..8f59b569600be 100644
--- a/clang/lib/Interpreter/DeviceOffload.cpp
+++ b/clang/lib/Interpreter/DeviceOffload.cpp
@@ -6,32 +6,228 @@
//
//===----------------------------------------------------------------------===//
//
-// 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/TargetID.h"
#include "clang/Basic/TargetOptions.h"
-#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/CodeGen/CodeGenAction.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"
+#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/AMDGPUTargetParser.h"
+#include "llvm/TargetParser/Host.h"
namespace clang {
-IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
+IncrementalDeviceParser::IncrementalDeviceParser(
CompilerInstance &DeviceInstance, CompilerInstance &HostInstance,
IncrementalAction *DeviceAct,
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs)
- : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs), VFS(FS),
+ : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs),
+ DeviceCI(DeviceInstance), VFS(FS),
CodeGenOpts(HostInstance.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;
+ 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();
+
+ 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, CodeGenOptsForObj, PTU.TheModule.get(),
+ Backend_EmitObj, DeviceCI.getVirtualFileSystemPtr(),
+ std::move(ObjOS));
+
+ if (DeviceCI.getDiagnostics().hasErrorOccurred())
+ return llvm::make_error<llvm::StringError>(
+ "Backend code generation failed for HIP device code.",
+ llvm::inconvertibleErrorCode());
+
+ 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);
+
+ std::string TargetID = llvm::AMDGPU::TargetID::createFromSubtargetFeatures(
+ DeviceCI.getTarget().getTriple(), TargetOpts.CPU,
+ llvm::join(TargetOpts.Features, ","))
+ .getCanonicalFeatureString();
+
+ llvm::StringRef OffloadKind =
+ (TargetOpts.CodeObjectVersion == llvm::CodeObjectVersionKind::COV_2 ||
+ TargetOpts.CodeObjectVersion == llvm::CodeObjectVersionKind::COV_3)
+ ? "hip"
+ : "hipv4";
+
+ std::string HostTriple = "host-" + llvm::sys::getProcessTriple() + "-";
+ std::string DeviceTriple =
+ OffloadKind.str() + "-" +
+ normalizeForBundler(PTU.TheModule->getTargetTriple(), TargetID) + "-" +
+ TargetID;
+
+ 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();
+}
+
+llvm::Error IncrementalHIPDeviceParser::GenerateOffloadBinary() {
+ llvm::Expected<llvm::StringRef> HSACO = GenerateHSACO();
+ if (!HSACO)
+ return HSACO.takeError();
+ return GenerateOffloadBundle();
+}
+
+IncrementalHIPDeviceParser::~IncrementalHIPDeviceParser() {}
+
+IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
+ 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;
@@ -68,9 +264,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)
@@ -158,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 a31bd5a0499b8..45a3fc17c065e 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,11 @@
#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 clang {
struct PartialTranslationUnit;
class CompilerInstance;
@@ -24,7 +26,52 @@ class CodeGenOptions;
class TargetOptions;
class IncrementalAction;
-class IncrementalCUDADeviceParser : 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(
+ 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::Error GenerateOffloadBinary() override;
+
+ ~IncrementalHIPDeviceParser();
+
+protected:
+ // 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;
+};
+
+class IncrementalCUDADeviceParser : public IncrementalDeviceParser {
public:
IncrementalCUDADeviceParser(
@@ -33,21 +80,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;
};
} // namespace clang
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 655db32477a0c..8aafbc867ddaf 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -576,12 +576,7 @@ Interpreter::Parse(llvm::StringRef Code) {
DeviceParser->RegisterPTU(*DeviceTU);
- llvm::Expected<llvm::StringRef> PTX = DeviceParser->GeneratePTX();
- if (!PTX)
- return PTX.takeError();
-
- llvm::Error Err = DeviceParser->GenerateFatbinary();
- if (Err)
+ if (llvm::Error Err = DeviceParser->GenerateOffloadBinary())
return std::move(Err);
}
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..a4eaa06b074f8
--- /dev/null
+++ b/clang/unittests/Basic/TargetIDTest.cpp
@@ -0,0 +1,50 @@
+//===- 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 "clang/Basic/TargetID.h"
+#include "llvm/TargetParser/AMDGPUTargetParser.h"
+#include "llvm/TargetParser/Triple.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+static std::string bundleEntryID(const llvm::Triple &T, llvm::StringRef CPU,
+ llvm::StringRef Features,
+ llvm::StringRef OffloadKind) {
+ std::string TargetID =
+ llvm::AMDGPU::TargetID::createFromSubtargetFeatures(T, CPU, Features)
+ .getCanonicalFeatureString();
+ return OffloadKind.str() + "-" + clang::normalizeForBundler(T, TargetID) +
+ "-" + TargetID;
+}
+
+TEST(TargetIDTest, HIPBundleEntryPreservesXnack) {
+ llvm::Triple T("amdgcn-amd-amdhsa");
+ EXPECT_EQ(bundleEntryID(T, "gfx90a", "+xnack,+wavefrontsize64", "hipv4"),
+ "hipv4-amdgcn-amd-amdhsa--gfx90a:xnack+");
+}
+
+TEST(TargetIDTest, HIPBundleEntryPreservesDisabledFeature) {
+ llvm::Triple T("amdgcn-amd-amdhsa");
+ EXPECT_EQ(bundleEntryID(T, "gfx90a", "-xnack", "hipv4"),
+ "hipv4-amdgcn-amd-amdhsa--gfx90a:xnack-");
+}
+
+TEST(TargetIDTest, HIPBundleEntryWithoutFeatures) {
+ llvm::Triple T("amdgcn-amd-amdhsa");
+ EXPECT_EQ(bundleEntryID(T, "gfx90a", "", "hipv4"),
+ "hipv4-amdgcn-amd-amdhsa--gfx90a");
+}
+
+TEST(TargetIDTest, HIPBundleEntryLegacyKind) {
+ llvm::Triple T("amdgcn-amd-amdhsa");
+ EXPECT_EQ(bundleEntryID(T, "gfx908", "+sramecc", "hip"),
+ "hip-amdgcn-amd-amdhsa--gfx908:sramecc+");
+}
+
+} // namespace
More information about the cfe-commits
mailing list