Skip to content

Commit a4a5227

Browse files
committed
[HIPSPV] Add in-tree SPIR-V backend support for chipStar
chipStar (https://github.com/CHIP-SPV/chipStar) enables HIP/CUDA programs to run on OpenCL and Level Zero devices via SPIR-V. Until now, the HIPSPV toolchain relied exclusively on the external llvm-spirv translator for bitcode-to-SPIR-V conversion. This patch adds native in-tree SPIR-V backend support for chipStar targets (triple: spirv64*-unknown-chipstar), removing the hard dependency on llvm-spirv. Changes: HIPSPV old driver (HIPSPV.cpp): - chipStar targets now use opt (HipSpvPasses) + clang -c (SPIR-V backend) instead of opt + llvm-spirv translator - Non-chipStar HIPSPV targets continue using llvm-spirv unchanged - Remove HostTC->addClangTargetOptions() delegation to avoid macOS Darwin flags (-faligned-alloc-unavailable) breaking SPIR-V device compilation New offload driver (ClangLinkerWrapper.cpp): - Add chipStar SPIR-V pipeline: llvm-link -> opt (HipSpvPasses) -> clang -c --target=spirv64 with SPIR-V extensions - Extract --hip-path from --device-compiler= args for locating the HipSpvPasses plugin and device libraries - Fall back to llvm-spirv translator when available for non-chipStar SPIR-V targets SPIR-V toolchain (SPIRV.cpp): - Enable NativeLLVMSupport for chipStar triples so the toolchain does not require an external translator SPIR-V backend (SPIRVSubtarget.cpp): - Set Kernel environment for chipStar triples (needed for OpenCL kernel ABI) AlignedAllocation.h: - Add ChipStar case to avoid unhandled enum warning Tests: - Update hipspv-toolchain.hip driver test to verify the new in-tree backend pipeline for chipStar targets
1 parent bc3386c commit a4a5227

8 files changed

Lines changed: 307 additions & 51 deletions

File tree

clang/include/clang/Basic/AlignedAllocation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) {
3535
return llvm::VersionTuple(4U);
3636
case llvm::Triple::ZOS:
3737
return llvm::VersionTuple(); // All z/OS versions have no support.
38+
case llvm::Triple::ChipStar:
39+
return llvm::VersionTuple(); // No version constraint for device targets.
3840
}
3941

4042
llvm_unreachable("Unexpected OS");

clang/lib/Driver/ToolChains/HIPSPV.cpp

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,55 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
7272
tools::constructLLVMLinkCommand(C, *this, JA, Inputs, LinkArgs, Output, Args,
7373
TempFile);
7474

75-
// Post-link HIP lowering.
75+
auto T = getToolChain().getTriple();
76+
77+
if (T.getOS() == llvm::Triple::ChipStar) {
78+
// chipStar: run HipSpvPasses via opt, then use the in-tree SPIR-V backend
79+
// for codegen (replaces the external llvm-spirv translator).
80+
81+
// Run HipSpvPasses plugin via opt (must run on LLVM IR before
82+
// the SPIR-V backend lowers to MIR).
83+
auto PassPluginPath = findPassPlugin(C.getDriver(), Args);
84+
if (!PassPluginPath.empty()) {
85+
const char *PassPathCStr = C.getArgs().MakeArgString(PassPluginPath);
86+
const char *OptOutput = HIP::getTempFile(C, Name + "-lower", "bc");
87+
ArgStringList OptArgs{TempFile, "-load-pass-plugin",
88+
PassPathCStr, "-passes=hip-post-link-passes",
89+
"-o", OptOutput};
90+
const char *Opt =
91+
Args.MakeArgString(getToolChain().GetProgramPath("opt"));
92+
C.addCommand(std::make_unique<Command>(JA, *this,
93+
ResponseFileSupport::None(), Opt,
94+
OptArgs, Inputs, Output));
95+
TempFile = OptOutput;
96+
}
7697

77-
// Run LLVM IR passes to lower/expand/emulate HIP code that does not translate
78-
// to SPIR-V (E.g. dynamic shared memory).
98+
// Compile processed bitcode to SPIR-V using the in-tree backend.
99+
ArgStringList ClangArgs;
100+
ClangArgs.push_back("--no-default-config");
101+
ClangArgs.push_back("-c");
102+
ClangArgs.push_back(C.getArgs().MakeArgString("--target=" + T.getTriple()));
103+
104+
ClangArgs.push_back("-mllvm");
105+
ClangArgs.push_back("-spirv-ext=+SPV_INTEL_function_pointers"
106+
",+SPV_INTEL_subgroups"
107+
",+SPV_EXT_relaxed_printf_string_address_space"
108+
",+SPV_KHR_bit_instructions"
109+
",+SPV_EXT_shader_atomic_float_add");
110+
111+
ClangArgs.push_back(TempFile);
112+
ClangArgs.push_back("-o");
113+
ClangArgs.push_back(Output.getFilename());
114+
115+
const char *Clang =
116+
C.getArgs().MakeArgString(C.getDriver().getClangProgramPath());
117+
C.addCommand(std::make_unique<Command>(JA, *this,
118+
ResponseFileSupport::None(), Clang,
119+
ClangArgs, Inputs, Output));
120+
return;
121+
}
122+
123+
// Non-chipStar: run HIP passes via opt, then translate with llvm-spirv.
79124
auto PassPluginPath = findPassPlugin(C.getDriver(), Args);
80125
if (!PassPluginPath.empty()) {
81126
const char *PassPathCStr = C.getArgs().MakeArgString(PassPluginPath);
@@ -89,27 +134,11 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
89134
TempFile = OptOutput;
90135
}
91136

92-
// Emit SPIR-V binary.
137+
// Emit SPIR-V binary via llvm-spirv translator (non-chipStar targets).
93138
llvm::opt::ArgStringList TrArgs;
94-
auto T = getToolChain().getTriple();
95-
bool HasNoSubArch = T.getSubArch() == llvm::Triple::NoSubArch;
96-
if (T.getOS() == llvm::Triple::ChipStar) {
97-
// chipStar needs 1.2 for supporting warp-level primitivies via sub-group
98-
// extensions. Strictly put we'd need 1.3 for the standard non-extension
99-
// shuffle operations, but it's not supported by any backend driver of the
100-
// chipStar.
101-
if (HasNoSubArch)
102-
TrArgs.push_back("--spirv-max-version=1.2");
103-
TrArgs.push_back("--spirv-ext=-all"
104-
// Needed for experimental indirect call support.
105-
",+SPV_INTEL_function_pointers"
106-
// Needed for shuffles below SPIR-V 1.3
107-
",+SPV_INTEL_subgroups");
108-
} else {
109-
if (HasNoSubArch)
110-
TrArgs.push_back("--spirv-max-version=1.1");
111-
TrArgs.push_back("--spirv-ext=+all");
112-
}
139+
if (T.getSubArch() == llvm::Triple::NoSubArch)
140+
TrArgs.push_back("--spirv-max-version=1.1");
141+
TrArgs.push_back("--spirv-ext=+all");
113142

114143
InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, "");
115144
SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs);

clang/lib/Driver/ToolChains/SPIRV.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ SPIRVToolChain::SPIRVToolChain(const Driver &D, const llvm::Triple &Triple,
199199
: ToolChain(D, Triple, Args) {
200200
// TODO: Revisit need/use of --sycl-link option once SYCL toolchain is
201201
// available and SYCL linking support is moved there.
202-
NativeLLVMSupport = Args.hasArg(options::OPT_sycl_link) || D.isUsingLTO();
202+
NativeLLVMSupport = Args.hasArg(options::OPT_sycl_link) || D.isUsingLTO() ||
203+
Triple.getOS() == llvm::Triple::ChipStar;
203204

204205
// Lookup binaries into the driver directory.
205206
getProgramPaths().push_back(getDriver().Dir);

clang/test/Driver/hipspv-link-static-library.hip

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@
4848
// SDL-NEW-SAME: "{{.*}}/tu0.o" "{{.*}}/libSDL2.a"
4949
// DELETE-SDL-NEW: "{{.*}}llvm-link" "-o" "{{.*}}.bc" "{{.*}}.o" "{{.*}}.o"
5050

51-
// SDL-NEW-WRAPPER: clang{{.*}}" --no-default-config -o {{[^ ]*.img}}
52-
// SDL-NEW-WRAPPER-SAME: {{[^ ]*.o}} {{[^ ]*.o}}
53-
// SDL-NEW-WRAPPER-SAME: --hip-path=[[HIP_PATH]]
51+
// SDL-NEW-WRAPPER: "{{.*}}opt"
52+
// SDL-NEW-WRAPPER-SAME: -load-pass-plugin
53+
// SDL-NEW-WRAPPER-SAME: [[HIP_PATH]]/lib/libLLVMHipSpvPasses.so
54+
// SDL-NEW-WRAPPER: clang{{.*}}" --no-default-config
55+
// SDL-NEW-WRAPPER-SAME: --target=spirv64-unknown-chipstar
56+
// SDL-NEW-WRAPPER-SAME: -c -x ir
5457

5558
// SDL: "{{.*}}opt"
5659
// SDL-SAME: "-load-pass-plugin" {{".*/hipspv/lib/libLLVMHipSpvPasses.so"}}

clang/test/Driver/hipspv-pass-plugin.hip

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,24 @@
1616
// RUN: --no-offload-new-driver -nogpuinc -nogpulib %s \
1717
// RUN: 2>&1 | FileCheck --check-prefixes=ALL,NO-PLUGIN %s
1818

19-
// Run commands for the new offload driver:
19+
// Run commands for the new offload driver (chipStar uses in-tree SPIR-V
20+
// backend instead of llvm-spirv):
2021

2122
// RUN: touch %t.dummy.o
2223
// RUN: %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \
2324
// RUN: %t.dummy.o --hip-path=%S/Inputs/hipspv \
24-
// RUN: 2>&1 | FileCheck %s --check-prefixes=ALL,FROM-HIP-PATH
25+
// RUN: 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,FROM-HIP-PATH
2526

2627
// RUN: %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \
2728
// RUN: %t.dummy.o --hipspv-pass-plugin=%S/Inputs/pass-plugin.so \
28-
// RUN: 2>&1 | FileCheck %s --check-prefixes=ALL,FROM-OPTION
29+
// RUN: 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,FROM-OPTION
2930

3031
// RUN: not %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \
3132
// RUN: %t.dummy.o --hipspv-pass-plugin=foo.so \
32-
// RUN: 2>&1 | FileCheck %s --check-prefixes=ALL,FROM-OPTION-INVALID
33+
// RUN: 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,FROM-OPTION-INVALID
3334

3435
// RUN: %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \
35-
// RUN: %t.dummy.o 2>&1 | FileCheck %s --check-prefixes=ALL,NO-PLUGIN
36+
// RUN: %t.dummy.o 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,NO-PLUGIN
3637

3738
// FROM-HIP-PATH: {{".*opt"}} {{".*.bc"}} "-load-pass-plugin"
3839
// FROM-HIP-PATH-SAME: {{".*/Inputs/hipspv/lib/libLLVMHipSpvPasses.so"}}
@@ -42,3 +43,4 @@
4243
// NO-PLUGIN-NOT: {{".*opt"}} {{".*.bc"}} "-load-pass-plugin"
4344
// NO-PLUGIN-NOT: {{".*/Inputs/hipspv/lib/libLLVMHipSpvPasses.so"}}
4445
// ALL: {{".*llvm-spirv[^ ]*"}}
46+
// CHIPSTAR: {{".*clang.*"}} "--no-default-config" "-c"

clang/test/Driver/hipspv-toolchain.hip

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,50 @@
5959
// RUN: llvm-offload-binary -o %t.dev.out \
6060
// RUN: --image=file=%t.dev.bc,kind=hip,triple=spirv64-unknown-chipstar,arch=generic
6161

62-
// RUN: clang-linker-wrapper --dry-run \
62+
// Test the in-tree SPIR-V backend path (no llvm-spirv available).
63+
// Run from a directory that doesn't contain llvm-spirv and use
64+
// --no-canonical-prefixes so getExecutableDir() looks there instead of
65+
// the build bin dir. Empty PATH ensures PATH lookup also fails.
66+
// RUN: mkdir -p %t/no-spirv %t/empty
67+
// RUN: ln -sf clang-linker-wrapper %t/no-spirv/clang-linker-wrapper
68+
// RUN: env "PATH=%t/empty" %t/no-spirv/clang-linker-wrapper \
69+
// RUN: --no-canonical-prefixes --dry-run \
6370
// RUN: --device-compiler=spirv64-unknown-chipstar=--hip-path="%S/Inputs/hipspv" \
6471
// RUN: --host-triple=spirv64-unknown-chipstar \
6572
// RUN: --linker-path=clang-offload-bundler \
6673
// RUN: --emit-fatbin-only -o /dev/null %t.dev.out \
6774
// RUN: 2>&1 | FileCheck %s --check-prefix=WRAPPER -DHIP_PATH=%S/Inputs/hipspv
6875

69-
// WRAPPER: clang{{.*}}" --no-default-config -o {{[^ ]*.img}}
76+
// The linker wrapper runs opt (HipSpvPasses) then uses the in-tree SPIR-V
77+
// backend when llvm-spirv is not available.
78+
// WRAPPER: "{{.*}}opt" {{.*}}-load-pass-plugin
79+
// WRAPPER-SAME: {{.*}}libLLVMHipSpvPasses.so
80+
// WRAPPER-SAME: -passes=hip-post-link-passes
81+
82+
// WRAPPER: "{{.*}}clang{{.*}}" --no-default-config -o
7083
// WRAPPER-SAME: --target=spirv64-unknown-chipstar
71-
// WRAPPER-SAME: {{[^ ]*.o}}
72-
// WRAPPER-SAME: --hip-path=[[HIP_PATH]]
84+
// WRAPPER-SAME: -mllvm -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
85+
// WRAPPER-SAME: -c -x ir
86+
87+
// Test the llvm-spirv translator path (llvm-spirv available in executable dir).
88+
// Place a fake llvm-spirv next to the clang-linker-wrapper symlink.
89+
// RUN: mkdir -p %t/with-spirv
90+
// RUN: ln -sf clang-linker-wrapper %t/with-spirv/clang-linker-wrapper
91+
// RUN: touch %t/with-spirv/llvm-spirv && chmod +x %t/with-spirv/llvm-spirv
92+
// RUN: env "PATH=%t/empty" %t/with-spirv/clang-linker-wrapper \
93+
// RUN: --no-canonical-prefixes --dry-run \
94+
// RUN: --device-compiler=spirv64-unknown-chipstar=--hip-path="%S/Inputs/hipspv" \
95+
// RUN: --host-triple=spirv64-unknown-chipstar \
96+
// RUN: --linker-path=clang-offload-bundler \
97+
// RUN: --emit-fatbin-only -o /dev/null %t.dev.out \
98+
// RUN: 2>&1 | FileCheck %s --check-prefix=WRAPPER-TR
99+
100+
// WRAPPER-TR: "{{.*}}opt" {{.*}}-load-pass-plugin
101+
// WRAPPER-TR-SAME: {{.*}}libLLVMHipSpvPasses.so
102+
// WRAPPER-TR-SAME: -passes=hip-post-link-passes
103+
104+
// WRAPPER-TR: "{{.*}}llvm-spirv" {{.*}}--spirv-max-version=1.2
105+
// WRAPPER-TR-SAME: --spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups
73106

74107
// RUN: touch %t.dummy.o
75108
// RUN: %clang -### --no-default-config -o %t.dummy.img \
@@ -84,8 +117,9 @@
84117
// CHIPSTAR-SAME: "[[HIP_PATH]]/lib/libLLVMHipSpvPasses.so"
85118
// CHIPSTAR-SAME: "-passes=hip-post-link-passes" "-o" [[LOWER_BC:".*bc"]]
86119

87-
// CHIPSTAR: {{".*llvm-spirv"}} "--spirv-max-version=1.2"
88-
// CHIPSTAR-SAME: "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups"
120+
// CHIPSTAR: {{".*clang.*"}} "--no-default-config" "-c"
121+
// CHIPSTAR-SAME: "--target=spirv64-unknown-chipstar"
122+
// CHIPSTAR-SAME: "-mllvm" "-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"
89123
// CHIPSTAR-SAME: [[LOWER_BC]] "-o" "[[SPIRV_OUT:.*img]]"
90124

91125
// RUN: %clang -### --no-default-config -o %t.dummy.img \
@@ -100,8 +134,9 @@
100134
// CHIPSTAR-SUBARCH-SAME: "[[HIP_PATH]]/lib/libLLVMHipSpvPasses.so"
101135
// CHIPSTAR-SUBARCH-SAME: "-passes=hip-post-link-passes" "-o" [[LOWER_BC:".*bc"]]
102136

103-
// CHIPSTAR-SUBARCH: {{".*llvm-spirv"}}
104-
// CHIPSTAR-SUBARCH-SAME: "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups"
137+
// CHIPSTAR-SUBARCH: {{".*clang.*"}} "--no-default-config" "-c"
138+
// CHIPSTAR-SUBARCH-SAME: "--target=spirv64v1.3-unknown-chipstar"
139+
// CHIPSTAR-SUBARCH-SAME: "-mllvm" "-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"
105140
// CHIPSTAR-SUBARCH-SAME: [[LOWER_BC]] "-o" "[[SPIRV_OUT:.*img]]"
106141

107142
//-----------------------------------------------------------------------------
@@ -115,9 +150,4 @@
115150
// RUN: | FileCheck -DVERSION=%llvm-version-major \
116151
// RUN: --check-prefix=VERSIONED %s
117152

118-
// RUN: env "PATH=%t/versioned" %clang -### --no-default-config \
119-
// RUN: -o %t.dummy.img --target=spirv64-unknown-chipstar %t.dummy.o \
120-
// RUN: --hip-path="%S/Inputs/hipspv" -o /dev/null 2>&1 \
121-
// RUN: | FileCheck -DVERSION=%llvm-version-major --check-prefix=VERSIONED %s
122-
123153
// VERSIONED: {{.*}}llvm-spirv-[[VERSION]]

0 commit comments

Comments
 (0)