llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-driver Author: Paulius Velesko (pvelesko) <details> <summary>Changes</summary> ## Summary 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 (`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` - 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 ## Test plan - [ ] `hipspv-toolchain.hip` driver test updated to verify the new in-tree backend pipeline - [ ] chipStar test suite: 1173/1173 tests pass (100%) on the translator path; 1169/1173 (99.7%) on the native in-tree backend (4 remaining printf failures due to upstream `ExpandVariadics` regression in LLVM 23) --- Patch is 21.95 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/186972.diff 6 Files Affected: - (modified) clang/include/clang/Basic/AlignedAllocation.h (+2) - (modified) clang/lib/Driver/ToolChains/HIPSPV.cpp (+58-25) - (modified) clang/lib/Driver/ToolChains/SPIRV.cpp (+2-1) - (modified) clang/test/Driver/hipspv-toolchain.hip (+43-13) - (modified) clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp (+194-5) - (modified) llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp (+2-1) ``````````diff diff --git a/clang/include/clang/Basic/AlignedAllocation.h b/clang/include/clang/Basic/AlignedAllocation.h index ac26eb4a276da..9b84d07286d52 100644 --- a/clang/include/clang/Basic/AlignedAllocation.h +++ b/clang/include/clang/Basic/AlignedAllocation.h @@ -35,6 +35,8 @@ inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { return llvm::VersionTuple(4U); case llvm::Triple::ZOS: return llvm::VersionTuple(); // All z/OS versions have no support. + case llvm::Triple::ChipStar: + return llvm::VersionTuple(); // No version constraint for device targets. } llvm_unreachable("Unexpected OS"); diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp index 8bdb7ab042b2b..70f831c3ade87 100644 --- a/clang/lib/Driver/ToolChains/HIPSPV.cpp +++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp @@ -72,10 +72,56 @@ 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). + + // 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; + } - // 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()); + 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 +135,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); @@ -152,14 +182,17 @@ HIPSPVToolChain::HIPSPVToolChain(const Driver &D, const llvm::Triple &Triple, void HIPSPVToolChain::addClangTargetOptions( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadingKind) const { - if (!HostTC) { assert(DeviceOffloadingKind == Action::OFK_None && "Need host toolchain for offloading!"); return; } - HostTC->addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind); + // NOTE: Unlike other HIP toolchains, we do NOT delegate to + // HostTC.addClangTargetOptions() here. On macOS (Darwin), the host toolchain + // adds flags like -faligned-alloc-unavailable that are specific to macOS + // libc++ and break SPIR-V device compilation. SPIR-V device code doesn't + // have the same stdlib limitations as the host. assert(DeviceOffloadingKind == Action::OFK_HIP && "Only HIP offloading kinds are supported for GPUs."); diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp index a59bd05cac0cf..e6a04e00af87b 100644 --- a/clang/lib/Driver/ToolChains/SPIRV.cpp +++ b/clang/lib/Driver/ToolChains/SPIRV.cpp @@ -185,7 +185,8 @@ SPIRVToolChain::SPIRVToolChain(const Driver &D, const llvm::Triple &Triple, : ToolChain(D, Triple, Args) { // TODO: Revisit need/use of --sycl-link option once SYCL toolchain is // available and SYCL linking support is moved there. - NativeLLVMSupport = Args.hasArg(options::OPT_sycl_link) || D.isUsingLTO(); + NativeLLVMSupport = Args.hasArg(options::OPT_sycl_link) || D.isUsingLTO() || + Triple.getOS() == llvm::Triple::ChipStar; // Lookup binaries into the driver directory. getProgramPaths().push_back(getDriver().Dir); diff --git a/clang/test/Driver/hipspv-toolchain.hip b/clang/test/Driver/hipspv-toolchain.hip index ae8d65313abfb..9af64ca4bdaa4 100644 --- a/clang/test/Driver/hipspv-toolchain.hip +++ b/clang/test/Driver/hipspv-toolchain.hip @@ -59,17 +59,50 @@ // RUN: llvm-offload-binary -o %t.dev.out \ // RUN: --image=file=%t.dev.bc,kind=hip,triple=spirv64-unknown-chipstar,arch=generic -// RUN: clang-linker-wrapper --dry-run \ +// Test the in-tree SPIR-V backend path (no llvm-spirv available). +// Run from a directory that doesn't contain llvm-spirv and use +// --no-canonical-prefixes so getExecutableDir() looks there instead of +// the build bin dir. Empty PATH ensures PATH lookup also fails. +// RUN: mkdir -p %t/no-spirv %t/empty +// RUN: ln -sf clang-linker-wrapper %t/no-spirv/clang-linker-wrapper +// RUN: env "PATH=%t/empty" %t/no-spirv/clang-linker-wrapper \ +// RUN: --no-canonical-prefixes --dry-run \ // RUN: --device-compiler=spirv64-unknown-chipstar=--hip-path="%S/Inputs/hipspv" \ // RUN: --host-triple=spirv64-unknown-chipstar \ // RUN: --linker-path=clang-offload-bundler \ // RUN: --emit-fatbin-only -o /dev/null %t.dev.out \ // RUN: 2>&1 | FileCheck %s --check-prefix=WRAPPER -DHIP_PATH=%S/Inputs/hipspv -// WRAPPER: clang{{.*}}" --no-default-config -o {{[^ ]*.img}} +// The linker wrapper runs opt (HipSpvPasses) then uses the in-tree SPIR-V +// backend when llvm-spirv is not available. +// WRAPPER: "{{.*}}opt" {{.*}}-load-pass-plugin +// WRAPPER-SAME: {{.*}}libLLVMHipSpvPasses.so +// WRAPPER-SAME: -passes=hip-post-link-passes + +// WRAPPER: "{{.*}}clang{{.*}}" --no-default-config -o // WRAPPER-SAME: --target=spirv64-unknown-chipstar -// WRAPPER-SAME: {{[^ ]*.o}} -// WRAPPER-SAME: --hip-path=[[HIP_PATH]] +// 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 +// WRAPPER-SAME: -c -x ir + +// Test the llvm-spirv translator path (llvm-spirv available in executable dir). +// Place a fake llvm-spirv next to the clang-linker-wrapper symlink. +// RUN: mkdir -p %t/with-spirv +// RUN: ln -sf clang-linker-wrapper %t/with-spirv/clang-linker-wrapper +// RUN: touch %t/with-spirv/llvm-spirv && chmod +x %t/with-spirv/llvm-spirv +// RUN: env "PATH=%t/empty" %t/with-spirv/clang-linker-wrapper \ +// RUN: --no-canonical-prefixes --dry-run \ +// RUN: --device-compiler=spirv64-unknown-chipstar=--hip-path="%S/Inputs/hipspv" \ +// RUN: --host-triple=spirv64-unknown-chipstar \ +// RUN: --linker-path=clang-offload-bundler \ +// RUN: --emit-fatbin-only -o /dev/null %t.dev.out \ +// RUN: 2>&1 | FileCheck %s --check-prefix=WRAPPER-TR + +// WRAPPER-TR: "{{.*}}opt" {{.*}}-load-pass-plugin +// WRAPPER-TR-SAME: {{.*}}libLLVMHipSpvPasses.so +// WRAPPER-TR-SAME: -passes=hip-post-link-passes + +// WRAPPER-TR: "{{.*}}llvm-spirv" {{.*}}--spirv-max-version=1.2 +// WRAPPER-TR-SAME: --spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups // RUN: touch %t.dummy.o // RUN: %clang -### --no-default-config -o %t.dummy.img \ @@ -84,8 +117,9 @@ // CHIPSTAR-SAME: "[[HIP_PATH]]/lib/libLLVMHipSpvPasses.so" // CHIPSTAR-SAME: "-passes=hip-post-link-passes" "-o" [[LOWER_BC:".*bc"]] -// CHIPSTAR: {{".*llvm-spirv"}} "--spirv-max-version=1.2" -// CHIPSTAR-SAME: "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups" +// CHIPSTAR: {{".*clang.*"}} "--no-default-config" "-c" +// CHIPSTAR-SAME: "--target=spirv64-unknown-chipstar" +// 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" // CHIPSTAR-SAME: [[LOWER_BC]] "-o" "[[SPIRV_OUT:.*img]]" // RUN: %clang -### --no-default-config -o %t.dummy.img \ @@ -100,8 +134,9 @@ // CHIPSTAR-SUBARCH-SAME: "[[HIP_PATH]]/lib/libLLVMHipSpvPasses.so" // CHIPSTAR-SUBARCH-SAME: "-passes=hip-post-link-passes" "-o" [[LOWER_BC:".*bc"]] -// CHIPSTAR-SUBARCH: {{".*llvm-spirv"}} -// CHIPSTAR-SUBARCH-SAME: "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups" +// CHIPSTAR-SUBARCH: {{".*clang.*"}} "--no-default-config" "-c" +// CHIPSTAR-SUBARCH-SAME: "--target=spirv64v1.3-unknown-chipstar" +// 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" // CHIPSTAR-SUBARCH-SAME: [[LOWER_BC]] "-o" "[[SPIRV_OUT:.*img]]" //----------------------------------------------------------------------------- @@ -115,9 +150,4 @@ // RUN: | FileCheck -DVERSION=%llvm-version-major \ // RUN: --check-prefix=VERSIONED %s -// RUN: env "PATH=%t/versioned" %clang -### --no-default-config \ -// RUN: -o %t.dummy.img --target=spirv64-unknown-chipstar %t.dummy.o \ -// RUN: --hip-path="%S/Inputs/hipspv" -o /dev/null 2>&1 \ -// RUN: | FileCheck -DVERSION=%llvm-version-major --check-prefix=VERSIONED %s - // VERSIONED: {{.*}}llvm-spirv-[[VERSION]] diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 9e24a9c26d897..2522d0ac71df1 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -125,6 +125,9 @@ static StringRef ExecutableName; /// Binary path for the CUDA installation. static std::string CudaBinaryPath; +/// HIP installation path. +static std::string HipPath; + /// Mutex lock to protect writes to shared TempFiles in parallel. static std::mutex TempFilesMutex; @@ -479,9 +482,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(); + } + 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); + } 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, ","))); @@ -554,7 +573,161 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args, if (!Triple.isNVPTX() && !Triple.isSPIRV()) CmdArgs.push_back("-Wl,--no-undefined"); - for (StringRef InputFile : InputFiles) + // For non-chipStar SPIR-V targets, pass the HIP path to clang so it can + // find resources. For chipStar, passes are run via opt separately, so the + // inner clang doesn't need --hip-path (it just compiles IR to SPIR-V). + if (Triple.isSPIRV() && !HipPath.empty() && + Triple.getOS() != llvm::Triple::ChipStar) + CmdArgs.push_back(Args.MakeArgString("--hip-path=" + HipPath)); + + // For chipStar targets: llvm-link (merge) → opt (HipSpvPasses) → clang + // (SPIR-V backend). The passes must operate on LLVM IR before the backend + // lowers to MIR, and all TU bitcode must be merged first for RDC support. + SmallVector<StringRef, 16> ProcessedInputFiles; + if (Triple.isSPIRV() && Triple.getOS() == llvm::Triple::ChipStar) { + // Step 1: Merge all input bitcode files with llvm-link (needed for RDC + // where functions can be defined across translation units). + StringRef MergedFile; + if (InputFiles.size() > 1) { + Expected<std::string> LinkPath = + findProgram("llvm-link", {getExecutableDir("llvm-link")}); + if (!LinkPath) + return LinkPath.takeError(); + + auto LinkOutOrErr = createOutputFile( + sys::path::filename(ExecutableName) + ".merged", "bc"); + if (!LinkOutOrErr) + return LinkOutOrErr.takeError(); + + SmallVector<StringRef, 16> LinkArgs{*LinkPath}; + for (StringRef F : InputFiles) + LinkArgs.push_back(F); + LinkArgs.push_back("-o"); + LinkArgs.push_back(*LinkOutOrErr); + + if (Error Err = executeCommands(*LinkPath, LinkArgs)) + return std::move(Err); + + MergedFile = *LinkOutOrErr; + } else { + MergedFile = InputFiles[0]; + } + + // Step 2: Run HipSpvPasses via opt on the merged bitcode. + SmallString<128> PluginPath; + if (!HipPath.empty()) { + PluginPath.assign(HipPath); + sys::path::append(PluginPath, "lib", "libLLVMHipSpvPasses.so"); + if (!sys::fs::exists(PluginPath)) { + PluginPath.assign(HipPath); + sys::path::append(PluginPath, "lib", "llvm", + "libLLVMHipSpvPasses.so"); + } + if (!sys::fs::exists(PluginPath)) + PluginPath.clear(); + } + + StringRef OptOutputFile = MergedFile; + if (!PluginPath.empty()) { + Expected<std::string> OptPath = + findProgram("opt", {getExecutableDir("opt")}); + if (!OptPath) + return OptPath.takeError(); + + auto OptOutOrErr = createOutputFile( + sys::path::filename(ExecutableName) + ".lowered", "bc"); + if (!OptOutOrErr) + return OptOutOrErr.takeError(); + + SmallVector<StringRef, 16> OptArgs{ + *OptPath, + MergedFile, + "-load-pass-plugin", + Args.MakeArgString(PluginPath), + "-passes=hip-post-link-passes", + "-o", + *OptOutOrErr, + }; + + if (Error Err = executeCommands(*OptPath, OptArgs)) + return std::move(Err); + + OptOutputFile = *OptOutOrErr; + } + + // Step 3: Convert processed bitcode to SPIR-V. + // Check if llvm-spirv translator is available. If so, use it directly; + // otherwise use the in-tree SPIR-V backend via clang. + // Use sys::findProgramByName() instead of findProgram() to avoid the + // dry-run fallback that always "finds" programs by returning their name. + bool UseLLVMSpirvTranslator = false; + std::string LLVMSpirvPathStr; + { + ErrorOr<std::string> LLVMSpirvPath = + sys::findProgramByName("llvm-spirv", {getExecutableDir("llvm-spirv")}); + if (!LLVMSpirvPath) + LLVMSpirvPath = sys::findProgramByName("llvm-spirv"); + if (LLVMSpirvPath) { + LLVMSpirvPathStr = *LLVMSpirvPath; + UseLLVMSpirvTranslator = true; + } + } + if (UseLLVMSpirvTranslator) { + // Use llvm-spirv translator: BC → SPIR-V binary directly. + auto SpirvOutOrErr = createOutputFile( + sys::path::filename(ExecutableName) + ".spirv", "spv"); + if (!SpirvOutOrErr) + return SpirvOutOrErr.takeError(); + + // Derive SPIR-V max version from the triple's sub-arch. + // chipStar needs v1.2 for sub-group extensions by default. + std::string MaxVerArg; + if (Triple.getSubArch() == llvm::Triple::SPIRVSubArch_v13) + MaxVerArg = "--spirv-max-version=1.3"; + else if (Triple.getSubArch() == llvm::Triple::SPIRVSubArch_v12 || + Triple.getOS() == llvm::Triple::ChipStar) + MaxVerArg = "--spirv-max-version=1.2"; + else + MaxVerArg = "--spirv-max-version=1.1"; + + SmallVector<StringRef, 16> TranslateArgs{ + LLVMSpirvPathStr, + OptOutputFile, + Args.MakeArgString(MaxVerArg), + "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups", + "-o", + *SpirvOutOrErr, + }; + + if (Error Err = executeCommands(LLVMSpirvPathStr, TranslateArgs)) + return std::move(Err); + + // The SPIR-V binary is the final output; skip the inner clang + // compilation by returning it directly as the linked image. + return *SpirvOutOrErr; + } + + // No llvm-spirv available; use the in-tree SPIR-V backend via clang. + ProcessedInputFiles.push_back(OptOutputFile); + CmdArgs.push_back("-mllvm"); + CmdArgs.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"); + // The extracted bitcode files have a .o extension which causes the driver + // to treat them as pre-compiled objects, skipping the Backend compilation + // step. Force the input language to LLVM IR so the SPIR-V backend runs. + // Use -c to skip the link phase — the SPIR-V backend output is the final + // binary; hitting HIPSPV::Linker would re-run the full pipeline. + CmdArgs.push_back("-c"); + CmdArgs.push_back("-x"); + CmdArgs.push_back("ir"); + } else { + ProcessedInputFiles.append(InputFiles.begin(), InputFiles.end()); + } + + for (StringRef InputFile : ProcessedInputFiles) CmdArgs.push_back(InputFile); // If this is CPU offloading we copy the input libraries. @@ -613,8 +786,14 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args, for (StringRef Arg : Args.getA... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/186972 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
