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..188de4879cd07 100644 --- a/clang/lib/Driver/ToolChains/HIPSPV.cpp +++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp @@ -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()); // 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). + + // 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(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(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); diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp index f77a1d30507c7..325e1752bf372 100644 --- a/clang/lib/Driver/ToolChains/SPIRV.cpp +++ b/clang/lib/Driver/ToolChains/SPIRV.cpp @@ -199,7 +199,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-link-static-library.hip b/clang/test/Driver/hipspv-link-static-library.hip index eb114ada49020..a00f385b3288b 100644 --- a/clang/test/Driver/hipspv-link-static-library.hip +++ b/clang/test/Driver/hipspv-link-static-library.hip @@ -49,7 +49,8 @@ // DELETE-SDL-NEW: "{{.*}}llvm-link" "-o" "{{.*}}.bc" "{{.*}}.o" "{{.*}}.o" // SDL-NEW-WRAPPER: clang{{.*}}" --no-default-config -o {{[^ ]*.img}} -// SDL-NEW-WRAPPER-SAME: {{[^ ]*.o}} {{[^ ]*.o}} +// SDL-NEW-WRAPPER-SAME: --target=spirv64-unknown-chipstar +// SDL-NEW-WRAPPER-SAME: {{[^ ]*.o}} // SDL-NEW-WRAPPER-SAME: --hip-path=[[HIP_PATH]] // SDL: "{{.*}}opt" diff --git a/clang/test/Driver/hipspv-pass-plugin.hip b/clang/test/Driver/hipspv-pass-plugin.hip index 3a0979ad6df01..5cf891e4c6114 100644 --- a/clang/test/Driver/hipspv-pass-plugin.hip +++ b/clang/test/Driver/hipspv-pass-plugin.hip @@ -16,23 +16,24 @@ // RUN: --no-offload-new-driver -nogpuinc -nogpulib %s \ // RUN: 2>&1 | FileCheck --check-prefixes=ALL,NO-PLUGIN %s -// Run commands for the new offload driver: +// Run commands for the new offload driver (chipStar uses in-tree SPIR-V +// backend instead of llvm-spirv): // RUN: touch %t.dummy.o // RUN: %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \ // RUN: %t.dummy.o --hip-path=%S/Inputs/hipspv \ -// RUN: 2>&1 | FileCheck %s --check-prefixes=ALL,FROM-HIP-PATH +// RUN: 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,FROM-HIP-PATH // RUN: %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \ // RUN: %t.dummy.o --hipspv-pass-plugin=%S/Inputs/pass-plugin.so \ -// RUN: 2>&1 | FileCheck %s --check-prefixes=ALL,FROM-OPTION +// RUN: 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,FROM-OPTION // RUN: not %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \ // RUN: %t.dummy.o --hipspv-pass-plugin=foo.so \ -// RUN: 2>&1 | FileCheck %s --check-prefixes=ALL,FROM-OPTION-INVALID +// RUN: 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,FROM-OPTION-INVALID // RUN: %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \ -// RUN: %t.dummy.o 2>&1 | FileCheck %s --check-prefixes=ALL,NO-PLUGIN +// RUN: %t.dummy.o 2>&1 | FileCheck %s --check-prefixes=CHIPSTAR,NO-PLUGIN // FROM-HIP-PATH: {{".*opt"}} {{".*.bc"}} "-load-pass-plugin" // FROM-HIP-PATH-SAME: {{".*/Inputs/hipspv/lib/libLLVMHipSpvPasses.so"}} @@ -42,3 +43,4 @@ // NO-PLUGIN-NOT: {{".*opt"}} {{".*.bc"}} "-load-pass-plugin" // NO-PLUGIN-NOT: {{".*/Inputs/hipspv/lib/libLLVMHipSpvPasses.so"}} // ALL: {{".*llvm-spirv[^ ]*"}} +// CHIPSTAR: {{".*clang.*"}} "--no-default-config" "-c" diff --git a/clang/test/Driver/hipspv-toolchain.hip b/clang/test/Driver/hipspv-toolchain.hip index ae8d65313abfb..bb6559fd9021f 100644 --- a/clang/test/Driver/hipspv-toolchain.hip +++ b/clang/test/Driver/hipspv-toolchain.hip @@ -59,6 +59,10 @@ // RUN: llvm-offload-binary -o %t.dev.out \ // RUN: --image=file=%t.dev.bc,kind=hip,triple=spirv64-unknown-chipstar,arch=generic +// The linker wrapper forwards --hip-path from --device-compiler= to the inner +// clang invocation; the HIPSPV toolchain inside that clang then drives the +// llvm-link / opt (HipSpvPasses) / SPIR-V backend pipeline (covered by the +// CHIPSTAR run below). // RUN: clang-linker-wrapper --dry-run \ // RUN: --device-compiler=spirv64-unknown-chipstar=--hip-path="%S/Inputs/hipspv" \ // RUN: --host-triple=spirv64-unknown-chipstar \ @@ -84,8 +88,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 +105,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 +121,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 5abf1d387922a..175cf0da590e2 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -479,9 +479,25 @@ fatbinary(ArrayRef> InputFiles, SmallVector 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---- + 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, ","))); diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp index 4aca400e827d7..f40ec9262f50a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -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) Env = Kernel; else Env = Unknown;