-
Notifications
You must be signed in to change notification settings - Fork 16.9k
[HIPSPV] Add in-tree SPIR-V backend support for chipStar #186972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,8 +59,13 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( | |
| // Link LLVM bitcode. | ||
| ArgStringList LinkArgs{}; | ||
|
|
||
| for (auto Input : Inputs) | ||
| LinkArgs.push_back(Input.getFilename()); | ||
| // The new offload driver can pass non-filename InputInfo entries (e.g. | ||
| // Nothing/InputArg placeholders) alongside the real bitcode inputs. Calling | ||
| // getFilename() on those reads garbage from the union; only forward genuine | ||
| // filename inputs to llvm-link. | ||
| for (const auto &Input : Inputs) | ||
| if (Input.isFilename()) | ||
| LinkArgs.push_back(Input.getFilename()); | ||
|
Comment on lines
+66
to
68
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change got introduced in #187655 so a rebase maybe needed before merge. |
||
|
|
||
| // Add static device libraries using the common helper function. | ||
| // This handles unbundling archives (.a) containing bitcode bundles. | ||
|
|
@@ -72,10 +77,55 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( | |
| tools::constructLLVMLinkCommand(C, *this, JA, Inputs, LinkArgs, Output, Args, | ||
| TempFile); | ||
|
|
||
| // Post-link HIP lowering. | ||
| auto T = getToolChain().getTriple(); | ||
|
|
||
| if (T.getOS() == llvm::Triple::ChipStar) { | ||
| // chipStar: run HipSpvPasses via opt, then use the in-tree SPIR-V backend | ||
| // for codegen (replaces the external llvm-spirv translator). | ||
|
pvelesko marked this conversation as resolved.
|
||
|
|
||
| // Run HipSpvPasses plugin via opt (must run on LLVM IR before | ||
| // the SPIR-V backend lowers to MIR). | ||
| auto PassPluginPath = findPassPlugin(C.getDriver(), Args); | ||
| if (!PassPluginPath.empty()) { | ||
| const char *PassPathCStr = C.getArgs().MakeArgString(PassPluginPath); | ||
| const char *OptOutput = HIP::getTempFile(C, Name + "-lower", "bc"); | ||
| ArgStringList OptArgs{TempFile, "-load-pass-plugin", | ||
| PassPathCStr, "-passes=hip-post-link-passes", | ||
| "-o", OptOutput}; | ||
| const char *Opt = | ||
| Args.MakeArgString(getToolChain().GetProgramPath("opt")); | ||
| C.addCommand(std::make_unique<Command>(JA, *this, | ||
| ResponseFileSupport::None(), Opt, | ||
| OptArgs, Inputs, Output)); | ||
| TempFile = OptOutput; | ||
| } | ||
|
Comment on lines
+86
to
+101
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This portion is a duplicate from the below - could you refactor the duplication away? |
||
|
|
||
| // Run LLVM IR passes to lower/expand/emulate HIP code that does not translate | ||
| // to SPIR-V (E.g. dynamic shared memory). | ||
| // Compile processed bitcode to SPIR-V using the in-tree backend. | ||
| ArgStringList ClangArgs; | ||
| ClangArgs.push_back("--no-default-config"); | ||
| ClangArgs.push_back("-c"); | ||
| ClangArgs.push_back(C.getArgs().MakeArgString("--target=" + T.getTriple())); | ||
|
|
||
| ClangArgs.push_back("-mllvm"); | ||
| ClangArgs.push_back("-spirv-ext=+SPV_INTEL_function_pointers" | ||
| ",+SPV_INTEL_subgroups" | ||
| ",+SPV_EXT_relaxed_printf_string_address_space" | ||
| ",+SPV_KHR_bit_instructions" | ||
| ",+SPV_EXT_shader_atomic_float_add"); | ||
|
|
||
| ClangArgs.push_back(TempFile); | ||
| ClangArgs.push_back("-o"); | ||
| ClangArgs.push_back(Output.getFilename()); | ||
|
|
||
| const char *Clang = | ||
| C.getArgs().MakeArgString(C.getDriver().getClangProgramPath()); | ||
|
Comment on lines
+120
to
+121
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using clang driver for emitting SPIR-V (through SPIR-V BE) seems hazarous - it think it's better to use cc1 like HIPAMD does. |
||
| C.addCommand(std::make_unique<Command>(JA, *this, | ||
| ResponseFileSupport::None(), Clang, | ||
| ClangArgs, Inputs, Output)); | ||
| return; | ||
| } | ||
|
|
||
| // Non-chipStar: run HIP passes via opt, then translate with llvm-spirv. | ||
| auto PassPluginPath = findPassPlugin(C.getDriver(), Args); | ||
| if (!PassPluginPath.empty()) { | ||
| const char *PassPathCStr = C.getArgs().MakeArgString(PassPluginPath); | ||
|
|
@@ -89,27 +139,11 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( | |
| TempFile = OptOutput; | ||
| } | ||
|
|
||
| // Emit SPIR-V binary. | ||
| // Emit SPIR-V binary via llvm-spirv translator (non-chipStar targets). | ||
| llvm::opt::ArgStringList TrArgs; | ||
| auto T = getToolChain().getTriple(); | ||
| bool HasNoSubArch = T.getSubArch() == llvm::Triple::NoSubArch; | ||
| if (T.getOS() == llvm::Triple::ChipStar) { | ||
| // chipStar needs 1.2 for supporting warp-level primitivies via sub-group | ||
| // extensions. Strictly put we'd need 1.3 for the standard non-extension | ||
| // shuffle operations, but it's not supported by any backend driver of the | ||
| // chipStar. | ||
| if (HasNoSubArch) | ||
| TrArgs.push_back("--spirv-max-version=1.2"); | ||
| TrArgs.push_back("--spirv-ext=-all" | ||
| // Needed for experimental indirect call support. | ||
| ",+SPV_INTEL_function_pointers" | ||
| // Needed for shuffles below SPIR-V 1.3 | ||
| ",+SPV_INTEL_subgroups"); | ||
| } else { | ||
| if (HasNoSubArch) | ||
| TrArgs.push_back("--spirv-max-version=1.1"); | ||
| TrArgs.push_back("--spirv-ext=+all"); | ||
| } | ||
| if (T.getSubArch() == llvm::Triple::NoSubArch) | ||
| TrArgs.push_back("--spirv-max-version=1.1"); | ||
| TrArgs.push_back("--spirv-ext=+all"); | ||
|
|
||
| InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, ""); | ||
| SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -479,9 +479,25 @@ fatbinary(ArrayRef<std::tuple<StringRef, StringRef, StringRef>> InputFiles, | |
| SmallVector<StringRef> Targets = { | ||
| Saver.save("-targets=host-" + HostTriple.normalize())}; | ||
| for (const auto &[File, TripleRef, Arch] : InputFiles) { | ||
| std::string NormalizedTriple = | ||
| normalizeForBundler(Triple(TripleRef), !Arch.empty()); | ||
| Targets.push_back(Saver.save("hip-" + NormalizedTriple + "-" + Arch)); | ||
| llvm::Triple T(TripleRef); | ||
| // For SPIR-V targets, derive arch from triple if not provided | ||
| StringRef EffectiveArch = Arch; | ||
| if (EffectiveArch.empty() && T.isSPIRV()) { | ||
| EffectiveArch = T.getArchName(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think CPU/GPU model is expected here which is not same thing as what Triple::getArchName() returns. For SPIR-V I think we can set it to "generic" - that's the default model used elsewhere for SPIR-V targets.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, is it a problem if the |
||
| } | ||
| StringRef BundleID; | ||
| if (EffectiveArch == "amdgcnspirv") { | ||
| BundleID = Saver.save("hip-spirv64-amd-amdhsa--" + EffectiveArch); | ||
| } else if (T.isSPIRV()) { | ||
| // ChipStar and other SPIR-V HIP targets: use | ||
| // hip-spirv64-<vendor>-<os>--<arch> | ||
| BundleID = Saver.save("hip-spirv64-" + T.getVendorName() + "-" + | ||
| T.getOSName() + "--" + EffectiveArch); | ||
|
Comment on lines
+493
to
+495
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm lost here - does this fix a breakage for chipStar? I have tested CHIP-SPV/chipStar#1219 locally on couple days old LLVM and I haven't seen issues. I'm wondering if it necessary to have this. |
||
| } else { | ||
| std::string NormalizedTriple = normalizeForBundler(T, !Arch.empty()); | ||
| BundleID = Saver.save("hip-" + NormalizedTriple + "-" + Arch); | ||
| } | ||
| Targets.push_back(BundleID); | ||
| } | ||
| CmdArgs.push_back(Saver.save(llvm::join(Targets, ","))); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -91,7 +91,8 @@ SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, | |
| if (TargetTriple.getOS() == Triple::Vulkan) | ||
| Env = Shader; | ||
| else if (TargetTriple.getOS() == Triple::OpenCL || | ||
| TargetTriple.getVendor() == Triple::AMD) | ||
| TargetTriple.getVendor() == Triple::AMD || | ||
| TargetTriple.getOS() == Triple::ChipStar) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This if fine for now. I just want to comment that I regret making the "ChipStar" an OS component but it doesn't matter unless/until chipStar adds a driver backend that requires Vulkan or other SPIR-V environment. It would have been better if it were a vendor component instead to differentiate the target environment - something like "spirv64-chipstar-vulkan".
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I have a branch that converts our generated SPIRV from OpenCL to Vulkan SPIRV. This is for simplifying integration with clvk - converting SPIRV to Vulkan SPIRV on our side allows us to bypass the clspv component of clvk. Not sure if this is something that will ever get merged or how that would affect llvm if so. |
||
| Env = Kernel; | ||
| else | ||
| Env = Unknown; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, this function is related to availability of std::aligned_alloc(). I'm wondering what this has to do with HIP. Like does HIP language support
std::aligned_alloc()to be called from device code?