Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/AlignedAllocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment on lines +38 to +39
Copy link
Copy Markdown
Contributor

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?

}

llvm_unreachable("Unexpected OS");
Expand Down
84 changes: 59 additions & 25 deletions clang/lib/Driver/ToolChains/HIPSPV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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.
Expand All @@ -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).
Comment thread
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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);
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/ToolChains/SPIRV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion clang/test/Driver/hipspv-link-static-library.hip
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 7 additions & 5 deletions clang/test/Driver/hipspv-pass-plugin.hip
Original file line number Diff line number Diff line change
Expand Up @@ -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"}}
Expand All @@ -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"
19 changes: 10 additions & 9 deletions clang/test/Driver/hipspv-toolchain.hip
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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 \
Expand All @@ -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]]"

//-----------------------------------------------------------------------------
Expand All @@ -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]]
22 changes: 19 additions & 3 deletions clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is it a problem if the Arch is empty for non-chipStar SPIR-V targets?

}
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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, ",")));

Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't matter unless/until chipStar adds a driver backend that requires Vulkan

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.

@linehill

Env = Kernel;
else
Env = Unknown;
Expand Down