llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Aditya Sinha (AdityaSinha149) <details> <summary>Changes</summary> This PR adds a hidden `-hip` option to clang-repl, with `-rocm-path` for the SDK location. It sets up the HIP host and device compilers and the HIP device parser. HIP code doesn't execute yet, because binary generation is still a stub that returns an unsupported error. That will come in follow-up PRs. I have also added a lit test in `clang/test/Interpreter/HIP` which runs clang repl with the option hip and expects for not supported message for now. This test will be removed in the future PR when the HIP kernel will be built. Prerequisite PR : #<!-- -->231391 Assisted by Claude Sonnet 5.5 --- Full diff: https://github.com/llvm/llvm-project/pull/231783.diff 6 Files Affected: - (modified) clang/include/clang/Interpreter/Interpreter.h (+11-9) - (modified) clang/lib/Interpreter/Interpreter.cpp (+24-20) - (added) clang/test/Interpreter/HIP/hip-not-supported.hip (+11) - (added) clang/test/Interpreter/HIP/lit.local.cfg (+12) - (modified) clang/tools/clang-repl/ClangRepl.cpp (+29-19) - (modified) clang/unittests/Interpreter/DeviceOffloadTest.cpp (+8-8) ``````````diff diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 64f02b797c204f..64dee1cf80db8d 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -69,28 +69,33 @@ class IncrementalCompilerBuilder { // Offload options void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; }; - // CUDA specific - void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; + // The SDK path (CUDA or ROCm) of the device language being offloaded to. + void SetDeviceSDK(llvm::StringRef Path) { DeviceSDKPath = Path; } // Hand over the compilation. void SetDriverCompilationCallback(std::function<DriverCompilationFn> C) { CompilationCB = C; } - llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost(); - llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice(); + llvm::Expected<std::unique_ptr<CompilerInstance>> + CreateHost(OffloadType Type); + llvm::Expected<std::unique_ptr<CompilerInstance>> + CreateDevice(OffloadType Type); private: llvm::Expected<std::unique_ptr<CompilerInstance>> create(std::string TT, std::vector<const char *> &ClangArgv); - llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device); + llvm::Expected<std::unique_ptr<CompilerInstance>> + createOffload(bool device, OffloadType Type = OffloadType::Detect); std::vector<const char *> UserArgs; std::optional<std::string> TargetTriple; llvm::StringRef OffloadArch; - llvm::StringRef CudaSDKPath; + llvm::StringRef DeviceSDKPath; + + std::string OffloadCUID; std::optional<std::function<DriverCompilationFn>> CompilationCB; }; @@ -154,9 +159,6 @@ class Interpreter { createWithDevice(std::unique_ptr<CompilerInstance> CI, std::unique_ptr<CompilerInstance> DCI, OffloadType Type = OffloadType::Detect); - static llvm::Expected<std::unique_ptr<Interpreter>> - createWithCUDA(std::unique_ptr<CompilerInstance> CI, - std::unique_ptr<CompilerInstance> DCI); const ASTContext &getASTContext() const; ASTContext &getASTContext(); diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 9bd711c24be26d..ae88c5e1a6346f 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -45,12 +45,14 @@ #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ModuleCache.h" #include "clang/Serialization/ObjectFilePCHContainerReader.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/IR/Module.h" #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Process.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" @@ -304,19 +306,21 @@ IncrementalCompilerBuilder::CreateCpp() { } llvm::Expected<std::unique_ptr<CompilerInstance>> -IncrementalCompilerBuilder::createCuda(bool device) { +IncrementalCompilerBuilder::createOffload(bool device, OffloadType Type) { + if (Type == OffloadType::Detect) + return llvm::make_error<llvm::StringError>( + "Detecting the device vendor is not supported yet.", + llvm::inconvertibleErrorCode()); + + const bool HipEnabled = Type == OffloadType::HIP; std::vector<const char *> Argv; Argv.reserve(5 + 4 + UserArgs.size()); + Argv.push_back(HipEnabled ? "-xhip" : "-xcuda"); + Argv.push_back(device ? "--cuda-device-only" : "--cuda-host-only"); - Argv.push_back("-xcuda"); - if (device) - Argv.push_back("--cuda-device-only"); - else - Argv.push_back("--cuda-host-only"); - - std::string SDKPathArg = "--cuda-path="; - if (!CudaSDKPath.empty()) { - SDKPathArg += CudaSDKPath; + std::string SDKPathArg = HipEnabled ? "--rocm-path=" : "--cuda-path="; + if (!DeviceSDKPath.empty()) { + SDKPathArg += DeviceSDKPath; Argv.push_back(SDKPathArg.c_str()); } @@ -326,6 +330,12 @@ IncrementalCompilerBuilder::createCuda(bool device) { Argv.push_back(ArchArg.c_str()); } + if (OffloadCUID.empty()) + OffloadCUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(), + /*LowerCase=*/true); + std::string CUIDArg = "-cuid=" + OffloadCUID; + Argv.push_back(CUIDArg.c_str()); + llvm::append_range(Argv, UserArgs); std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); @@ -333,13 +343,13 @@ IncrementalCompilerBuilder::createCuda(bool device) { } llvm::Expected<std::unique_ptr<CompilerInstance>> -IncrementalCompilerBuilder::CreateCudaDevice() { - return IncrementalCompilerBuilder::createCuda(true); +IncrementalCompilerBuilder::CreateDevice(OffloadType Type) { + return IncrementalCompilerBuilder::createOffload(/*device=*/true, Type); } llvm::Expected<std::unique_ptr<CompilerInstance>> -IncrementalCompilerBuilder::CreateCudaHost() { - return IncrementalCompilerBuilder::createCuda(false); +IncrementalCompilerBuilder::CreateHost(OffloadType Type) { + return IncrementalCompilerBuilder::createOffload(/*device=*/false, Type); } Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, @@ -476,12 +486,6 @@ llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::create( return std::move(Interp); } -llvm::Expected<std::unique_ptr<Interpreter>> -Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, - std::unique_ptr<CompilerInstance> DCI) { - return createWithDevice(std::move(CI), std::move(DCI), OffloadType::CUDA); -} - llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::createWithDevice(std::unique_ptr<CompilerInstance> CI, std::unique_ptr<CompilerInstance> DCI, diff --git a/clang/test/Interpreter/HIP/hip-not-supported.hip b/clang/test/Interpreter/HIP/hip-not-supported.hip new file mode 100644 index 00000000000000..add1769b837165 --- /dev/null +++ b/clang/test/Interpreter/HIP/hip-not-supported.hip @@ -0,0 +1,11 @@ +// Check that clang-repl sets up the HIP environment but reports that HIP +// offload binary generation is not supported yet. An explicit --offload-arch +// is passed so the test does not rely on GPU auto-detection. No device code +// is run, so the architecture is arbitrary. +// FIXME: Replace this with real HIP execution tests once the HIP device parser +// can generate offload binaries. + +// RUN: cat %s | clang-repl -hip --offload-arch=gfx1100 2>&1 | FileCheck %s + +__attribute__((device)) void f() {} +// CHECK: HIP offload binary generation is not supported yet. diff --git a/clang/test/Interpreter/HIP/lit.local.cfg b/clang/test/Interpreter/HIP/lit.local.cfg new file mode 100644 index 00000000000000..cc84168b237130 --- /dev/null +++ b/clang/test/Interpreter/HIP/lit.local.cfg @@ -0,0 +1,12 @@ +import ctypes + +if "host-supports-jit" not in config.available_features: + config.unsupported = True +elif "amdgpu-registered-target" not in config.available_features: + config.unsupported = True +else: + # clang-repl loads the HIP runtime on startup, so it must be available. + try: + ctypes.CDLL("libamdhip64.so") + except OSError: + config.unsupported = True diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp index c9873540a5d66b..ec9cf94c89ad88 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -53,6 +53,8 @@ LLVM_ATTRIBUTE_USED int __lsan_is_turned_off() { return 1; } #define DEBUG_TYPE "clang-repl" static llvm::cl::opt<bool> CudaEnabled("cuda", llvm::cl::Hidden); +static llvm::cl::opt<bool> HipEnabled("hip", llvm::cl::Hidden); +static llvm::cl::opt<std::string> RocmPath("rocm-path", llvm::cl::Hidden); static llvm::cl::opt<std::string> CudaPath("cuda-path", llvm::cl::Hidden); static llvm::cl::opt<std::string> OffloadArch("offload-arch", llvm::cl::Hidden); static llvm::cl::OptionCategory OOPCategory("Out-of-process Execution Options"); @@ -310,24 +312,31 @@ int main(int argc, const char **argv) { IEB->SlabAllocateSize = *SizeOrErr; IEB->UseSharedMemory = UseSharedMemory; - std::unique_ptr<clang::CompilerInstance> DeviceCI; - if (CudaEnabled) { - if (!CudaPath.empty()) - CB.SetCudaSDK(CudaPath); + // If both -cuda and -hip are passed, the one that appears later wins. + bool UseHip = HipEnabled && (!CudaEnabled || HipEnabled.getPosition() > + CudaEnabled.getPosition()); + bool DeviceEnabled = HipEnabled || CudaEnabled; - if (OffloadArch.empty()) { - OffloadArch = "sm_35"; - } - CB.SetOffloadArch(OffloadArch); + clang::OffloadType OffloadKind = + UseHip ? clang::OffloadType::HIP : clang::OffloadType::CUDA; + std::string DevicePath = UseHip ? RocmPath : CudaPath; + llvm::StringRef DeviceOffloadArch = !OffloadArch.empty() + ? llvm::StringRef(OffloadArch) + : (UseHip ? "native" : "sm_35"); + + std::unique_ptr<clang::CompilerInstance> DeviceCI; - DeviceCI = ExitOnErr(CB.CreateCudaDevice()); + if (DeviceEnabled) { + CB.SetDeviceSDK(DevicePath); + CB.SetOffloadArch(DeviceOffloadArch); + DeviceCI = ExitOnErr(CB.CreateDevice(OffloadKind)); } // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It // can replace the boilerplate code for creation of the compiler instance. std::unique_ptr<clang::CompilerInstance> CI; - if (CudaEnabled) { - CI = ExitOnErr(CB.CreateCudaHost()); + if (DeviceEnabled) { + CI = ExitOnErr(CB.CreateHost(OffloadKind)); } else { CI = ExitOnErr(CB.CreateCpp()); } @@ -339,20 +348,21 @@ int main(int argc, const char **argv) { // Load any requested plugins. CI->LoadRequestedPlugins(); - if (CudaEnabled) + if (DeviceEnabled) DeviceCI->LoadRequestedPlugins(); std::unique_ptr<clang::Interpreter> Interp; - if (CudaEnabled) { - Interp = ExitOnErr( - clang::Interpreter::createWithCUDA(std::move(CI), std::move(DeviceCI))); + if (DeviceEnabled) { + Interp = ExitOnErr(clang::Interpreter::createWithDevice( + std::move(CI), std::move(DeviceCI), OffloadKind)); - if (CudaPath.empty()) { - ExitOnErr(Interp->LoadDynamicLibrary("libcudart.so")); + const char *RuntimeLib = UseHip ? "libamdhip64.so" : "libcudart.so"; + if (DevicePath.empty()) { + ExitOnErr(Interp->LoadDynamicLibrary(RuntimeLib)); } else { - auto CudaRuntimeLibPath = CudaPath + "/lib/libcudart.so"; - ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str())); + std::string RuntimeLibPath = DevicePath + "/lib/" + RuntimeLib; + ExitOnErr(Interp->LoadDynamicLibrary(RuntimeLibPath.c_str())); } } else { Interp = diff --git a/clang/unittests/Interpreter/DeviceOffloadTest.cpp b/clang/unittests/Interpreter/DeviceOffloadTest.cpp index 039c919fe1e1e0..d3a84fd7bc54ee 100644 --- a/clang/unittests/Interpreter/DeviceOffloadTest.cpp +++ b/clang/unittests/Interpreter/DeviceOffloadTest.cpp @@ -62,10 +62,10 @@ TEST_F(DeviceOffloadTest, FirstDeviceModuleVerifies) { IncrementalCompilerBuilder CB; CB.SetCompilerArgs( {"-nocudainc", "-nocudalib", "-fverify-intermediate-code"}); - auto DeviceCI = llvm::cantFail(CB.CreateCudaDevice()); - auto HostCI = llvm::cantFail(CB.CreateCudaHost()); - auto Interp = llvm::cantFail(Interpreter::createWithCUDA( - std::move(HostCI), std::move(DeviceCI))); + auto DeviceCI = llvm::cantFail(CB.CreateDevice(OffloadType::CUDA)); + auto HostCI = llvm::cantFail(CB.CreateHost(OffloadType::CUDA)); + auto Interp = llvm::cantFail(Interpreter::createWithDevice( + std::move(HostCI), std::move(DeviceCI), OffloadType::CUDA)); llvm::cantFail(Interp->Parse("__attribute__((device)) void f() {}")); exit(0); }, @@ -79,12 +79,12 @@ TEST_F(DeviceOffloadTest, EmptyDeviceModule) { // Without the runtime headers and libdevice no CUDA toolkit is needed. IncrementalCompilerBuilder CB; CB.SetCompilerArgs({"-nocudainc", "-nocudalib"}); - auto DeviceCI = CB.CreateCudaDevice(); + auto DeviceCI = CB.CreateDevice(OffloadType::CUDA); ASSERT_THAT_EXPECTED(DeviceCI, llvm::Succeeded()); - auto HostCI = CB.CreateCudaHost(); + auto HostCI = CB.CreateHost(OffloadType::CUDA); ASSERT_THAT_EXPECTED(HostCI, llvm::Succeeded()); - auto Interp = - Interpreter::createWithCUDA(std::move(*HostCI), std::move(*DeviceCI)); + auto Interp = Interpreter::createWithDevice( + std::move(*HostCI), std::move(*DeviceCI), OffloadType::CUDA); ASSERT_THAT_EXPECTED(Interp, llvm::Succeeded()); // A host-only input leaves the device module without a function. Its PTX `````````` </details> https://github.com/llvm/llvm-project/pull/231783 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
