diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index 38e6b1983..397d8c576 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -66,7 +66,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - llvm-version: [20] + llvm-version: [21] fail-fast: false steps: - uses: actions/checkout@v3 @@ -127,7 +127,7 @@ jobs: matrix: include: - pocl-version: "7.1" - llvm-version: 20 + llvm-version: 21 fail-fast: false steps: - uses: actions/checkout@v3 @@ -202,7 +202,7 @@ jobs: # PoCL backend with specific version combinations - backend: pocl pocl-version: "7.1" - llvm-version: 20 + llvm-version: 21 extra_exclude: "" fail-fast: false steps: diff --git a/.github/workflows/test-llvm-patches.yml b/.github/workflows/test-llvm-patches.yml index eb0a5ca15..2030a9039 100644 --- a/.github/workflows/test-llvm-patches.yml +++ b/.github/workflows/test-llvm-patches.yml @@ -28,10 +28,6 @@ jobs: strategy: matrix: include: - - llvm-version: 20 - build-id: "20" - install-suffix: "" - variant-flag: "" - llvm-version: 21 build-id: "21" install-suffix: "" @@ -44,6 +40,13 @@ jobs: build-id: "22-native" install-suffix: "-native" variant-flag: "--variant native" + # LLVM 23 needs only one build: chipStar patches in llvm#213052, so the + # SPIRV-target build also serves the translator and the producer is + # chosen per compilation by -f[no-]integrated-objemitter. + - llvm-version: 23 + build-id: "23" + install-suffix: "" + variant-flag: "--variant native" fail-fast: true steps: - uses: actions/checkout@v3 @@ -82,9 +85,6 @@ jobs: strategy: matrix: include: - - llvm-version: 20 - build-id: "20" - install-suffix: "" - llvm-version: 21 build-id: "21" install-suffix: "" @@ -94,6 +94,9 @@ jobs: - llvm-version: 22 build-id: "22-native" install-suffix: "-native" + - llvm-version: 23 + build-id: "23" + install-suffix: "" fail-fast: false steps: - uses: actions/checkout@v3 @@ -139,8 +142,30 @@ jobs: # install-only runtime headers such as omp.h, which made # TestHipccFopenmp fail with "'omp.h' file not found". LLVM_PREFIX="$HOME/install/llvm/${{ matrix.llvm-version }}.0${{ matrix.install-suffix }}" - LLVM_BIN="$HOME/llvm-stage/${{ matrix.build-id }}${LLVM_PREFIX}/bin" + LLVM_STAGE="$HOME/llvm-stage/${{ matrix.build-id }}${LLVM_PREFIX}" + LLVM_BIN="${LLVM_STAGE}/bin" test -f "${LLVM_BIN}/clang" || exit 1 + + # The staged binaries are thin drivers; all the driver logic lives in + # libclang-cpp.so / libLLVM.so. Their RUNPATH points at the *final* + # install prefix ($HOME/install/llvm/), not at the stage, so by + # default the staged clang loads the previously installed libraries + # and silently runs old code. That makes this lane test the installed + # toolchain rather than the one just built from llvm-patches/, which + # is precisely what this workflow exists to validate. Pin the loader + # to the stage, and persist it to the test steps via GITHUB_ENV since + # chipStar invokes clang again at test time. + export LD_LIBRARY_PATH="${LLVM_STAGE}/lib:${LLVM_STAGE}/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" + echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> "$GITHUB_ENV" + + # Fail loudly if the pin did not take effect, rather than silently + # validating the wrong toolchain again. + RESOLVED=$(ldd "${LLVM_BIN}/clang" 2>/dev/null | awk '/libclang-cpp/{print $3}') + case "$RESOLVED" in + "${LLVM_STAGE}"/*) echo "OK: clang resolves libclang-cpp from the stage" ;; + "") echo "NOTE: clang does not link libclang-cpp dynamically; nothing to pin" ;; + *) echo "ERROR: clang resolves libclang-cpp from '$RESOLVED', not the stage"; exit 1 ;; + esac test -f "${LLVM_BIN}/../lib/clang/${{ matrix.llvm-version }}/include/omp.h" \ || { echo "ERROR: omp.h missing from LLVM install toolchain at ${LLVM_BIN}"; exit 1; } cd ${{ github.workspace }} @@ -162,6 +187,9 @@ jobs: elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null else source /etc/profile.d/modules.sh &> /dev/null; fi module use ~/modulefiles + # IGC 2.36.3/2.38.2 miscompile chipStar kernels under their + # optimizer (TestSnakeMiscompileO2); this build carries the fix. + module load igc/all-fixes-2026.07.30 module load opencl/igpu cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }} ../scripts/check.py ./ igpu opencl @@ -175,6 +203,9 @@ jobs: elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null else source /etc/profile.d/modules.sh &> /dev/null; fi module use ~/modulefiles + # IGC 2.36.3/2.38.2 miscompile chipStar kernels under their + # optimizer (TestSnakeMiscompileO2); this build carries the fix. + module load igc/all-fixes-2026.07.30 module load level-zero/igpu cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }} ../scripts/check.py ./ igpu level0 @@ -187,6 +218,9 @@ jobs: elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null else source /etc/profile.d/modules.sh &> /dev/null; fi module use ~/modulefiles + # IGC 2.36.3/2.38.2 miscompile chipStar kernels under their + # optimizer (TestSnakeMiscompileO2); this build carries the fix. + module load igc/all-fixes-2026.07.30 module load level-zero/dgpu cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }} ../scripts/check.py ./ dgpu level0 @@ -199,6 +233,9 @@ jobs: elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null else source /etc/profile.d/modules.sh &> /dev/null; fi module use ~/modulefiles + # IGC 2.36.3/2.38.2 miscompile chipStar kernels under their + # optimizer (TestSnakeMiscompileO2); this build carries the fix. + module load igc/all-fixes-2026.07.30 module load opencl/dgpu cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }} ../scripts/check.py ./ dgpu opencl @@ -211,6 +248,9 @@ jobs: elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null else source /etc/profile.d/modules.sh &> /dev/null; fi module use ~/modulefiles + # IGC 2.36.3/2.38.2 miscompile chipStar kernels under their + # optimizer (TestSnakeMiscompileO2); this build carries the fix. + module load igc/all-fixes-2026.07.30 module load opencl/cpu cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }} ../scripts/check.py ./ cpu opencl --num-tries=3 @@ -233,10 +273,6 @@ jobs: strategy: matrix: include: - - llvm-version: 20 - build-id: "20" - install-suffix: "" - module-name: "20.0" - llvm-version: 21 build-id: "21" install-suffix: "" @@ -249,6 +285,10 @@ jobs: build-id: "22-native" install-suffix: "-native" module-name: "22.0-native" + - llvm-version: 23 + build-id: "23" + install-suffix: "" + module-name: "23.0" fail-fast: false steps: - name: Install LLVM ${{ matrix.build-id }} @@ -415,11 +455,25 @@ jobs: # the build tree, which lacks install-only runtime headers such as # omp.h (breaks TestHipccFopenmp with "'omp.h' file not found"). LLVM_PREFIX="$HOME/install/llvm/22.0-${{ matrix.variant }}" - LLVM_BIN="$HOME/llvm-stage/22-${{ matrix.variant }}${LLVM_PREFIX}/bin" + LLVM_STAGE="$HOME/llvm-stage/22-${{ matrix.variant }}${LLVM_PREFIX}" + LLVM_BIN="${LLVM_STAGE}/bin" test -f "${LLVM_BIN}/clang" || exit 1 test -f "${LLVM_BIN}/../lib/clang/22/include/omp.h" \ || { echo "ERROR: omp.h missing from LLVM install toolchain at ${LLVM_BIN}"; exit 1; } + # configure_llvm.sh builds with LLVM_LINK_LLVM_DYLIB=ON and + # CMAKE_INSTALL_RPATH pinned to the final install prefix, so a staged + # (DESTDIR) clang resolves libclang-cpp/libLLVM from the previously + # installed toolchain and runs old driver code. Pin the loader to the + # stage so this lane tests what it just built. DYLD_LIBRARY_PATH (not + # DYLD_FALLBACK_LIBRARY_PATH) is required: fallback is consulted only + # after @rpath resolution fails, and here it succeeds with the wrong + # library. Diagnostic only, not fatal, since the macOS linkage layout + # is not verified here the way the Linux one is. + export DYLD_LIBRARY_PATH="${LLVM_STAGE}/lib${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}" + echo "clang links against:" + otool -L "${LLVM_BIN}/clang" 2>/dev/null | grep -iE "clang-cpp|libLLVM" || true + export PATH="/Users/paulius/.pyenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" export CHIP_DEVICE_TYPE=pocl export OCL_ICD_VENDORS=/Users/paulius/install/pocl/etc/OpenCL/vendors/ diff --git a/.github/workflows/x86-intel-gpu-ci.yml b/.github/workflows/x86-intel-gpu-ci.yml index 85826c354..7da4cfe50 100644 --- a/.github/workflows/x86-intel-gpu-ci.yml +++ b/.github/workflows/x86-intel-gpu-ci.yml @@ -474,38 +474,6 @@ jobs: # debug builds. These run ONLY on a manual workflow_dispatch, not on every # PR, to keep automatic CI fast. Automatic PRs cover llvm-22 native-release # (Stage 1, above) and llvm-22 translator-release (below). - unit-tests-llvm-20-debug: - needs: build-and-test-libceed - if: ${{ !cancelled() && github.event_name == 'workflow_dispatch' }} - runs-on: [self-hosted, Linux, X64] - env: - CHIP_MODULE_CACHE_DIR: "" - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - fetch-depth: 0 - submodules: 'recursive' - - name: Run unit test checking script - run: ./scripts/unit_tests.sh debug llvm-20 - shell: bash - - unit-tests-llvm-20-release: - needs: build-and-test-libceed - if: ${{ !cancelled() && github.event_name == 'workflow_dispatch' }} - runs-on: [self-hosted, Linux, X64] - env: - CHIP_MODULE_CACHE_DIR: "" - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - fetch-depth: 0 - submodules: 'recursive' - - name: Run unit test checking script - run: ./scripts/unit_tests.sh release llvm-20 - shell: bash - unit-tests-llvm-21-debug: needs: build-and-test-libceed if: ${{ !cancelled() && github.event_name == 'workflow_dispatch' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 8220a4705..677cf8fa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -275,6 +275,7 @@ option(CHIP_VERBOSE "Verbose compilation" OFF) option(CHIP_BUILD_SHARED_LIBS "Build chipStar as a shared library" ON) option(CHIP_BUILD_DOCS "Build doxygen documentation" OFF) option(CHIP_LLVM_USE_INTERGRATED_SPIRV "Use LLVM's intergrated SPIR-V backend for emitting device binary instead of SPIR-V translator. Auto-detected from LLVM targets when LLVM >= 22." OFF) +option(CHIP_KEEP_KERNEL_DEBUG_INFO "Keep device debug info in kernels. No SPIR-V producer emits debug info that validates, and only IGC on Intel Data Center GPU Max tolerates it, so this is off by default and should only be enabled for that device." OFF) option(CHIP_SET_RPATH "Add CMAKE_INSTALL_PREFIX/lib to the RPATH for chipStar executables" ON) option(CHIP_ENABLE_UNCOMPILABLE_TESTS "Enable tests which are known to not compile" OFF) option(CHIP_BUILD_TESTS "Enable build_tests target" ON) @@ -381,6 +382,10 @@ endif() set(SPIRV_EMITTER_OPTS "") if(CHIP_LLVM_USE_INTERGRATED_SPIRV) set(SPIRV_EMITTER_OPTS "-fintegrated-objemitter") +elseif(LLVM_VERSION_MAJOR GREATER_EQUAL 23) + # LLVM 23's HIPSPV toolchain defaults to the in-tree SPIR-V backend when it + # is built; explicitly request the llvm-spirv translator. + set(SPIRV_EMITTER_OPTS "-fno-integrated-objemitter") endif() if(CHIP_VERBOSE) diff --git a/MacOS-Issues.md b/MacOS-Issues.md index 48ba79f53..14f331ba0 100644 --- a/MacOS-Issues.md +++ b/MacOS-Issues.md @@ -110,7 +110,7 @@ For macOS development, use **Option A** (dynamic LLVM). The `configure_llvm.sh` ### Required Dependencies - Homebrew packages: `spirv-tools`, `cmake`, `ninja` -- Environment modules: `llvm/20.0` (or newer), `ocl-icd-loader`, `pocl` +- Environment modules: `llvm/22.0` (or newer), `ocl-icd-loader`, `pocl` ### Build Command ```bash diff --git a/README.md b/README.md index c59e46394..b59188eee 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,11 @@ Release notes for [1.3](docs/release_notes/chipStar_1.3.rst), [1.2](docs/release ## Prerequisites * Cmake >= 3.20.0 -* Clang and LLVM 20, 21, 22 (plus an experimental `latest` option tracking the maintained [chipStar-llvm-23](https://github.com/CHIP-SPV/llvm-project/tree/chipStar-llvm-23) branch) - * Can be installed, for example, by adding the [LLVM's Debian/Ubuntu repository](https://apt.llvm.org/) and installing packages 'clang-20 llvm-20 clang-tools-20'. +* Clang and LLVM 21, 22, 23 (plus an experimental `latest` option tracking the maintained [chipStar-llvm-23](https://github.com/CHIP-SPV/llvm-project/tree/chipStar-llvm-23) branch) + * Can be installed, for example, by adding the [LLVM's Debian/Ubuntu repository](https://apt.llvm.org/) and installing packages 'clang-21 llvm-21 clang-tools-21'. * For the best results, build Clang/LLVM with the chipStar patches applied (from `llvm-patches/llvm-/`). See below for a scripted way to build and install the patched versions. * SPIRV-LLVM-Translator from a branch matching the LLVM major version: - (e.g. llvm\_release\_200 for LLVM 20, llvm\_release\_210 for LLVM 21) + (e.g. llvm\_release\_210 for LLVM 21, llvm\_release\_220 for LLVM 22) , [llvm-spirv](https://github.com/KhronosGroup/SPIRV-LLVM-Translator). * Make sure the built llvm-spirv binary is installed into the same path as clang binary, otherwise clang might find and use a different llvm-spirv, leading to errors. * SPIRV-Tools and SPIRV-Headers: @@ -101,12 +101,12 @@ For this you can use a script included in the chipStar repository: ```bash ./scripts/configure_llvm.sh Usage: ./scripts/configure_llvm.sh --version --install-dir --link-type static/dynamic(default) [--variant translator|native] [--with-binutils [path]] [--configure-only] [-N] ---version: LLVM version 20, 21, 22, or latest (experimental, tracks the maintained chipStar-llvm-23 branch, no patches) +--version: LLVM version 21, 22, 23, or latest (experimental, tracks the maintained chipStar-llvm-23 branch, no patches) --install-dir: installation directory --link-type: static or dynamic (default: dynamic) -./scripts/configure_llvm.sh --version 20 --install-dir /opt/install/llvm/20.0 -cd llvm-project/llvm/build_20 +./scripts/configure_llvm.sh --version 22 --install-dir /opt/install/llvm/22.0 +cd llvm-project/llvm/build_22 make -j 16 make install ``` @@ -114,13 +114,13 @@ make -j 16 Or you can do the steps manually (clone the release branches, apply the patches from `llvm-patches/llvm-/`, then build): ```bash -git clone --depth 1 https://github.com/llvm/llvm-project.git -b release/20.x +git clone --depth 1 https://github.com/llvm/llvm-project.git -b release/22.x cd llvm-project -for p in /path/to/chipStar/llvm-patches/llvm-20/llvm/*.patch; do git apply "$p"; done +for p in /path/to/chipStar/llvm-patches/llvm-22/llvm/*.patch; do git apply "$p"; done cd llvm/projects -git clone --depth 1 https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git -b llvm_release_200 +git clone --depth 1 https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git -b llvm_release_220 cd SPIRV-LLVM-Translator -for p in /path/to/chipStar/llvm-patches/llvm-20/spirv-translator/*.patch; do git apply "$p"; done +for p in /path/to/chipStar/llvm-patches/llvm-22/spirv-translator/*.patch; do git apply "$p"; done cd ../../.. # DLLVM_ENABLE_PROJECTS="clang;openmp" OpenMP is optional but many apps use it @@ -131,7 +131,7 @@ cmake -S llvm -B build \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS="clang;openmp" \ -DLLVM_TARGETS_TO_BUILD=X86 \ - -DCMAKE_INSTALL_PREFIX=$HOME/local/llvm-20 + -DCMAKE_INSTALL_PREFIX=$HOME/local/llvm-22 make -C build -j8 all install ``` diff --git a/bitcode/CMakeLists.txt b/bitcode/CMakeLists.txt index 276db6599..8b8e1f911 100644 --- a/bitcode/CMakeLists.txt +++ b/bitcode/CMakeLists.txt @@ -205,8 +205,15 @@ function(embed_spirv_in_cpp OUTPUT "${OUTPUT_SOURCE}" "${OUTPUT_HEADER}" DEPENDS "${BC_SOURCE}" BYPRODUCTS "${SPIR_BINARY}" + # NOTE: the triple must NOT carry the "chipstar" OS component here. + # spirv64vX-unknown-chipstar selects the HIPSPV toolchain, whose -c + # action emits LLVM bitcode for the offload driver to link later; it + # exits 0, so the ".spv" silently contains "BC\xc0\xde" instead of + # SPIR-V and every clLinkProgram() of the rtdevlib fails with + # CL_LINK_PROGRAM_FAILURE / CL_INVALID_PROGRAM. The plain spirv64vX + # triple selects the SPIRV toolchain, which emits SPIR-V directly. COMMAND "${CMAKE_CXX_COMPILER}" - --target=spirv64v${MAX_SPIRV_VERSION}-unknown-chipstar + --target=spirv64v${MAX_SPIRV_VERSION} -mllvm -spirv-ext=${SPIRV_EXTENSIONS} -c -x ir "${BC_SOURCE}" -o "${SPIR_BINARY}" diff --git a/cmake/LLVMCheck.cmake b/cmake/LLVMCheck.cmake index dcc6bb77a..2ac892cf1 100644 --- a/cmake/LLVMCheck.cmake +++ b/cmake/LLVMCheck.cmake @@ -1,10 +1,10 @@ if((CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang") OR (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")) - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 20.0.0) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 21.0.0) message(FATAL_ERROR "Unsupported clang version '${CMAKE_CXX_COMPILER_VERSION}'. " - "chipStar requires clang/LLVM 20, 21, or 22 (or the experimental " + "chipStar requires clang/LLVM 21, 22, or 23 (or the experimental " "'latest' toolchain); see scripts/configure_llvm.sh.") endif() else() diff --git a/docs/MacOS.md b/docs/MacOS.md index 70248e86b..c8ffe51f2 100644 --- a/docs/MacOS.md +++ b/docs/MacOS.md @@ -199,7 +199,7 @@ Note: `coreutils` provides the `nproc` command which will be used throughout thi ## Step 2.5: Install Environment Modules (Optional) -Environment Modules provides a convenient way to manage environment variables for different software versions. If you prefer using `module load llvm/20.0` instead of manually setting PATH variables, install it: +Environment Modules provides a convenient way to manage environment variables for different software versions. If you prefer using `module load llvm/22.0` instead of manually setting PATH variables, install it: ```bash brew install modules @@ -233,7 +233,7 @@ chipStar requires a specific version of LLVM/Clang (20, 21, or 22) with patches. ### Using the chipStar configure script: ```bash -./scripts/configure_llvm.sh --version 20 --install-dir $HOME/install/llvm-20 +./scripts/configure_llvm.sh --version 22 --install-dir $HOME/install/llvm-22 cd llvm-project/llvm/build_20 make -j$(nproc) make install @@ -242,7 +242,7 @@ make install Add LLVM to your PATH: ```bash -echo 'export PATH="$HOME/install/llvm-20/bin:$PATH"' >> ~/.zshrc +echo 'export PATH="$HOME/install/llvm-22/bin:$PATH"' >> ~/.zshrc source ~/.zshrc ``` @@ -269,7 +269,7 @@ spirv-as --version Note: The `spirv-extractor` tool in chipStar expects SPIRV-Tools headers at `/opt/homebrew/include/spirv-tools/` (Apple Silicon) or `/usr/local/include/spirv-tools/` (Intel). -**Note on SPIRV-LLVM-Translator**: The `llvm-spirv` tool is automatically built as part of the LLVM build process since the chipStar configure script clones it into `llvm-project/llvm/projects/SPIRV-LLVM-Translator`. It will be installed in `$HOME/install/llvm-20/bin/`. +**Note on SPIRV-LLVM-Translator**: The `llvm-spirv` tool is automatically built as part of the LLVM build process since the chipStar configure script clones it into `llvm-project/llvm/projects/SPIRV-LLVM-Translator`. It will be installed in `$HOME/install/llvm-22/bin/`. ## Step 5: Build OpenCL Components @@ -320,8 +320,8 @@ mkdir build && cd build cmake .. \ -DCMAKE_INSTALL_PREFIX=$HOME/install \ -DENABLE_SPIR=ON \ - -DLLVM_DIR=$HOME/install/llvm-20/lib/cmake/llvm \ - -DLLVM_CONFIG=$HOME/install/llvm-20/bin/llvm-config + -DLLVM_DIR=$HOME/install/llvm-22/lib/cmake/llvm \ + -DLLVM_CONFIG=$HOME/install/llvm-22/bin/llvm-config make -j$(nproc) && make install cd ../../.. @@ -360,7 +360,7 @@ clinfo -l ```bash mkdir build && cd build cmake .. \ - -DLLVM_CONFIG_BIN=$HOME/install/llvm-20/bin/llvm-config \ + -DLLVM_CONFIG_BIN=$HOME/install/llvm-22/bin/llvm-config \ -DCMAKE_INSTALL_PREFIX=$HOME/install/chipStar \ -GNinja ninja -j$(nproc) all build_tests install @@ -392,9 +392,9 @@ python3 scripts/check.py build pocl opencl ### Installation Locations All dependencies are installed to `$HOME/install`: -- **LLVM/Clang**: `$HOME/install/llvm-20/` +- **LLVM/Clang**: `$HOME/install/llvm-22/` - **SPIRV-Tools**: `/opt/homebrew/` or `/usr/local/` (via Homebrew) -- **SPIRV-LLVM-Translator**: `$HOME/install/llvm-20/` +- **SPIRV-LLVM-Translator**: `$HOME/install/llvm-22/` - **OpenCL Headers**: `$HOME/install/include/CL/` - **OpenCL ICD Loader**: `$HOME/install/lib/libOpenCL.dylib` - **PoCL**: `$HOME/install/lib/pocl/` or `$HOME/install/lib/` @@ -412,9 +412,9 @@ All dependencies are installed to `$HOME/install`: Add these to your `~/.zshrc`: ```bash -export PATH="$HOME/install/llvm-20/bin:$PATH" +export PATH="$HOME/install/llvm-22/bin:$PATH" export PATH="$HOME/install/bin:$PATH" -export LLVM_DIR="$HOME/install/llvm-20/lib/cmake/llvm" +export LLVM_DIR="$HOME/install/llvm-22/lib/cmake/llvm" export LD_LIBRARY_PATH="$HOME/install/lib:$LD_LIBRARY_PATH" export DYLD_LIBRARY_PATH="$HOME/install/lib:$DYLD_LIBRARY_PATH" @@ -460,7 +460,7 @@ which llvm-config-20 If not found, add to your `~/.zshrc`: ```bash -export PATH="$HOME/install/llvm-20/bin:$PATH" +export PATH="$HOME/install/llvm-22/bin:$PATH" source ~/.zshrc ``` diff --git a/docs/Profiling.md b/docs/Profiling.md index efa456651..395fe0bdf 100644 --- a/docs/Profiling.md +++ b/docs/Profiling.md @@ -12,10 +12,19 @@ vary by installation. | In-kernel debugging, line info + breakpoints | `-g -O0` | — | | In-kernel debugging, readable locals | `-g -O0` | `CHIP_JIT_FLAGS="-cl-opt-disable"` | -Device debug info requires LLVM built with chipStar's -`preserve-device-debug-info` patch (upstream from LLVM 24, -[llvm#210504](https://github.com/llvm/llvm-project/pull/210504)); -`scripts/configure_llvm.sh` applies it for LLVM 20-22. +Device debug info is stripped by default. No SPIR-V producer emits debug +information that `spirv-val` accepts: the SPIRV-LLVM-Translator emits a +cyclic type reference, and the in-tree SPIR-V backend emits a +`DebugCompilationUnit` whose DWARF version operand is not a 32-bit +unsigned `OpConstant`. Only IGC on Intel Data Center GPU Max tolerates +the result, so chipStar drops the debug metadata in an LLVM pass at +device link time. + +To keep it, build chipStar with `-DCHIP_KEEP_KERNEL_DEBUG_INFO=ON` and an +LLVM 23 toolchain from `scripts/configure_llvm.sh --version 23`, which +applies chipStar's `preserve-device-debug-info` patch (upstream from LLVM +24, [llvm#210504](https://github.com/llvm/llvm-project/pull/210504)). That +combination is only expected to work on Intel Data Center GPU Max. ## Compile time vs JIT time diff --git a/llvm-patches/README.md b/llvm-patches/README.md index ec414784f..8641a4ed2 100644 --- a/llvm-patches/README.md +++ b/llvm-patches/README.md @@ -5,22 +5,24 @@ a small set of patches, kept in one directory per supported LLVM version: ``` llvm-patches/ -├── llvm-20/ +├── llvm-21/ │ ├── llvm/ patches applied in the llvm-project checkout │ └── spirv-translator/ patches applied in the SPIRV-LLVM-Translator checkout -├── llvm-21/ +├── llvm-22/ │ ├── llvm/ │ └── spirv-translator/ -└── llvm-22/ +└── llvm-23/ ├── llvm/ └── spirv-translator/ ``` -`scripts/configure_llvm.sh --version <20|21|22>` clones the matching upstream -branches (`release/.x` and `llvm_release_0`) and applies -every patch in the version's directory, in lexicographic (numeric) order, with -`git apply`. There is no per-patch version gating: everything in a version -directory applies to that version, and a failed patch is a hard error. +`scripts/configure_llvm.sh --version <21|22|23>` clones the matching +upstream LLVM ref (`release/.x`, except 23 which is pinned to the +tag `llvmorg-23.1.0-rc2`) together with the translator branch +`llvm_release_0`, and applies every patch in the version's +directory, in lexicographic (numeric) order, with `git apply`. There is no +per-patch version gating: everything in a version directory applies to that +version, and a failed patch is a hard error. `--version latest` (experimental) is different: it clones the maintained branch `chipStar-llvm-23` from @@ -33,21 +35,24 @@ the release-pinned versions. | LLVM Version | Source | Patches | |---|---|---| -| 20 | `llvm/llvm-project` `release/20.x` | `llvm-patches/llvm-20/` | | 21 | `llvm/llvm-project` `release/21.x` | `llvm-patches/llvm-21/` | | 22 | `llvm/llvm-project` `release/22.x` | `llvm-patches/llvm-22/` | +| 23 | `llvm/llvm-project` `llvmorg-23.1.0-rc2` | `llvm-patches/llvm-23/` | | latest (experimental) | `CHIP-SPV/llvm-project` `chipStar-llvm-23` | none | -LLVM 17, 18, and 19 support was dropped. +LLVM 17 through 20 support was dropped. + +## llvm-21 -## llvm-20 +The reference set the later versions are trimmed down from. The numbering +gap is deliberate: 0002-preserve-device-debug-info was removed, since both +SPIR-V producers reachable on 21 emit debug info that `spirv-val` rejects. ### llvm/ | Patch | Purpose | Upstream status | |---|---|---| | 0001-spirv-version-and-extensions | Enable SPIR-V 1.2 (warp-level primitives via subgroup extensions) and restrict `--spirv-ext` to only the required extensions | Upstreamed in LLVM 23+ behind `Triple::ChipStar` ([llvm#179902](https://github.com/llvm/llvm-project/pull/179902)) | -| 0002-preserve-device-debug-info | Keep debug info intact through the HIP SPIR-V device pipeline | Merged upstream ([llvm#210504](https://github.com/llvm/llvm-project/pull/210504)), ships in LLVM 24; matches the final merged form including SPV_INTEL_optnone | | 0003-unbundle-static-device-libraries | Enable RDC linking with static libraries containing device code | Upstream in LLVM 22+ ([llvm#136412](https://github.com/llvm/llvm-project/pull/136412), commit `ae0614de05ac`) | | 0004-fix-spirv-data-layout | Revert the `-n8:16:32:64` data layout change to avoid bitcode linking mismatches | chipStar-local revert of [llvm#110695](https://github.com/llvm/llvm-project/pull/110695), not upstreamable | | 0005-macos-hip-spirv | HIP SPIR-V compilation on macOS (Mach-O sections, Darwin toolchain guards, skip host stdlib for device) | Upstreamed via [llvm#183991](https://github.com/llvm/llvm-project/pull/183991) + [llvm#206902](https://github.com/llvm/llvm-project/pull/206902) | @@ -61,54 +66,61 @@ LLVM 17, 18, and 19 support was dropped. | 0003-fix-block-merge-innermost-loop | Fix block merging in innermost loops | Upstream in translator 220+ ([KhronosGroup#3280](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3280)) | | 0004-coalesce-duplicate-phi-predecessors | Coalesce duplicate phi predecessors during translation | Pending upstream ([KhronosGroup#3866](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3866)) | -## llvm-21 +## llvm-22 -Same patch set as llvm-20 (rebased onto `release/21.x`): +Smaller set: the unbundle-SDL fix is already upstream in LLVM 22, the data +layout revert is no longer needed, and the loop/block merge fixes are already +upstream in translator 220+. As in llvm-21, the numbering gap is +0002-preserve-device-debug-info, which was removed. ### llvm/ | Patch | Purpose | Upstream status | |---|---|---| -| 0001-spirv-version-and-extensions | As in llvm-20 | Upstreamed in LLVM 23+ behind `Triple::ChipStar` ([llvm#179902](https://github.com/llvm/llvm-project/pull/179902)) | -| 0002-preserve-device-debug-info | As in llvm-20 | Merged upstream ([llvm#210504](https://github.com/llvm/llvm-project/pull/210504)), ships in LLVM 24; matches the final merged form including SPV_INTEL_optnone | -| 0003-unbundle-static-device-libraries | As in llvm-20 | Upstream in LLVM 22+ ([llvm#136412](https://github.com/llvm/llvm-project/pull/136412), `ae0614de05ac`) | -| 0004-fix-spirv-data-layout | As in llvm-20 | chipStar-local revert of [llvm#110695](https://github.com/llvm/llvm-project/pull/110695), not upstreamable | -| 0005-macos-hip-spirv | As in llvm-20 | Upstreamed via [llvm#183991](https://github.com/llvm/llvm-project/pull/183991) + [llvm#206902](https://github.com/llvm/llvm-project/pull/206902) | +| 0001-spirv-version-and-extensions | As in llvm-21 | Upstreamed in LLVM 23+ behind `Triple::ChipStar` ([llvm#179902](https://github.com/llvm/llvm-project/pull/179902)) | +| 0003-macos-hip-spirv | As in llvm-21 | Upstreamed via [llvm#183991](https://github.com/llvm/llvm-project/pull/183991) + [llvm#206902](https://github.com/llvm/llvm-project/pull/206902) | ### spirv-translator/ | Patch | Purpose | Upstream status | |---|---|---| -| 0001-pretend-subgroup-caps-are-spirv-1.2 | As in llvm-20 | Deliberate spec deviation, permanent | -| 0002-fix-loop-merge-placement | As in llvm-20 | Upstream in translator 220+ ([KhronosGroup#3277](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3277)) | -| 0003-fix-block-merge-innermost-loop | As in llvm-20 | Upstream in translator 220+ ([KhronosGroup#3280](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3280)) | -| 0004-coalesce-duplicate-phi-predecessors | As in llvm-20 | Pending upstream ([KhronosGroup#3866](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3866)) | +| 0001-pretend-subgroup-caps-are-spirv-1.2 | As in llvm-21 | Deliberate spec deviation, permanent | +| 0002-coalesce-duplicate-phi-predecessors | As in llvm-21 | Pending upstream ([KhronosGroup#3866](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3866)) | -## llvm-22 +## llvm-23 -Smaller set: the unbundle-SDL fix is already upstream in LLVM 22, the data -layout revert is no longer needed, and the loop/block merge fixes are already -upstream in translator 220+. +Different in kind from the earlier sets. LLVM 23 already carries the SPIR-V +version/extension selection (upstreamed behind `Triple::ChipStar`), the +static-device-library unbundling, the data layout, and the macOS Mach-O +support, so none of those patches are needed. What it does *not* carry is +[llvm#213052](https://github.com/llvm/llvm-project/pull/213052), which +landed after `release/23.x` was cut. ### llvm/ | Patch | Purpose | Upstream status | |---|---|---| -| 0001-spirv-version-and-extensions | As in llvm-20 | Upstreamed in LLVM 23+ behind `Triple::ChipStar` ([llvm#179902](https://github.com/llvm/llvm-project/pull/179902)) | -| 0002-preserve-device-debug-info | As in llvm-20 | Merged upstream ([llvm#210504](https://github.com/llvm/llvm-project/pull/210504)), ships in LLVM 24; matches the final merged form including SPV_INTEL_optnone | -| 0003-macos-hip-spirv | As in llvm-20 | Upstreamed via [llvm#183991](https://github.com/llvm/llvm-project/pull/183991) + [llvm#206902](https://github.com/llvm/llvm-project/pull/206902) | +| 0001-hipspv-in-tree-spirv-backend | Drive the in-tree SPIR-V backend from the HIPSPV toolchain by default, falling back to `llvm-spirv` under `-fno-integrated-objemitter`; map the `chipstar` OS to the Kernel execution environment | Backport of [llvm#213052](https://github.com/llvm/llvm-project/pull/213052) (`7ef0ca2b13f9`), first ships in LLVM 24 | +| 0002-preserve-device-debug-info | Honor `-g` for device code, but only when the in-tree backend is the effective emitter | The ungated form is upstream ([llvm#210504](https://github.com/llvm/llvm-project/pull/210504)); the backend gate is chipStar-specific | + +The gate in 0002 is why device `-g` works here and nowhere else: the +translator's `DebugTypeComposite` `Parent` operand creates a cyclic forward +reference that `spirv-val` rejects and IGC mis-handles, so `-g` must keep +being stripped whenever the translator is the producer. Because the strip +happens in `HIPSPVToolChain::adjustDebugInfoKind`, clang CodeGen never emits +a `DICompileUnit` on that path. ### spirv-translator/ | Patch | Purpose | Upstream status | |---|---|---| -| 0001-pretend-subgroup-caps-are-spirv-1.2 | As in llvm-20 | Deliberate spec deviation, permanent | -| 0002-coalesce-duplicate-phi-predecessors | As in llvm-20 | Pending upstream ([KhronosGroup#3866](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3866)) | +| 0001-pretend-subgroup-caps-are-spirv-1.2 | As in llvm-21 | Deliberate spec deviation, permanent | +| 0002-coalesce-duplicate-phi-predecessors | As in llvm-21 | Pending upstream ([KhronosGroup#3866](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/3866)) | ## Removed in the layout change - **archive-data-layout patch** (`llvm-link` empty "ArchiveModule" data layout fix): deleted; a no-op versus the upstream IRMover behavior. - **fp_fast_mode test patch** (translator): deleted; a no-op. -- **LLVM 17/18/19 support** and their version-specific patch variants were - dropped. +- **LLVM 17 through 20 support** and their version-specific patch variants + were dropped. diff --git a/llvm-patches/llvm-20/llvm/0001-spirv-version-and-extensions.patch b/llvm-patches/llvm-20/llvm/0001-spirv-version-and-extensions.patch deleted file mode 100644 index 73bbc1656..000000000 --- a/llvm-patches/llvm-20/llvm/0001-spirv-version-and-extensions.patch +++ /dev/null @@ -1,51 +0,0 @@ -From d3e5d75098f16e05d660fe736223f4b97dbf2371 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pekka=20J=C3=A4=C3=A4skel=C3=A4inen?= - -Date: Thu, 15 Dec 2022 19:23:56 +0200 -Subject: [PATCH 1/5] Allow SPIR-V 1.2 and restrict extensions to the necessary - set - -Raise the HIPSPV translator invocation's --spirv-max-version from 1.1 to -1.2 to support warp-level primitives (shuffles, ballots) via the -subgroup extensions. Strictly the non-extension shuffle operations would -require v1.3, but it's not supported by any target yet. - -At the same time, replace --spirv-ext=+all with an explicit allowlist of -only the extensions chipStar needs: SPV_INTEL_function_pointers, -SPV_INTEL_subgroups and SPV_EXT_shader_atomic_float_add. "+all" lets -the translator emit extensions that consuming drivers reject. - -This squashes the two historical chipStar patches -(0001-Allow-up-to-v1.2-SPIR-V-features and 0004-only-necessary-exts) -into a single hunk. - -Applies-to: LLVM release/20.x -Upstream-status: upstreamed in LLVM 23+ behind the chipStar toolchain -detection (Triple::ChipStar), llvm/llvm-project#179902, commit -0c8b435c57f6. Still needed as a patch on release/20.x. ---- - clang/lib/Driver/ToolChains/HIPSPV.cpp | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp -index bdbcf91..9e1a4b1 100644 ---- a/clang/lib/Driver/ToolChains/HIPSPV.cpp -+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp -@@ -96,9 +96,11 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( - } - - // Emit SPIR-V binary. -- -- llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.1", -- "--spirv-ext=+all"}; -+ // We need 1.2 when using 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 target yet. -+ llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.2", -+ "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_EXT_shader_atomic_float_add"}; - InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, ""); - SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs); - } --- -2.43.0 - diff --git a/llvm-patches/llvm-20/llvm/0002-preserve-device-debug-info.patch b/llvm-patches/llvm-20/llvm/0002-preserve-device-debug-info.patch deleted file mode 100644 index b8074ed0b..000000000 --- a/llvm-patches/llvm-20/llvm/0002-preserve-device-debug-info.patch +++ /dev/null @@ -1,89 +0,0 @@ -From fcd464ddd71c33203aa31e382715adc965338f91 Mon Sep 17 00:00:00 2001 -From: chipStar -Date: Sat, 18 Jul 2026 14:18:22 +0300 -Subject: [PATCH 2/5] Preserve device debug info for gdb-oneapi - -HIPSPVToolChain::adjustDebugInfoKind() unconditionally forced NoDebugInfo, -so -g/-O0 produced device SPIR-V with no debug metadata at all. The stated -reason (SPIRV-LLVM-Translator aborting on DW_OP_LLVM_convert) no longer -applies: the translator now lowers it to SPIRVDebug::Convert. - -Stop clobbering the requested debug level, and when -g is given emit the -NonSemantic.Shader.DebugInfo form (--spirv-debug-info-version= -nonsemantic-shader-200 + SPV_KHR_non_semantic_info) that Intel's IGC and -gdb-oneapi consume to resolve source lines and locals in device code. - -Also enable SPV_INTEL_optnone when -g is given: clang emits the optnone -function attribute at -O0, and without the extension the translator drops -it, the device compiler optimizes the kernel anyway, and gdb-oneapi -reports every local as - the exact symptom of #1004. - -Refs: CHIP-SPV/chipStar#1004 -Applies-to: LLVM release/20.x -Upstream-status: upstreamed in llvm/llvm-project#210504 (3093d8c577d7), -first ships in LLVM 24. This patch matches the final merged form, -including the SPV_INTEL_optnone enablement from its second commit -(f44bf2b4ce5c). - ---- - clang/lib/Driver/ToolChains/HIPSPV.cpp | 39 ++++++++++++++++++++++---- - 1 file changed, 33 insertions(+), 6 deletions(-) - -diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp -index 9e1a4b1..e8a0ccb 100644 ---- a/clang/lib/Driver/ToolChains/HIPSPV.cpp -+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp -@@ -99,8 +99,28 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( - // We need 1.2 when using 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 target yet. -- llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.2", -- "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_EXT_shader_atomic_float_add"}; -+ std::string SpirvExts = -+ "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups," -+ "+SPV_EXT_shader_atomic_float_add"; -+ llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.2"}; -+ // When the user requests debug info (-g, but not -g0), preserve it into the -+ // SPIR-V in the NonSemantic.Shader.DebugInfo form. Intel's IGC and gdb-oneapi -+ // consume this to map device code back to source lines and local variables; -+ // the translator's default OpenCL.DebugInfo.100 form is not sufficient for -+ // that. Emitting the NonSemantic debug instructions requires the -+ // SPV_KHR_non_semantic_info extension, so it is only enabled here on demand -+ // to keep the default (non-debug) SPIR-V output unchanged. -+ // SPV_INTEL_optnone carries the optnone function attribute, which Clang -+ // emits at -O0. Without the extension the translator drops the attribute, -+ // the device compiler optimizes the kernel anyway, and debuggers report -+ // locals as even though line info is present. At -O1 and -+ // above no optnone attribute exists, so the extension has no effect there. -+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group); -+ A && !A->getOption().matches(options::OPT_g0)) { -+ SpirvExts += ",+SPV_KHR_non_semantic_info,+SPV_INTEL_optnone"; -+ TrArgs.push_back("--spirv-debug-info-version=nonsemantic-shader-200"); -+ } -+ TrArgs.push_back(Args.MakeArgString(SpirvExts)); - InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, ""); - SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs); - } -@@ -283,8 +303,15 @@ VersionTuple HIPSPVToolChain::computeMSVCVersion(const Driver *D, - void HIPSPVToolChain::adjustDebugInfoKind( - llvm::codegenoptions::DebugInfoKind &DebugInfoKind, - const llvm::opt::ArgList &Args) const { -- // Debug info generation is disabled for SPIRV-LLVM-Translator -- // which currently aborts on the presence of DW_OP_LLVM_convert. -- // TODO: Enable debug info when the SPIR-V backend arrives. -- DebugInfoKind = llvm::codegenoptions::NoDebugInfo; -+ // Historically device debug info was force-disabled here because the -+ // SPIRV-LLVM-Translator aborted on DW_OP_LLVM_convert debug expressions. -+ // The translator now lowers that operation (SPIRVDebug::Convert), so honor -+ // the debug level the user requested (e.g. via -g) and let it flow into the -+ // emitted SPIR-V. constructLinkAndEmitSpirvCommand() additionally enables the -+ // NonSemantic.Shader.DebugInfo form at translation time so that Intel's IGC -+ // and gdb-oneapi can consume it. Leaving DebugInfoKind untouched keeps the -+ // default (no -g) behavior unchanged, since the driver defaults it to -+ // NoDebugInfo. -+ (void)DebugInfoKind; -+ (void)Args; - } --- -2.43.0 - diff --git a/llvm-patches/llvm-20/llvm/0003-unbundle-static-device-libraries.patch b/llvm-patches/llvm-20/llvm/0003-unbundle-static-device-libraries.patch deleted file mode 100644 index 4b4c06032..000000000 --- a/llvm-patches/llvm-20/llvm/0003-unbundle-static-device-libraries.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 32e60e3ac258e3b4da0e1cc849533a8a62b3eb9f Mon Sep 17 00:00:00 2001 -From: Paulius Velesko -Date: Mon, 28 Jul 2025 21:22:23 +0300 -Subject: [PATCH 3/5] HIPSPV: Unbundle SDL (#136412) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This fixes the issue of rdc linking static libraries with device code - -https://github.com/CHIP-SPV/chipStar/issues/984 - -Applies-to: LLVM release/20.x -Upstream-status: merged upstream in LLVM 22+ as commit ae0614de05ac -(llvm/llvm-project#136412); backports to release branches were declined. - -Co-authored-by: Henry Linjamäki ---- - clang/lib/Driver/ToolChains/HIPSPV.cpp | 9 ++++++ - .../Driver/hipspv-link-static-library.hip | 28 +++++++++++++++++++ - 2 files changed, 37 insertions(+) - create mode 100644 clang/test/Driver/hipspv-link-static-library.hip - -diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp -index 2c46d12..e7aad1b 100644 ---- a/clang/lib/Driver/ToolChains/HIPSPV.cpp -+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp -@@ -70,8 +70,17 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( - - // Link LLVM bitcode. - ArgStringList LinkArgs{}; -+ - for (auto Input : Inputs) - LinkArgs.push_back(Input.getFilename()); -+ -+ // Add static device libraries using the common helper function. -+ // This handles unbundling archives (.a) containing bitcode bundles. -+ StringRef Arch = getToolChain().getTriple().getArchName(); -+ StringRef Target = -+ "generic"; // SPIR-V is generic, no specific target ID like -mcpu -+ tools::AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LinkArgs, Arch, -+ Target, /*IsBitCodeSDL=*/true); - LinkArgs.append({"-o", TempFile}); - const char *LlvmLink = - Args.MakeArgString(getToolChain().GetProgramPath("llvm-link")); -diff --git a/clang/test/Driver/hipspv-link-static-library.hip b/clang/test/Driver/hipspv-link-static-library.hip -new file mode 100644 -index 0000000..03126ae ---- /dev/null -+++ b/clang/test/Driver/hipspv-link-static-library.hip -@@ -0,0 +1,28 @@ -+// Test HIPSPV static device library linking -+// REQUIRES: system-linux -+// UNSUPPORTED: system-windows -+ -+// Create a dummy archive to test SDL linking -+// RUN: rm -rf %t && mkdir %t -+// RUN: touch %t/dummy.bc -+// RUN: llvm-ar cr %t/libSDL.a %t/dummy.bc -+ -+// Test that -l options are passed to llvm-link for --offload=spirv64 -+// RUN: %clang -### --target=x86_64-linux-gnu --offload=spirv64 \ -+// RUN: --hip-path=%S/Inputs/hipspv -nohipwrapperinc %s \ -+// RUN: -L%t -lSDL \ -+// RUN: 2>&1 | FileCheck -check-prefix=SDL-LINK %s -+ -+// Test that .a files are properly unbundled and passed to llvm-link -+// RUN: %clang -### --target=x86_64-linux-gnu --offload=spirv64 \ -+// RUN: --hip-path=%S/Inputs/hipspv -nohipwrapperinc %s \ -+// RUN: %t/libSDL.a \ -+// RUN: 2>&1 | FileCheck -check-prefix=SDL-ARCHIVE %s -+ -+// Verify that the input files are added before the SDL files in llvm-link command -+// This tests the ordering fix to match HIPAMD behavior -+// SDL-LINK: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libSDL.a" "-targets=hip-spirv64-unknown-unknown-unknown-generic" "-output=[[SDL_A:.*\.a]]" "-allow-missing-bundles" -+// SDL-LINK: "{{.*}}llvm-link" "{{.*}}.bc" "[[SDL_A]]" "-o" -+ -+// SDL-ARCHIVE: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}libSDL.a" "-targets=hip-spirv64-unknown-unknown-unknown-generic" "-output=[[SDL_A:.*\.a]]" "-allow-missing-bundles" -+// SDL-ARCHIVE: "{{.*}}llvm-link" "{{.*}}.bc" "[[SDL_A]]" "-o" --- -2.43.0 - diff --git a/llvm-patches/llvm-20/llvm/0004-fix-spirv-data-layout.patch b/llvm-patches/llvm-20/llvm/0004-fix-spirv-data-layout.patch deleted file mode 100644 index 350a4a714..000000000 --- a/llvm-patches/llvm-20/llvm/0004-fix-spirv-data-layout.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 2024372ae80dad7011beb2835982a7ef305b34f8 Mon Sep 17 00:00:00 2001 -From: Paulius Velesko -Date: Tue, 6 May 2025 19:36:56 +0300 -Subject: [PATCH 4/5] fix SPIR-V data layout - -Drop the "n8:16:32:64" native integer widths from the SPIR-V data -layout strings so optimizations do not create integer types that SPIR-V -consumers cannot handle. - -Applies-to: LLVM release/20.x -Upstream-status: chipStar-local revert of llvm/llvm-project#110695; -not upstreamable. ---- - clang/lib/Basic/Targets/SPIR.h | 6 +++--- - llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp | 4 ++-- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h -index c0849b6..33ed81a 100644 ---- a/clang/lib/Basic/Targets/SPIR.h -+++ b/clang/lib/Basic/Targets/SPIR.h -@@ -313,7 +313,7 @@ public: - // SPIR-V IDs are represented with a single 32-bit word. - SizeType = TargetInfo::UnsignedInt; - resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-" -- "v256:256-v512:512-v1024:1024-n8:16:32:64-G1"); -+ "v256:256-v512:512-v1024:1024-G1"); - } - ArrayRef getTargetBuiltins() const override; - void getTargetDefines(const LangOptions &Opts, -@@ -337,7 +337,7 @@ public: - // we take the maximum because it's possible the Host supports wider types. - MaxAtomicInlineWidth = std::max(MaxAtomicInlineWidth, 32); - resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-" -- "v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"); -+ "v192:256-v256:256-v512:512-v1024:1024-G1"); - } - - void getTargetDefines(const LangOptions &Opts, -@@ -361,7 +361,7 @@ public: - // we take the maximum because it's possible the Host supports wider types. - MaxAtomicInlineWidth = std::max(MaxAtomicInlineWidth, 64); - resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-" -- "v256:256-v512:512-v1024:1024-n8:16:32:64-G1"); -+ "v256:256-v512:512-v1024:1024-G1"); - } - - void getTargetDefines(const LangOptions &Opts, -diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp -index 098c7a6..eba2003 100644 ---- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp -+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp -@@ -60,13 +60,13 @@ static std::string computeDataLayout(const Triple &TT) { - // mean anything. - if (Arch == Triple::spirv32) - return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-" -- "v256:256-v512:512-v1024:1024-n8:16:32:64-G1"; -+ "v256:256-v512:512-v1024:1024-G1"; - if (TT.getVendor() == Triple::VendorType::AMD && - TT.getOS() == Triple::OSType::AMDHSA) - return "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-" - "v512:512-v1024:1024-n32:64-S32-G1-P4-A0"; - return "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-" -- "v512:512-v1024:1024-n8:16:32:64-G1"; -+ "v512:512-v1024:1024-G1"; - } - - static Reloc::Model getEffectiveRelocModel(std::optional RM) { --- -2.43.0 - diff --git a/llvm-patches/llvm-20/llvm/0005-macos-hip-spirv.patch b/llvm-patches/llvm-20/llvm/0005-macos-hip-spirv.patch deleted file mode 100644 index 4ea7816ee..000000000 --- a/llvm-patches/llvm-20/llvm/0005-macos-hip-spirv.patch +++ /dev/null @@ -1,155 +0,0 @@ -From fd93b63ac292e9f4a068c863b9d0eabf7df40b29 Mon Sep 17 00:00:00 2001 -From: Paulius Velesko -Date: Fri, 1 Aug 2025 12:00:00 +0300 -Subject: [PATCH 5/5] Fix HIP SPIR-V compilation on macOS hosts - -Make HIP offloading to SPIR-V work when the host toolchain is Darwin: - -- AlignedAllocation.h: return an empty version tuple for unknown OS - types (e.g. SPIRV device targets) instead of hitting llvm_unreachable. -- CGCUDANV: use Mach-O "segment,section" names for the HIP fatbin - sections on macOS. -- Darwin toolchain: guard addClangWarningOptions, CheckObjCARC and - getSupportedSanitizers against an uninitialized target, which happens - when Darwin serves as the host toolchain for HIP offloading. -- HIPSPV: do not delegate addClangTargetOptions to the host toolchain; - on Darwin it injects macOS libc++-specific flags such as - -faligned-alloc-unavailable that break SPIR-V device compilation. -- HIPUtility: emit the Mach-O section directive for the fatbin symbol. - -Applies-to: LLVM release/20.x -Upstream-status: upstreamed via llvm/llvm-project#183991 and -llvm/llvm-project#206902; still needed on 20.x. ---- - clang/include/clang/Basic/AlignedAllocation.h | 6 +++--- - clang/lib/CodeGen/CGCUDANV.cpp | 10 +++++++--- - clang/lib/Driver/ToolChains/Darwin.cpp | 15 +++++++++++++++ - clang/lib/Driver/ToolChains/HIPSPV.cpp | 6 +++++- - clang/lib/Driver/ToolChains/HIPUtility.cpp | 7 +++++-- - 5 files changed, 35 insertions(+), 9 deletions(-) - -diff --git a/clang/include/clang/Basic/AlignedAllocation.h b/clang/include/clang/Basic/AlignedAllocation.h -index ac26eb4..21bb7e2 100644 ---- a/clang/include/clang/Basic/AlignedAllocation.h -+++ b/clang/include/clang/Basic/AlignedAllocation.h -@@ -24,7 +24,9 @@ namespace clang { - inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { - switch (OS) { - default: -- break; -+ // For unknown/unsupported OS types (e.g. SPIRV, CUDA device targets), -+ // return empty version tuple indicating aligned alloc is always available. -+ return llvm::VersionTuple(); - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: // Earliest supporting version is 10.13. - return llvm::VersionTuple(10U, 13U); -@@ -36,8 +38,6 @@ inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { - case llvm::Triple::ZOS: - return llvm::VersionTuple(); // All z/OS versions have no support. - } -- -- llvm_unreachable("Unexpected OS"); - } - - } // end namespace clang -diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp -index e8d2dca..4333cd0 100644 ---- a/clang/lib/CodeGen/CGCUDANV.cpp -+++ b/clang/lib/CodeGen/CGCUDANV.cpp -@@ -820,10 +820,14 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { - llvm::Constant *FatBinStr; - unsigned FatMagic; - if (IsHIP) { -- FatbinConstantName = ".hip_fatbin"; -- FatbinSectionName = ".hipFatBinSegment"; -+ // On macOS (Mach-O), section names must be in "segment,section" format. -+ FatbinConstantName = -+ CGM.getTriple().isMacOSX() ? "__HIP,__hip_fatbin" : ".hip_fatbin"; -+ FatbinSectionName = -+ CGM.getTriple().isMacOSX() ? "__HIP,__fatbin" : ".hipFatBinSegment"; - -- ModuleIDSectionName = "__hip_module_id"; -+ ModuleIDSectionName = -+ CGM.getTriple().isMacOSX() ? "__HIP,__module_id" : "__hip_module_id"; - ModuleIDPrefix = "__hip_"; - - if (CudaGpuBinary) { -diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp -index 55c55ba..856b023 100644 ---- a/clang/lib/Driver/ToolChains/Darwin.cpp -+++ b/clang/lib/Driver/ToolChains/Darwin.cpp -@@ -1201,6 +1201,12 @@ void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const { - CC1Args.push_back("-Werror=undef-prefix"); - - // For modern targets, promote certain warnings to errors. -+ // Guard against uninitialized target (e.g. when Darwin is used as host -+ // toolchain for HIP/CUDA offloading where the target platform may not -+ // have been fully set up). -+ if (!isTargetInitialized()) -+ return; -+ - if (isTargetWatchOSBased() || getTriple().isArch64Bit()) { - // Always enable -Wdeprecated-objc-isa-usage and promote it - // to an error. -@@ -3593,6 +3599,10 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args, - } - - void Darwin::CheckObjCARC() const { -+ // Guard against uninitialized target (e.g. when Darwin is used as host -+ // toolchain for HIP/CUDA offloading). -+ if (!isTargetInitialized()) -+ return; - if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() || - (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))) - return; -@@ -3612,6 +3622,11 @@ SanitizerMask Darwin::getSupportedSanitizers() const { - Res |= SanitizerKind::FuzzerNoLink; - Res |= SanitizerKind::ObjCCast; - -+ // Guard against uninitialized target (e.g. when Darwin is used as host -+ // toolchain for HIP/CUDA offloading). Return base sanitizers only. -+ if (!isTargetInitialized()) -+ return Res; -+ - // Prior to 10.9, macOS shipped a version of the C++ standard library without - // C++11 support. The same is true of iOS prior to version 5. These OS'es are - // incompatible with -fsanitize=vptr. -diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp -index e7aad1b..362a49b 100644 ---- a/clang/lib/Driver/ToolChains/HIPSPV.cpp -+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp -@@ -157,7 +157,11 @@ 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 { -- 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/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp -index dfe9acc..49d5f59 100644 ---- a/clang/lib/Driver/ToolChains/HIPUtility.cpp -+++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp -@@ -426,9 +426,12 @@ void HIP::constructGenerateObjFileFromHIPFatBinary( - } - if (FoundPrimaryHipFatbinSymbol) { - // Define the first fatbin symbol -- if (HostTriple.isWindowsMSVCEnvironment()) -+ if (HostTriple.isWindowsMSVCEnvironment()) { - ObjStream << " .section .hip_fatbin,\"dw\"\n"; -- else { -+ } else if (HostTriple.isMacOSX()) { -+ // Mach-O requires "segment,section" format -+ ObjStream << " .section __HIP,__hip_fatbin\n"; -+ } else { - ObjStream << " .protected " << PrimaryHipFatbinSymbol << "\n"; - ObjStream << " .type " << PrimaryHipFatbinSymbol << ",@object\n"; - ObjStream << " .section .hip_fatbin,\"a\",@progbits\n"; --- -2.43.0 - diff --git a/llvm-patches/llvm-20/spirv-translator/0002-fix-loop-merge-placement.patch b/llvm-patches/llvm-20/spirv-translator/0002-fix-loop-merge-placement.patch deleted file mode 100644 index 131aa36bf..000000000 --- a/llvm-patches/llvm-20/spirv-translator/0002-fix-loop-merge-placement.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 81472dfb51524335f829fe941b508b098709941f Mon Sep 17 00:00:00 2001 -From: Paulius Velesko -Date: Wed, 23 Jul 2025 13:33:02 +0300 -Subject: [PATCH 2/4] Fix LoopMerge error - -Insert OpLoopMerge and OpLoopControlINTEL immediately before the block's -branch terminator only when that terminator actually is OpBranch or -OpBranchConditional; otherwise append them at the end of the block. -This fixes "OpLoopMerge must appear immediately before the branch" -validation errors. - -Applies-to: SPIRV-LLVM-Translator llvm_release_200 -Upstream-status: merged upstream in llvm_release_220+ as commit 691d303a -(KhronosGroup/SPIRV-LLVM-Translator#3277, Paulius Velesko). ---- - lib/SPIRV/libSPIRV/SPIRVModule.cpp | 36 ++++++++++++++++++++++++------ - 1 file changed, 29 insertions(+), 7 deletions(-) - -diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp -index 5fa2b29..81899a5 100644 ---- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp -+++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp -@@ -1869,10 +1869,22 @@ SPIRVInstruction *SPIRVModuleImpl::addSelectionMergeInst( - SPIRVInstruction *SPIRVModuleImpl::addLoopMergeInst( - SPIRVId MergeBlock, SPIRVId ContinueTarget, SPIRVWord LoopControl, - std::vector LoopControlParameters, SPIRVBasicBlock *BB) { -- return addInstruction( -- new SPIRVLoopMerge(MergeBlock, ContinueTarget, LoopControl, -- LoopControlParameters, BB), -- BB, const_cast(BB->getTerminateInstr())); -+ SPIRVInstruction *TermInst = const_cast(BB->getTerminateInstr()); -+ // OpLoopMerge must be the second-to-last instruction in the block, -+ // immediately preceding the branch instruction (OpBranch or OpBranchConditional) -+ if (TermInst && (TermInst->getOpCode() == OpBranch || -+ TermInst->getOpCode() == OpBranchConditional)) { -+ return addInstruction( -+ new SPIRVLoopMerge(MergeBlock, ContinueTarget, LoopControl, -+ LoopControlParameters, BB), -+ BB, TermInst); -+ } else { -+ // If there's no proper terminator, add at the end -+ return addInstruction( -+ new SPIRVLoopMerge(MergeBlock, ContinueTarget, LoopControl, -+ LoopControlParameters, BB), -+ BB); -+ } - } - - SPIRVInstruction *SPIRVModuleImpl::addLoopControlINTELInst( -@@ -1880,9 +1892,19 @@ SPIRVInstruction *SPIRVModuleImpl::addLoopControlINTELInst( - SPIRVBasicBlock *BB) { - addCapability(CapabilityUnstructuredLoopControlsINTEL); - addExtension(ExtensionID::SPV_INTEL_unstructured_loop_controls); -- return addInstruction( -- new SPIRVLoopControlINTEL(LoopControl, LoopControlParameters, BB), BB, -- const_cast(BB->getTerminateInstr())); -+ SPIRVInstruction *TermInst = const_cast(BB->getTerminateInstr()); -+ // OpLoopControlINTEL must be the second-to-last instruction in the block, -+ // immediately preceding the branch instruction (OpBranch or OpBranchConditional) -+ if (TermInst && (TermInst->getOpCode() == OpBranch || -+ TermInst->getOpCode() == OpBranchConditional)) { -+ return addInstruction( -+ new SPIRVLoopControlINTEL(LoopControl, LoopControlParameters, BB), BB, -+ TermInst); -+ } else { -+ // If there's no proper terminator, add at the end -+ return addInstruction( -+ new SPIRVLoopControlINTEL(LoopControl, LoopControlParameters, BB), BB); -+ } - } - - SPIRVInstruction *SPIRVModuleImpl::addFixedPointIntelInst( --- -2.43.0 - diff --git a/llvm-patches/llvm-20/spirv-translator/0003-fix-block-merge-innermost-loop.patch b/llvm-patches/llvm-20/spirv-translator/0003-fix-block-merge-innermost-loop.patch deleted file mode 100644 index 4287f31d0..000000000 --- a/llvm-patches/llvm-20/spirv-translator/0003-fix-block-merge-innermost-loop.patch +++ /dev/null @@ -1,53 +0,0 @@ -From f30637700557e86fbfece6795ded2b20018c8769 Mon Sep 17 00:00:00 2001 -From: Paulius Velesko -Date: Wed, 23 Jul 2025 17:10:08 +0300 -Subject: [PATCH 3/4] fix blockMerge - -When deciding where to place OpLoopMerge for a conditional branch, use -the innermost loop containing the branch's basic block -(LoopInfo::getLoopFor) instead of iterating over all loops in preorder, -and only emit a merge when one of the branch successors is that loop's -header. - -Applies-to: SPIRV-LLVM-Translator llvm_release_200 -Upstream-status: merged upstream in llvm_release_220+ as commit 9e823ad4 -(KhronosGroup/SPIRV-LLVM-Translator#3280, Paulius Velesko). ---- - lib/SPIRV/SPIRVWriter.cpp | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp -index 9d056b2..b930794 100644 ---- a/lib/SPIRV/SPIRVWriter.cpp -+++ b/lib/SPIRV/SPIRVWriter.cpp -@@ -2492,7 +2492,11 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, - Function *Fun = Branch->getFunction(); - DominatorTree DomTree(*Fun); - LoopInfo LI(DomTree); -- for (const auto *LoopObj : LI.getLoopsInPreorder()) { -+ // Find the innermost loop that contains the current basic block -+ BasicBlock *CurrentBB = Branch->getParent(); -+ const Loop *ContainingLoop = LI.getLoopFor(CurrentBB); -+ -+ if (ContainingLoop) { - // Check whether SuccessorFalse or SuccessorTrue is the loop header BB. - // For example consider following LLVM IR: - // br i1 %compare, label %for.body, label %for.end -@@ -2501,12 +2505,12 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, - // <- SuccessorTrue is 'for.end' aka successor(1) - // meanwhile the true successor (by definition) should be a loop header - // aka 'for.body' -- if (LoopObj->getHeader() == Branch->getSuccessor(1)) -+ if (ContainingLoop->getHeader() == Branch->getSuccessor(1)) - // SuccessorFalse is the loop header BB. - BM->addLoopMergeInst(SuccessorTrue->getId(), // Merge Block - BB->getId(), // Continue Target - LoopControl, Parameters, SuccessorFalse); -- else -+ else if (ContainingLoop->getHeader() == Branch->getSuccessor(0)) - // SuccessorTrue is the loop header BB. - BM->addLoopMergeInst(SuccessorFalse->getId(), // Merge Block - BB->getId(), // Continue Target --- -2.43.0 - diff --git a/llvm-patches/llvm-21/llvm/0002-preserve-device-debug-info.patch b/llvm-patches/llvm-21/llvm/0002-preserve-device-debug-info.patch deleted file mode 100644 index 5aa91987c..000000000 --- a/llvm-patches/llvm-21/llvm/0002-preserve-device-debug-info.patch +++ /dev/null @@ -1,89 +0,0 @@ -From f83dcc1d9f2120758fb75dd990c3d420f305f9a4 Mon Sep 17 00:00:00 2001 -From: chipStar -Date: Sat, 18 Jul 2026 14:18:22 +0300 -Subject: [PATCH 2/5] Preserve device debug info for gdb-oneapi - -HIPSPVToolChain::adjustDebugInfoKind() unconditionally forced NoDebugInfo, -so -g/-O0 produced device SPIR-V with no debug metadata at all. The stated -reason (SPIRV-LLVM-Translator aborting on DW_OP_LLVM_convert) no longer -applies: the translator now lowers it to SPIRVDebug::Convert. - -Stop clobbering the requested debug level, and when -g is given emit the -NonSemantic.Shader.DebugInfo form (--spirv-debug-info-version= -nonsemantic-shader-200 + SPV_KHR_non_semantic_info) that Intel's IGC and -gdb-oneapi consume to resolve source lines and locals in device code. - -Also enable SPV_INTEL_optnone when -g is given: clang emits the optnone -function attribute at -O0, and without the extension the translator drops -it, the device compiler optimizes the kernel anyway, and gdb-oneapi -reports every local as - the exact symptom of #1004. - -Refs: CHIP-SPV/chipStar#1004 -Applies-to: LLVM release/21.x -Upstream-status: upstreamed in llvm/llvm-project#210504 (3093d8c577d7), -first ships in LLVM 24. This patch matches the final merged form, -including the SPV_INTEL_optnone enablement from its second commit -(f44bf2b4ce5c). - ---- - clang/lib/Driver/ToolChains/HIPSPV.cpp | 39 ++++++++++++++++++++++---- - 1 file changed, 33 insertions(+), 6 deletions(-) - -diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp -index a1a7285..2f797d1 100644 ---- a/clang/lib/Driver/ToolChains/HIPSPV.cpp -+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp -@@ -98,8 +98,28 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( - // We need 1.2 when using 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 target yet. -- llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.2", -- "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_EXT_shader_atomic_float_add"}; -+ std::string SpirvExts = -+ "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups," -+ "+SPV_EXT_shader_atomic_float_add"; -+ llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.2"}; -+ // When the user requests debug info (-g, but not -g0), preserve it into the -+ // SPIR-V in the NonSemantic.Shader.DebugInfo form. Intel's IGC and gdb-oneapi -+ // consume this to map device code back to source lines and local variables; -+ // the translator's default OpenCL.DebugInfo.100 form is not sufficient for -+ // that. Emitting the NonSemantic debug instructions requires the -+ // SPV_KHR_non_semantic_info extension, so it is only enabled here on demand -+ // to keep the default (non-debug) SPIR-V output unchanged. -+ // SPV_INTEL_optnone carries the optnone function attribute, which Clang -+ // emits at -O0. Without the extension the translator drops the attribute, -+ // the device compiler optimizes the kernel anyway, and debuggers report -+ // locals as even though line info is present. At -O1 and -+ // above no optnone attribute exists, so the extension has no effect there. -+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group); -+ A && !A->getOption().matches(options::OPT_g0)) { -+ SpirvExts += ",+SPV_KHR_non_semantic_info,+SPV_INTEL_optnone"; -+ TrArgs.push_back("--spirv-debug-info-version=nonsemantic-shader-200"); -+ } -+ TrArgs.push_back(Args.MakeArgString(SpirvExts)); - InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, ""); - SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs); - } -@@ -285,8 +305,15 @@ VersionTuple HIPSPVToolChain::computeMSVCVersion(const Driver *D, - void HIPSPVToolChain::adjustDebugInfoKind( - llvm::codegenoptions::DebugInfoKind &DebugInfoKind, - const llvm::opt::ArgList &Args) const { -- // Debug info generation is disabled for SPIRV-LLVM-Translator -- // which currently aborts on the presence of DW_OP_LLVM_convert. -- // TODO: Enable debug info when the SPIR-V backend arrives. -- DebugInfoKind = llvm::codegenoptions::NoDebugInfo; -+ // Historically device debug info was force-disabled here because the -+ // SPIRV-LLVM-Translator aborted on DW_OP_LLVM_convert debug expressions. -+ // The translator now lowers that operation (SPIRVDebug::Convert), so honor -+ // the debug level the user requested (e.g. via -g) and let it flow into the -+ // emitted SPIR-V. constructLinkAndEmitSpirvCommand() additionally enables the -+ // NonSemantic.Shader.DebugInfo form at translation time so that Intel's IGC -+ // and gdb-oneapi can consume it. Leaving DebugInfoKind untouched keeps the -+ // default (no -g) behavior unchanged, since the driver defaults it to -+ // NoDebugInfo. -+ (void)DebugInfoKind; -+ (void)Args; - } --- -2.43.0 - diff --git a/llvm-patches/llvm-22/llvm/0002-preserve-device-debug-info.patch b/llvm-patches/llvm-22/llvm/0002-preserve-device-debug-info.patch deleted file mode 100644 index bb9e5f137..000000000 --- a/llvm-patches/llvm-22/llvm/0002-preserve-device-debug-info.patch +++ /dev/null @@ -1,89 +0,0 @@ -From b2b3db6a36ebdd3955dce983bb137ae6767c15c2 Mon Sep 17 00:00:00 2001 -From: chipStar -Date: Sat, 18 Jul 2026 14:18:22 +0300 -Subject: [PATCH 2/3] Preserve device debug info for gdb-oneapi - -HIPSPVToolChain::adjustDebugInfoKind() unconditionally forced NoDebugInfo, -so -g/-O0 produced device SPIR-V with no debug metadata at all. The stated -reason (SPIRV-LLVM-Translator aborting on DW_OP_LLVM_convert) no longer -applies: the translator now lowers it to SPIRVDebug::Convert. - -Stop clobbering the requested debug level, and when -g is given emit the -NonSemantic.Shader.DebugInfo form (--spirv-debug-info-version= -nonsemantic-shader-200 + SPV_KHR_non_semantic_info) that Intel's IGC and -gdb-oneapi consume to resolve source lines and locals in device code. - -Also enable SPV_INTEL_optnone when -g is given: clang emits the optnone -function attribute at -O0, and without the extension the translator drops -it, the device compiler optimizes the kernel anyway, and gdb-oneapi -reports every local as - the exact symptom of #1004. - -Refs: CHIP-SPV/chipStar#1004 -Applies-to: LLVM release/22.x -Upstream-status: upstreamed in llvm/llvm-project#210504 (3093d8c577d7), -first ships in LLVM 24. This patch matches the final merged form, -including the SPV_INTEL_optnone enablement from its second commit -(f44bf2b4ce5c). - ---- - clang/lib/Driver/ToolChains/HIPSPV.cpp | 39 ++++++++++++++++++++++---- - 1 file changed, 33 insertions(+), 6 deletions(-) - -diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp -index 4cde8f9..2d24599 100644 ---- a/clang/lib/Driver/ToolChains/HIPSPV.cpp -+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp -@@ -93,8 +93,28 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( - // We need 1.2 when using 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 target yet. -- llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.2", -- "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_EXT_shader_atomic_float_add"}; -+ std::string SpirvExts = -+ "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups," -+ "+SPV_EXT_shader_atomic_float_add"; -+ llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.2"}; -+ // When the user requests debug info (-g, but not -g0), preserve it into the -+ // SPIR-V in the NonSemantic.Shader.DebugInfo form. Intel's IGC and gdb-oneapi -+ // consume this to map device code back to source lines and local variables; -+ // the translator's default OpenCL.DebugInfo.100 form is not sufficient for -+ // that. Emitting the NonSemantic debug instructions requires the -+ // SPV_KHR_non_semantic_info extension, so it is only enabled here on demand -+ // to keep the default (non-debug) SPIR-V output unchanged. -+ // SPV_INTEL_optnone carries the optnone function attribute, which Clang -+ // emits at -O0. Without the extension the translator drops the attribute, -+ // the device compiler optimizes the kernel anyway, and debuggers report -+ // locals as even though line info is present. At -O1 and -+ // above no optnone attribute exists, so the extension has no effect there. -+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group); -+ A && !A->getOption().matches(options::OPT_g0)) { -+ SpirvExts += ",+SPV_KHR_non_semantic_info,+SPV_INTEL_optnone"; -+ TrArgs.push_back("--spirv-debug-info-version=nonsemantic-shader-200"); -+ } -+ TrArgs.push_back(Args.MakeArgString(SpirvExts)); - InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, ""); - SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs); - } -@@ -283,8 +303,15 @@ VersionTuple HIPSPVToolChain::computeMSVCVersion(const Driver *D, - void HIPSPVToolChain::adjustDebugInfoKind( - llvm::codegenoptions::DebugInfoKind &DebugInfoKind, - const llvm::opt::ArgList &Args) const { -- // Debug info generation is disabled for SPIRV-LLVM-Translator -- // which currently aborts on the presence of DW_OP_LLVM_convert. -- // TODO: Enable debug info when the SPIR-V backend arrives. -- DebugInfoKind = llvm::codegenoptions::NoDebugInfo; -+ // Historically device debug info was force-disabled here because the -+ // SPIRV-LLVM-Translator aborted on DW_OP_LLVM_convert debug expressions. -+ // The translator now lowers that operation (SPIRVDebug::Convert), so honor -+ // the debug level the user requested (e.g. via -g) and let it flow into the -+ // emitted SPIR-V. constructLinkAndEmitSpirvCommand() additionally enables the -+ // NonSemantic.Shader.DebugInfo form at translation time so that Intel's IGC -+ // and gdb-oneapi can consume it. Leaving DebugInfoKind untouched keeps the -+ // default (no -g) behavior unchanged, since the driver defaults it to -+ // NoDebugInfo. -+ (void)DebugInfoKind; -+ (void)Args; - } --- -2.43.0 - diff --git a/llvm-patches/llvm-23/llvm/0001-hipspv-in-tree-spirv-backend.patch b/llvm-patches/llvm-23/llvm/0001-hipspv-in-tree-spirv-backend.patch new file mode 100644 index 000000000..de97298a1 --- /dev/null +++ b/llvm-patches/llvm-23/llvm/0001-hipspv-in-tree-spirv-backend.patch @@ -0,0 +1,466 @@ +From 7ef0ca2b13f900000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chipStar +Date: Fri, 31 Jul 2026 00:00:00 +0000 +Subject: [PATCH 1/2] [HIPSPV] Add in-tree SPIR-V backend support for chipStar + +Backport of llvm/llvm-project#213052 (merged 2026-07-31 as 7ef0ca2b13f9, +a reland of #206910). release/23.x branched before it, so a stock LLVM 23 +always emits device SPIR-V through the external SPIRV-LLVM-Translator. + +With this patch the HIPSPV toolchain drives the in-tree SPIR-V backend by +default (clang -cc1 -emit-obj on the lowered bitcode) and falls back to +llvm-spirv when -fno-integrated-objemitter is given or the SPIR-V target +was not built. This matters to chipStar beyond emitter choice: the +translator encodes DebugTypeComposite with a Parent operand, producing a +cyclic forward reference that spirv-val rejects and IGC mis-handles, so +device debug info (-g) only works via the backend. See the companion +0002-preserve-device-debug-info.patch. + +The HipSpvPasses opt invocation is factored into runHipSpvPasses() so both +emitters run it, and SPIRVSubtarget maps the chipstar OS to the Kernel +execution environment. + +Adapted from the upstream commit for release/23.x, which also lacks the +SPIR-V extension list and debug-info flags that main's HIPSPV.cpp had at +the time of the merge; both are folded in here so a patched 23 behaves +exactly like main. + +Applies-to: LLVM llvmorg-23.1.0-rc2 +Upstream-status: merged upstream as 7ef0ca2b13f9, first ships in LLVM 24. +--- +diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp +index d6900c7..98bec18 100644 +--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp ++++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp +@@ -13,6 +13,7 @@ + #include "clang/Driver/Driver.h" + #include "clang/Driver/InputInfo.h" + #include "clang/Options/Options.h" ++#include "llvm/MC/TargetRegistry.h" + #include "llvm/Support/FileSystem.h" + #include "llvm/Support/Path.h" + +@@ -48,6 +49,34 @@ static std::string findPassPlugin(const Driver &D, + return std::string(); + } + ++// Is the in-tree SPIR-V backend built into this clang? ++static bool isSPIRVBackendAvailable(const llvm::Triple &T) { ++ std::string IgnoredError; ++ return llvm::TargetRegistry::lookupTarget(T, IgnoredError); ++} ++ ++// Runs the HipSpvPasses plugin via `opt` on TempFile when the plugin is found. ++// Returns the lowered bitcode path, or TempFile unchanged if no plugin exists. ++static const char *runHipSpvPasses(Compilation &C, const JobAction &JA, ++ const Tool &Creator, const ToolChain &TC, ++ const InputInfoList &Inputs, ++ const InputInfo &Output, ++ const llvm::opt::ArgList &Args, ++ StringRef Name, const char *TempFile) { ++ auto PassPluginPath = findPassPlugin(C.getDriver(), Args); ++ if (PassPluginPath.empty()) ++ return TempFile; ++ const char *PassPathCStr = C.getArgs().MakeArgString(PassPluginPath); ++ const char *OptOutput = HIP::getTempFile(C, Name.str() + "-lower", "bc"); ++ ArgStringList OptArgs{TempFile, "-load-pass-plugin", ++ PassPathCStr, "-passes=hip-post-link-passes", ++ "-o", OptOutput}; ++ const char *Opt = Args.MakeArgString(TC.GetProgramPath("opt")); ++ C.addCommand(std::make_unique( ++ JA, Creator, ResponseFileSupport::None(), Opt, OptArgs, Inputs, Output)); ++ return OptOutput; ++} ++ + void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( + Compilation &C, const JobAction &JA, const InputInfoList &Inputs, + const InputInfo &Output, const llvm::opt::ArgList &Args) const { +@@ -73,44 +102,100 @@ void HIPSPV::Linker::constructLinkAndEmitSpirvCommand( + tools::constructLLVMLinkCommand(C, *this, JA, Inputs, LinkArgs, Output, Args, + TempFile); + +- // Post-link HIP lowering. ++ auto T = getToolChain().getTriple(); + +- // Run LLVM IR passes to lower/expand/emulate HIP code that does not translate +- // to SPIR-V (E.g. dynamic shared memory). +- 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")); ++ if (T.getOS() == llvm::Triple::ChipStar) { ++ // chipStar: run HipSpvPasses via opt, then emit SPIR-V with the in-tree ++ // SPIR-V backend by default, or with the external llvm-spirv translator ++ // when -fno-integrated-objemitter is given (or the backend is not built). ++ ++ // Run HipSpvPasses plugin via opt (must run on LLVM IR before ++ // the SPIR-V backend lowers to MIR). ++ TempFile = runHipSpvPasses(C, JA, *this, getToolChain(), Inputs, Output, ++ Args, Name, TempFile); ++ ++ // Note that useIntegratedBackend() is consulted first so that an explicit ++ // -f(no-)integrated-objemitter still gets diagnosed against this toolchain. ++ if (!getToolChain().useIntegratedBackend() || !isSPIRVBackendAvailable(T)) { ++ // External translator path: BC -> SPIR-V via llvm-spirv. ++ llvm::opt::ArgStringList TrArgs; ++ if (T.getSubArch() == llvm::Triple::NoSubArch) ++ TrArgs.push_back("--spirv-max-version=1.2"); ++ // Keep this extension list in sync with the in-tree backend fallback ++ // below. ++ TrArgs.push_back("--spirv-ext=-all" ++ ",+SPV_INTEL_function_pointers" ++ ",+SPV_INTEL_subgroups" ++ ",+SPV_KHR_bit_instructions" ++ ",+SPV_EXT_shader_atomic_float_add"); ++ ++ // Preserve debug info in the NonSemantic.Shader.DebugInfo form. ++ // These flags are passed unconditionally instead of gating on -g: in ++ // RDC-mode links this job runs in a clang invoked by ++ // clang-linker-wrapper where the original -g is not visible, but the ++ // debug info itself travels in the bitcode. SPV_KHR_non_semantic_info ++ // and the debug info version only take effect when the bitcode carries ++ // debug info. SPV_INTEL_optnone is not tied to debug info: clang emits ++ // optnone at -O0 even without -g, and the emitter needs the extension ++ // allowed to encode it. ++ TrArgs.push_back("--spirv-ext=+SPV_KHR_non_semantic_info" ++ ",+SPV_INTEL_optnone"); ++ TrArgs.push_back("--spirv-debug-info-version=nonsemantic-shader-200"); ++ ++ InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, ""); ++ SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs); ++ return; ++ } ++ ++ // Default: compile the lowered bitcode to SPIR-V with the in-tree backend. ++ // Invoke `clang -cc1` directly rather than the clang driver: the driver ++ // would re-run config-file loading, toolchain detection and argument ++ // translation over an input that is already device-compiled and lowered, ++ // which is both wasteful and fragile. This mirrors how HIPAMD drives its ++ // SPIR-V backend emission (see HIPAMD::constructLinkAndEmitSpirvCommand). ++ // Keep the default -O0 backend pipeline (i.e. no -disable-llvm-optzns) so ++ // the mandatory lowering passes still run, matching the previously ++ // validated driver `-c` behavior. ++ ArgStringList Cc1Args; ++ Cc1Args.push_back("-cc1"); ++ Cc1Args.push_back("-triple"); ++ Cc1Args.push_back(C.getArgs().MakeArgString(T.getTriple())); ++ Cc1Args.push_back("-emit-obj"); ++ ++ // SPIR-V extensions the chipStar runtime relies on. Keep in sync with the ++ // llvm-spirv translator path above. SPV_KHR_non_semantic_info and ++ // SPV_INTEL_optnone let the backend emit NonSemantic.Shader.DebugInfo and ++ // the OptNoneINTEL function control when the bitcode carries debug info / ++ // optnone attributes (the backend's debug handler is a no-op otherwise). ++ Cc1Args.push_back("-mllvm"); ++ Cc1Args.push_back("-spirv-ext=+SPV_INTEL_function_pointers" ++ ",+SPV_INTEL_subgroups" ++ ",+SPV_KHR_bit_instructions" ++ ",+SPV_EXT_shader_atomic_float_add" ++ ",+SPV_KHR_non_semantic_info" ++ ",+SPV_INTEL_optnone"); ++ ++ Cc1Args.push_back(TempFile); ++ Cc1Args.push_back("-o"); ++ Cc1Args.push_back(Output.getFilename()); ++ ++ const Driver &Drv = C.getDriver(); ++ const char *Clang = Drv.getDriverProgramPath(); + C.addCommand(std::make_unique( +- JA, *this, ResponseFileSupport::None(), Opt, OptArgs, Inputs, Output)); +- TempFile = OptOutput; ++ JA, *this, ResponseFileSupport::None(), Clang, Cc1Args, Inputs, Output, ++ Drv.getPrependArg())); ++ return; + } + +- // Emit SPIR-V binary. ++ // Non-chipStar: run HIP passes via opt, then translate with llvm-spirv. ++ TempFile = runHipSpvPasses(C, JA, *this, getToolChain(), Inputs, Output, Args, ++ Name, TempFile); ++ ++ // 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); +@@ -150,6 +235,11 @@ HIPSPVToolChain::HIPSPVToolChain(const Driver &D, const llvm::Triple &Triple, + getProgramPaths().push_back(getDriver().Dir); + } + ++bool HIPSPVToolChain::IsIntegratedBackendSupported() const { ++ // The in-tree SPIR-V backend can only be requested when it is built. ++ return isSPIRVBackendAvailable(getTriple()); ++} ++ + void HIPSPVToolChain::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, + BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const { +diff --git a/clang/lib/Driver/ToolChains/HIPSPV.h b/clang/lib/Driver/ToolChains/HIPSPV.h +index 337c9c9..e38a713 100644 +--- a/clang/lib/Driver/ToolChains/HIPSPV.h ++++ b/clang/lib/Driver/ToolChains/HIPSPV.h +@@ -52,10 +52,18 @@ public: + const llvm::opt::ArgList &Args); + + const llvm::Triple *getAuxTriple() const override { +- assert(HostTC); +- return &HostTC->getTriple(); ++ return HostTC ? &HostTC->getTriple() : nullptr; + } + ++ // Keep IsIntegratedBackendDefault() at the base class' "true": it also ++ // decides whether clang's compile and backend jobs are collapsed into a ++ // single -cc1 invocation, so making it depend on whether the SPIR-V backend ++ // was built would change the device compilation job layout of every HIPSPV ++ // compile. The fallback to the external llvm-spirv translator is decided in ++ // HIPSPV::Linker::constructLinkAndEmitSpirvCommand instead. ++ bool IsIntegratedBackendSupported() const override; ++ bool IsNonIntegratedBackendSupported() const override { return true; } ++ + void + addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, BoundArch BA, +diff --git a/clang/test/Driver/hipspv-link-static-library.hip b/clang/test/Driver/hipspv-link-static-library.hip +index eb114ad..a00f385 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-no-spirv-backend.hip b/clang/test/Driver/hipspv-no-spirv-backend.hip +new file mode 100644 +index 0000000..decab84 +--- /dev/null ++++ b/clang/test/Driver/hipspv-no-spirv-backend.hip +@@ -0,0 +1,41 @@ ++// Coverage for HIPSPV behavior that must not depend on whether the in-tree ++// SPIR-V backend was built. Deliberately not guarded by the ++// spirv-registered-target feature, so builders configured without the SPIR-V ++// target (e.g. X86-only bots) exercise it too. ++ ++// UNSUPPORTED: system-windows ++ ++// The device compilation job layout is a property of the driver, not of the ++// registered targets: an RDC device compile stays a single -cc1 invocation ++// that emits the object directly, rather than being split into a separate ++// -emit-llvm-bc job plus a backend job. ++ ++// RUN: %clang -### -x hip --target=x86_64-linux-gnu --offload=spirv64 \ ++// RUN: --no-offload-new-driver -fgpu-rdc --hip-path=%S/Inputs/hipspv \ ++// RUN: -nohipwrapperinc %S/Inputs/hip_multiple_inputs/a.cu \ ++// RUN: 2>&1 | FileCheck --check-prefix=RDC-JOB %s ++ ++// RDC-JOB: "-cc1" "-triple" "spirv64" ++// RDC-JOB-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" ++// RDC-JOB-SAME: "-emit-obj" ++// RDC-JOB-SAME: "-fcuda-is-device" ++ ++// -fno-integrated-objemitter selects the external llvm-spirv translator, and ++// it is accepted in either configuration. ++ ++// RUN: touch %t.o ++// RUN: %clang -### --no-default-config -o %t.img \ ++// RUN: --target=spirv64-unknown-chipstar %t.o --hip-path=%S/Inputs/hipspv \ ++// RUN: -fno-integrated-objemitter \ ++// RUN: 2>&1 | FileCheck --check-prefix=XTOR -DHIP_PATH=%S/Inputs/hipspv %s ++ ++// XTOR: {{".*llvm-link"}} ++// XTOR-SAME: "-o" [[LINK_BC:".*bc"]] "{{[^ ]*.o}}" ++ ++// XTOR: {{".*opt"}} [[LINK_BC]] "-load-pass-plugin" ++// XTOR-SAME: "[[HIP_PATH]]/lib/libLLVMHipSpvPasses.so" ++// XTOR-SAME: "-passes=hip-post-link-passes" "-o" [[LOWER_BC:".*bc"]] ++ ++// XTOR: {{".*llvm-spirv.*"}} "--spirv-max-version=1.2" ++// XTOR-SAME: [[LOWER_BC]] "-o" "{{.*img}}" ++// XTOR-NOT: "-cc1" +diff --git a/clang/test/Driver/hipspv-pass-plugin.hip b/clang/test/Driver/hipspv-pass-plugin.hip +index 3a0979a..ae6194b 100644 +--- a/clang/test/Driver/hipspv-pass-plugin.hip ++++ b/clang/test/Driver/hipspv-pass-plugin.hip +@@ -1,3 +1,4 @@ ++// REQUIRES: spirv-registered-target + // UNSUPPORTED: system-windows + + // RUN: %clang -### -target x86_64-linux-gnu --offload=spirv64 \ +@@ -16,23 +17,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: env "PATH=" %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: env "PATH=" %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: not env "PATH=" %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: env "PATH=" %clang -### --no-default-config -o /dev/null --target=spirv64-unknown-chipstar \ ++// 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 +44,5 @@ + // NO-PLUGIN-NOT: {{".*opt"}} {{".*.bc"}} "-load-pass-plugin" + // NO-PLUGIN-NOT: {{".*/Inputs/hipspv/lib/libLLVMHipSpvPasses.so"}} + // ALL: {{".*llvm-spirv[^ ]*"}} ++// CHIPSTAR: {{".*clang.*"}} "-cc1" ++// CHIPSTAR-SAME: "-emit-obj" +diff --git a/clang/test/Driver/hipspv-toolchain.hip b/clang/test/Driver/hipspv-toolchain.hip +index 64d5d22..3a262a2 100644 +--- a/clang/test/Driver/hipspv-toolchain.hip ++++ b/clang/test/Driver/hipspv-toolchain.hip +@@ -60,6 +60,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 \ +@@ -72,6 +76,8 @@ + // WRAPPER-SAME: {{[^ ]*.o}} + // WRAPPER-SAME: --hip-path=[[HIP_PATH]] + ++// The in-tree SPIR-V backend is the default emitter; PATH content (e.g. a ++// stray llvm-spirv) must not affect the choice. + // RUN: touch %t.dummy.o + // RUN: %clang -### --no-default-config -o %t.dummy.img \ + // RUN: --target=spirv64-unknown-chipstar %t.dummy.o \ +@@ -85,8 +91,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.*"}} "-cc1" "-triple" "spirv64-unknown-chipstar" ++// CHIPSTAR-SAME: "-emit-obj" ++// CHIPSTAR-SAME: "-mllvm" "-spirv-ext=+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_KHR_bit_instructions,+SPV_EXT_shader_atomic_float_add,+SPV_KHR_non_semantic_info,+SPV_INTEL_optnone" + // CHIPSTAR-SAME: [[LOWER_BC]] "-o" "[[SPIRV_OUT:.*img]]" + + // RUN: %clang -### --no-default-config -o %t.dummy.img \ +@@ -101,10 +108,27 @@ + // 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.*"}} "-cc1" "-triple" "spirv64v1.3-unknown-chipstar" ++// CHIPSTAR-SUBARCH-SAME: "-emit-obj" ++// CHIPSTAR-SUBARCH-SAME: "-mllvm" "-spirv-ext=+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_KHR_bit_instructions,+SPV_EXT_shader_atomic_float_add,+SPV_KHR_non_semantic_info,+SPV_INTEL_optnone" + // CHIPSTAR-SUBARCH-SAME: [[LOWER_BC]] "-o" "[[SPIRV_OUT:.*img]]" + ++// -fno-integrated-objemitter selects the external llvm-spirv translator. ++// RUN: %clang -### --no-default-config -o %t.dummy.img \ ++// RUN: --target=spirv64-unknown-chipstar %t.dummy.o \ ++// RUN: --hip-path="%S/Inputs/hipspv" -fno-integrated-objemitter \ ++// RUN: 2>&1 | FileCheck %s --check-prefix=CHIPSTAR-XTOR -DHIP_PATH=%S/Inputs/hipspv ++ ++// CHIPSTAR-XTOR: {{".*opt"}} {{".*bc"}} "-load-pass-plugin" ++// CHIPSTAR-XTOR-SAME: "[[HIP_PATH]]/lib/libLLVMHipSpvPasses.so" ++// CHIPSTAR-XTOR-SAME: "-passes=hip-post-link-passes" "-o" [[LOWER_BC:".*bc"]] ++ ++// CHIPSTAR-XTOR: {{".*llvm-spirv.*"}} "--spirv-max-version=1.2" ++// CHIPSTAR-XTOR-SAME: "--spirv-ext=-all,+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_KHR_bit_instructions,+SPV_EXT_shader_atomic_float_add" ++// CHIPSTAR-XTOR-SAME: "--spirv-ext=+SPV_KHR_non_semantic_info,+SPV_INTEL_optnone" ++// CHIPSTAR-XTOR-SAME: "--spirv-debug-info-version=nonsemantic-shader-200" ++// CHIPSTAR-XTOR-SAME: [[LOWER_BC]] "-o" "{{.*img}}" ++ + // Check unknown linker options are ignored - such as ones that are targeted at + // spirv-link. HIPSPV toolchain does linking via llvm-link. + // RUN: %clang -### --no-default-config -o %t.dummy.img \ +@@ -123,9 +147,21 @@ + // RUN: | FileCheck -DVERSION=%llvm-version-major \ + // RUN: --check-prefix=VERSIONED %s + ++// With -fno-integrated-objemitter the chipStar path must pick the same ++// versioned translator (lookup shared with SPIRV::constructTranslateCommand). + // 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 ++// RUN: -o %t.dummy.img --target=spirv64-unknown-chipstar %t.dummy.o \ ++// RUN: --hip-path="%S/Inputs/hipspv" -fno-integrated-objemitter 2>&1 \ ++// RUN: | FileCheck -DVERSION=%llvm-version-major --check-prefix=VERSIONED %s + + // VERSIONED: {{.*}}llvm-spirv-[[VERSION]] ++ ++//----------------------------------------------------------------------------- ++// The debug-info flags are passed regardless of -g (covered by the ++// CHIPSTAR-XTOR checks above): in RDC-mode links this job runs in a clang ++// invoked by clang-linker-wrapper where the original -g is not visible, but ++// debug info travels in the bitcode and the flags are no-ops without it. ++// RUN: %clang -### --no-default-config -g -o %t.dummy.img \ ++// RUN: --target=spirv64-unknown-chipstar %t.dummy.o \ ++// RUN: --hip-path="%S/Inputs/hipspv" -fno-integrated-objemitter \ ++// RUN: 2>&1 | FileCheck %s --check-prefix=CHIPSTAR-XTOR -DHIP_PATH=%S/Inputs/hipspv +diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +index be14064..5899f60 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; +-- +2.43.0 + diff --git a/llvm-patches/llvm-23/llvm/0002-preserve-device-debug-info.patch b/llvm-patches/llvm-23/llvm/0002-preserve-device-debug-info.patch new file mode 100644 index 000000000..c4b1b59a4 --- /dev/null +++ b/llvm-patches/llvm-23/llvm/0002-preserve-device-debug-info.patch @@ -0,0 +1,68 @@ +From b2b3db6a36ebdd3955dce983bb137ae6767c15c2 Mon Sep 17 00:00:00 2001 +From: chipStar +Date: Sat, 18 Jul 2026 14:18:22 +0300 +Subject: [PATCH 2/2] Preserve device debug info when the SPIR-V backend emits + +HIPSPVToolChain::adjustDebugInfoKind() unconditionally forced NoDebugInfo, +so -g/-O0 produced device SPIR-V with no debug metadata at all and +gdb-oneapi could not resolve source lines or locals in device code. + +Honor the requested debug level, but only when the module is actually +emitted by the in-tree SPIR-V backend (see +0001-hipspv-in-tree-spirv-backend.patch). The SPIRV-LLVM-Translator +encodes DebugTypeComposite with a Parent operand, which yields a cyclic +forward reference: spirv-val rejects the result and IGC reports an +internal error, so -g must keep being stripped on that path. The gate +mirrors the emitter choice made in constructLinkAndEmitSpirvCommand(), +which means -fno-integrated-objemitter (and a clang built without the +SPIR-V target) gets the strip too. + +Stripping here rather than at translation time means clang CodeGen never +emits a DICompileUnit, so no downstream pass can orphan debug metadata. + +The translator/backend invocations already request +NonSemantic.Shader.DebugInfo (SPV_KHR_non_semantic_info, +--spirv-debug-info-version=nonsemantic-shader-200) and SPV_INTEL_optnone; +those flags are no-ops when the bitcode carries no debug info. + +Refs: CHIP-SPV/chipStar#1004 +Applies-to: LLVM llvmorg-23.1.0-rc2 +Upstream-status: the unconditional form was upstreamed in +llvm/llvm-project#210504 (3093d8c577d7); the backend gate added here is +chipStar-specific and not upstream. +--- +diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp +index 98bec18..e4aaf79 100644 +--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp ++++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp +@@ -423,10 +423,23 @@ VersionTuple HIPSPVToolChain::computeMSVCVersion(const Driver *D, + void HIPSPVToolChain::adjustDebugInfoKind( + llvm::codegenoptions::DebugInfoKind &DebugInfoKind, + const llvm::opt::ArgList &Args) const { +- // Debug info generation is disabled for SPIRV-LLVM-Translator +- // which currently aborts on the presence of DW_OP_LLVM_convert. +- // TODO: Enable debug info when the SPIR-V backend arrives. +- DebugInfoKind = llvm::codegenoptions::NoDebugInfo; ++ // Device debug info is only usable when the in-tree SPIR-V backend emits the ++ // module. The SPIRV-LLVM-Translator encodes DebugTypeComposite with a Parent ++ // operand, which produces a cyclic forward reference that spirv-val rejects ++ // and that device compilers mis-handle (IGC internal errors); the backend ++ // avoids the cycle structurally. So honor the requested debug level only ++ // when the effective emitter is the backend, and otherwise keep forcing ++ // NoDebugInfo. Doing it here rather than at translation time means no debug ++ // metadata is generated at all: the module carries no DICompileUnit, so ++ // nothing downstream can orphan it. ++ // ++ // constructLinkAndEmitSpirvCommand() makes the same ++ // useIntegratedBackend()/isSPIRVBackendAvailable() choice, so a user passing ++ // -fno-integrated-objemitter (or a clang built without the SPIR-V target) ++ // gets the strip as well. ++ if (!useIntegratedBackend() || !isSPIRVBackendAvailable(getTriple())) ++ DebugInfoKind = llvm::codegenoptions::NoDebugInfo; ++ (void)Args; + } + + LTOKind HIPSPVToolChain::getLTOMode(const llvm::opt::ArgList &Args, +-- +2.43.0 + diff --git a/llvm-patches/llvm-23/llvm/0003-subgroup-caps-are-spirv-1.2.patch b/llvm-patches/llvm-23/llvm/0003-subgroup-caps-are-spirv-1.2.patch new file mode 100644 index 000000000..bf3ac2c21 --- /dev/null +++ b/llvm-patches/llvm-23/llvm/0003-subgroup-caps-are-spirv-1.2.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chipStar +Date: Sun, 3 Aug 2026 20:40:00 +0300 +Subject: [PATCH 3/3] Pretend the SPIR-V ver needed by subgroup ops is 1.2 + +Mirror of the SPIRV-LLVM-Translator patch +spirv-translator/0001-pretend-subgroup-caps-are-spirv-1.2.patch, for the +in-tree SPIR-V backend. + +chipStar targets spirv64v1.2 (OFFLOAD_TRIPLE spirv64v1.2-unknown-chipstar +on LLVM 23+). The GroupNonUniform* capabilities genuinely require SPIR-V +1.3 per spec, but they work on the v1.2 implementations we target, which +is why the translator has carried the same deviation for years. + +Without this the backend cannot emit chipStar's warp-level primitives and +aborts the whole compilation (seen building TestBoolParamShuffle): + + GroupNonUniformShuffle(65) requires SPIR-V version 1.3 or later + fatal error: error in backend: Unable to meet SPIR-V requirements + for this target. + +The backend gates these capabilities in two independent places, so both +have to be relaxed: + + 1. SPIRVSymbolicOperands.td, the per-capability minVersion (0x10300). + 2. SPIRVModuleAnalysis.cpp initAvailableCapabilities(), which only makes + the capabilities available at all when the subtarget is >= 1.3. + Relaxing only (1) leaves them unavailable and fails identically. + +The whole GroupNonUniform family is relaxed rather than only Shuffle, +because chipStar emits Shuffle/ShuffleXor (65), ShuffleUp/ShuffleDown +(66), Ballot (64), the arithmetic min/max ops (63) and the Quad ops (68), +and every one of them additionally requires the parent GroupNonUniform +(61), which is itself gated at 1.3. Relaxing only the capability named in +the first diagnostic just moves the error to the next one. + +GroupNonUniformRotateKHR (6026) needs no change: it is gated by +SPV_KHR_subgroup_rotate rather than by a minimum version. + +The initAvailableCapabilities() change is shared with the Vulkan path, +which is harmless here because chipStar only ever builds for the OpenCL +kernel environment, and Vulkan targets separately add GroupNonUniform via +the "Core in Vulkan 1.1 and earlier" block. + +Applies-to: llvm-project llvmorg-23.1.0-rc2 +Upstream-status: deliberate spec deviation, not upstreamable (these +capabilities genuinely require SPIR-V 1.3 per spec). +--- +diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp ++++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +@@ -958,7 +958,7 @@ + addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8, + Capability::Int16}); + +- if (ST.isAtLeastSPIRVVer(VersionTuple(1, 3))) ++ if (ST.isAtLeastSPIRVVer(VersionTuple(1, 2))) + addAvailableCaps({Capability::GroupNonUniform, + Capability::GroupNonUniformVote, + Capability::GroupNonUniformArithmetic, +diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td ++++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +@@ -489,14 +489,14 @@ + defm SubgroupDispatch : CapabilityOperand<58, 0x10100, 0, [], [DeviceEnqueue]>; + defm NamedBarrier : CapabilityOperand<59, 0x10100, 0, [], [Kernel]>; + defm PipeStorage : CapabilityOperand<60, 0x10100, 0, [], [Pipes]>; +-defm GroupNonUniform : CapabilityOperand<61, 0x10300, 0, [], []>; +-defm GroupNonUniformVote : CapabilityOperand<62, 0x10300, 0, [], [GroupNonUniform]>; +-defm GroupNonUniformArithmetic : CapabilityOperand<63, 0x10300, 0, [], [GroupNonUniform]>; +-defm GroupNonUniformBallot : CapabilityOperand<64, 0x10300, 0, [], [GroupNonUniform]>; +-defm GroupNonUniformShuffle : CapabilityOperand<65, 0x10300, 0, [], [GroupNonUniform]>; +-defm GroupNonUniformShuffleRelative : CapabilityOperand<66, 0x10300, 0, [], [GroupNonUniform]>; +-defm GroupNonUniformClustered : CapabilityOperand<67, 0x10300, 0, [], [GroupNonUniform]>; +-defm GroupNonUniformQuad : CapabilityOperand<68, 0x10300, 0, [], [GroupNonUniform]>; ++defm GroupNonUniform : CapabilityOperand<61, 0x10200, 0, [], []>; ++defm GroupNonUniformVote : CapabilityOperand<62, 0x10200, 0, [], [GroupNonUniform]>; ++defm GroupNonUniformArithmetic : CapabilityOperand<63, 0x10200, 0, [], [GroupNonUniform]>; ++defm GroupNonUniformBallot : CapabilityOperand<64, 0x10200, 0, [], [GroupNonUniform]>; ++defm GroupNonUniformShuffle : CapabilityOperand<65, 0x10200, 0, [], [GroupNonUniform]>; ++defm GroupNonUniformShuffleRelative : CapabilityOperand<66, 0x10200, 0, [], [GroupNonUniform]>; ++defm GroupNonUniformClustered : CapabilityOperand<67, 0x10200, 0, [], [GroupNonUniform]>; ++defm GroupNonUniformQuad : CapabilityOperand<68, 0x10200, 0, [], [GroupNonUniform]>; + defm SubgroupBallotKHR : CapabilityOperand<4423, 0, 0, [SPV_KHR_shader_ballot], []>; + defm DrawParameters : CapabilityOperand<4427, 0x10300, 0, [SPV_KHR_shader_draw_parameters], [Shader]>; + defm SubgroupVoteKHR : CapabilityOperand<4431, 0, 0, [SPV_KHR_subgroup_vote], []>; +-- +2.43.0 diff --git a/llvm-patches/llvm-23/llvm/0004-expandvariadics-dont-lower-unmangled-printf.patch b/llvm-patches/llvm-23/llvm/0004-expandvariadics-dont-lower-unmangled-printf.patch new file mode 100644 index 000000000..32308d9df --- /dev/null +++ b/llvm-patches/llvm-23/llvm/0004-expandvariadics-dont-lower-unmangled-printf.patch @@ -0,0 +1,60 @@ +From b1d21c6d3121000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paulius Velesko +Date: Tue, 21 Jul 2026 12:39:16 +0000 +Subject: [PATCH 4/4] [ExpandVariadics] Don't lower unmangled C printf on SPIR-V + +Backport of llvm/llvm-project#206998 +(https://github.com/llvm/llvm-project/pull/206998), merged to main on +2026-07-21 as b1d21c6d3121, after the release/23.x branch was cut. It is +therefore missing from llvmorg-23.1.0-rc2. + +LLVM 23 runs ExpandVariadics in the SPIR-V backend's IR pipeline for +non-shader targets, i.e. for OpenCL kernels. The pass already skips +SPIR-V builtins, but its guard tests the *demangled* name against the +prefix "printf(" and an unmangled C printf demangles to plain "printf", +with no argument list, so the guard misses it. OpenCL/HIP printf is +emitted unmangled, so it was lowered: the arguments got packed into a +Function-storage buffer and a single pointer was passed to the OpenCL.std +printf extended instruction. + + LLVM 22: %87 = OpExtInst %uint %1 printf %fmt %arg0 %arg1 %arg2 + LLVM 23: %99 = OpExtInst %uint %1 printf %fmt %vararg_buffer + +Every device-side printf then printed garbage and crashed. With chipStar's +samples/cuda_samples/0_Simple/simplePrintf, whose kernel prints +"[%d, %d]:\t\tValue is:%d\n": + + expected [0, 0]: Value is:10 + LLVM 23 dGPU [-4120576, ]: Value is: (then SIGSEGV) + LLVM 23 CPU OpenCL [540685652, 0]: Value is:0 + +Independent of device and of IGC: it reproduced on Intel dGPU, iGPU and +the Intel CPU OpenCL runtime, and -cl-opt-disable did not change it. +chipStar's own printf lowering is correct and the IR reaching the backend +is identical on LLVM 22 and 23; feeding that same IR to both backends +produces the two forms above. + +Applies-to: llvm-project llvmorg-23.1.0-rc2 +Upstream-status: merged upstream, drop this patch once release/23.x picks +it up. +--- +diff --git a/llvm/lib/Transforms/IPO/ExpandVariadics.cpp b/llvm/lib/Transforms/IPO/ExpandVariadics.cpp +--- a/llvm/lib/Transforms/IPO/ExpandVariadics.cpp ++++ b/llvm/lib/Transforms/IPO/ExpandVariadics.cpp +@@ -1067,8 +1067,13 @@ + StringRef DemangledName(Demangled); + + // Skip any SPIR-V builtins. ++ // Note: an unmangled C `printf` declaration demangles to "printf" with no ++ // argument list, so the "printf(" prefix check below misses it. Match the ++ // bare name as well so OpenCL/HIP printf (emitted unmangled) is left as a ++ // variadic call for the backend's OpenCL.std printf lowering to expand ++ // inline, rather than being packed into a vararg buffer here. + if (DemangledName.starts_with("__spirv_") || +- DemangledName.starts_with("printf(")) ++ DemangledName.starts_with("printf(") || F->getName() == "printf") + return true; + + return false; +-- +2.43.0 diff --git a/llvm-patches/llvm-23/llvm/0005-spirv-guard-getarg-for-variadic-callees.patch b/llvm-patches/llvm-23/llvm/0005-spirv-guard-getarg-for-variadic-callees.patch new file mode 100644 index 000000000..d4a47bc2e --- /dev/null +++ b/llvm-patches/llvm-23/llvm/0005-spirv-guard-getarg-for-variadic-callees.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: chipStar +Date: Mon, 4 Aug 2026 12:30:00 +0300 +Subject: [PATCH 5/5] [SPIRV] Don't index formal args past a variadic callee + +SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr() walks the operands +of a call with + + for (unsigned OpIdx = 0; OpIdx < CI->arg_size(); OpIdx++) + ... + Argument *CalledArg = CalledF->getArg(OpIdx); + +bounding the loop by the *call's* operand count while indexing the +*callee's* declared parameters. For a variadic callee those differ, and +getArg() asserts: + + Function.h:861: llvm::Function::getArg(unsigned): + Assertion `i < NumArgs && "getArg() out of range!"' failed. + +getArg() is only reached for pointer-typed operands that are not +Instructions or Arguments, i.e. pointer constants, so it needs a variadic +call whose variadic argument is a constant pointer. OpenCL printf with a +"%s" argument is exactly that: the callee declares one parameter (the +format string) and the call carries several, the extra one being a +pointer to a string literal. + +This does not reproduce while ExpandVariadics lowers printf away before +this pass runs. It surfaces once printf is correctly left variadic for +the backend's OpenCL.std lowering (llvm/llvm-project#206998), which is +why chipStar hit it when backporting that fix onto llvmorg-23.1.0-rc2. +The same unguarded indexing is present on main, so a kernel calling +printf("%s", ...) should assert there too. + +Reproducer: chipStar's hip-tests catch/unit/printf/printfFlags_exe.cc, +which crashes clang during hipspv-link. + +Applies-to: llvm-project llvmorg-23.1.0-rc2 +Upstream-status: not yet reported; the same code is on main and looks +like a genuine latent bug rather than a release-branch gap. +--- +diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp ++++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +@@ -2361,6 +2361,13 @@ + // However, we may have assumptions about the formal argument's type and + // may have a need to insert a ptr cast for the actual parameter of this + // call. ++ // A variadic callee has fewer declared parameters than the call has ++ // operands, so OpIdx can address a variadic argument for which no ++ // formal Argument exists. OpenCL kernels reach this with printf, whose ++ // pointer-typed variadic arguments (e.g. "%s") are constants: the ++ // callee declares one parameter but the call carries several. ++ if (OpIdx >= CalledF->arg_size()) ++ continue; + Argument *CalledArg = CalledF->getArg(OpIdx); + if (!GR->findDeducedElementType(CalledArg)) + continue; +-- +2.43.0 diff --git a/llvm-patches/llvm-20/spirv-translator/0001-pretend-subgroup-caps-are-spirv-1.2.patch b/llvm-patches/llvm-23/spirv-translator/0001-pretend-subgroup-caps-are-spirv-1.2.patch similarity index 62% rename from llvm-patches/llvm-20/spirv-translator/0001-pretend-subgroup-caps-are-spirv-1.2.patch rename to llvm-patches/llvm-23/spirv-translator/0001-pretend-subgroup-caps-are-spirv-1.2.patch index 0c667c897..f107a286b 100644 --- a/llvm-patches/llvm-20/spirv-translator/0001-pretend-subgroup-caps-are-spirv-1.2.patch +++ b/llvm-patches/llvm-23/spirv-translator/0001-pretend-subgroup-caps-are-spirv-1.2.patch @@ -1,8 +1,8 @@ -From 64c91bf3410bba6a06472ae0f79b398200cbf6a5 Mon Sep 17 00:00:00 2001 +From 2f97fcc8ea8ab9f8a417daa679d603158f5ea9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20J=C3=A4=C3=A4skel=C3=A4inen?= Date: Thu, 15 Dec 2022 19:31:18 +0200 -Subject: [PATCH 1/4] Pretend the SPIR ver needed by shuffles is 1.2 +Subject: [PATCH 1/2] Pretend the SPIR ver needed by shuffles is 1.2 In reality the SPIR-V shuffles and ballot operations require v1.3, but they seem to work with Intel's v1.2 @@ -12,26 +12,23 @@ Until v1.3 support is added to the driver, let's just pretend these are v1.2 features to allow CHIPSPV warp-level functions to compile. -Applies-to: SPIRV-LLVM-Translator llvm_release_200 -Upstream-status: deliberate deviation from the SPIR-V specification; -permanently downstream. +Applies-to: SPIRV-LLVM-Translator llvm_release_230 +Upstream-status: deliberate spec deviation, not upstreamable (the +GroupNonUniform* capabilities genuinely require SPIR-V 1.3 per spec). --- - lib/SPIRV/libSPIRV/SPIRVEntry.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - diff --git a/lib/SPIRV/libSPIRV/SPIRVEntry.h b/lib/SPIRV/libSPIRV/SPIRVEntry.h -index 409990e..1d44ef9 100644 +index e3f9448..ba0e673 100644 --- a/lib/SPIRV/libSPIRV/SPIRVEntry.h +++ b/lib/SPIRV/libSPIRV/SPIRVEntry.h -@@ -889,7 +889,7 @@ public: +@@ -921,7 +921,7 @@ public: case CapabilityGroupNonUniformShuffle: case CapabilityGroupNonUniformShuffleRelative: case CapabilityGroupNonUniformClustered: - return VersionNumber::SPIRV_1_3; + return VersionNumber::SPIRV_1_2; - case CapabilityNamedBarrier: - case CapabilitySubgroupDispatch: + case CapabilityFloatControls2: + return VersionNumber::SPIRV_1_2; -- 2.43.0 diff --git a/llvm-patches/llvm-20/spirv-translator/0004-coalesce-duplicate-phi-predecessors.patch b/llvm-patches/llvm-23/spirv-translator/0002-coalesce-duplicate-phi-predecessors.patch similarity index 79% rename from llvm-patches/llvm-20/spirv-translator/0004-coalesce-duplicate-phi-predecessors.patch rename to llvm-patches/llvm-23/spirv-translator/0002-coalesce-duplicate-phi-predecessors.patch index f8317e7ea..4e78b0330 100644 --- a/llvm-patches/llvm-20/spirv-translator/0004-coalesce-duplicate-phi-predecessors.patch +++ b/llvm-patches/llvm-23/spirv-translator/0002-coalesce-duplicate-phi-predecessors.patch @@ -1,7 +1,7 @@ -From 97622ab4a4cfc1714f21d13591e60eb8f6f0f7ad Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: chipStar -Date: Thu, 18 Jun 2026 00:00:00 +0000 -Subject: [PATCH 4/4] Coalesce duplicate predecessors when emitting OpPhi +Date: Wed, 18 Jun 2026 00:00:00 +0000 +Subject: [PATCH 2/2] Coalesce duplicate predecessors when emitting OpPhi LLVM IR allows a PHI to list the same predecessor block more than once (e.g. a switch with several cases branching to the same block); the LLVM @@ -13,18 +13,16 @@ count"), which IGC then mis-handles (nondeterministic crash / miscompile). Skip duplicate predecessor entries when building the OpPhi operand list. -Applies-to: SPIRV-LLVM-Translator llvm_release_200 -Upstream-status: pending upstream via -KhronosGroup/SPIRV-LLVM-Translator#3866. +Applies-to: SPIRV-LLVM-Translator llvm_release_230 +Upstream-status: same defect fixed upstream-pending in +KhronosGroup/SPIRV-LLVM-Translator#3866 (approved, unmerged). +chipStar regression test: tests/compiler/TestSpirvDuplicatePhiHip.hip. --- - lib/SPIRV/SPIRVWriter.cpp | 11 +++++++++++ - 1 file changed, 11 insertions(+) - diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp -index b930794..8dd064e 100644 +index d2b564a..5f44c80 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp -@@ -2526,7 +2526,18 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, +@@ -2645,7 +2645,18 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, std::vector IncomingPairs; SPIRVType *Ty = transScavengedType(Phi); diff --git a/llvm_passes/CMakeLists.txt b/llvm_passes/CMakeLists.txt index 609bfbc56..f1e2d366a 100644 --- a/llvm_passes/CMakeLists.txt +++ b/llvm_passes/CMakeLists.txt @@ -98,7 +98,7 @@ endif() add_library(LLVMHipStripUsedIntrinsics MODULE HipStripUsedIntrinsics.cpp) add_library(LLVMHipDefrost MODULE HipDefrost.cpp) add_library(LLVMHipPasses MODULE HipPasses.cpp - HipDynMem.cpp HipStripUsedIntrinsics.cpp HipDefrost.cpp + HipDynMem.cpp HipStripUsedIntrinsics.cpp HipStripDebugInfo.cpp HipDefrost.cpp HipPrintf.cpp HipGlobalVariables.cpp HipCleanup.cpp HipTextureLowering.cpp HipAbort.cpp HipEmitLoweredNames.cpp HipWarps.cpp HipKernelArgSpiller.cpp HipLowerZeroLengthArrays.cpp HipSanityChecks.cpp HipLowerSwitch.cpp @@ -139,7 +139,8 @@ endif() # validation pipeline runs automatically (see HipVerify.cpp::getVerificationMode). # Release builds keep it off due to the compile-time cost (CHIP-SPV/chipStar#1047). target_compile_definitions(LLVMHipPasses PRIVATE - $<$:CHIP_DEBUG_BUILD>) + $<$:CHIP_DEBUG_BUILD> + $<$:CHIP_KEEP_KERNEL_DEBUG_INFO>) # If trying to recompile with LLVM unloaded, the inlcude path is not found target_compile_options(LLVMHipDynMem PRIVATE -I/${LLVM_INCLUDE_DIRS}) diff --git a/llvm_passes/HipPasses.cpp b/llvm_passes/HipPasses.cpp index 3a8055688..e6c1eec19 100644 --- a/llvm_passes/HipPasses.cpp +++ b/llvm_passes/HipPasses.cpp @@ -18,6 +18,7 @@ #include "HipCleanup.h" #include "HipDefrost.h" #include "HipDynMem.h" +#include "HipStripDebugInfo.h" #include "HipStripUsedIntrinsics.h" #include "HipWarps.h" #include "HipPrintf.h" @@ -125,7 +126,16 @@ addPassWithVerification(ModulePassManager &MPM, PassT &&P, static void addFullLinkTimePasses(ModulePassManager &MPM) { MPM.addPass(HipFixOpenCLMDPass()); // must be first or else we get OCL Version mismatch - + +#ifndef CHIP_KEEP_KERNEL_DEBUG_INFO + // No SPIR-V producer emits debug information our consumers accept, so drop it + // up front unless the build opted in (-DCHIP_KEEP_KERNEL_DEBUG_INFO=ON, which + // only makes sense on Intel Data Center GPU Max). Doing it here also spares + // the passes below from keeping debug metadata consistent as they erase + // globals and functions. See HipStripDebugInfo.cpp. + MPM.addPass(HipStripDebugInfoPass()); +#endif + // Clear any previous results at the start of a new pipeline HipVerifyPass::clearResults(); diff --git a/llvm_passes/HipPrintf.cpp b/llvm_passes/HipPrintf.cpp index 7702ec000..d07b0dcea 100644 --- a/llvm_passes/HipPrintf.cpp +++ b/llvm_passes/HipPrintf.cpp @@ -133,11 +133,7 @@ getFormatStringPieces(Value *FmtStrArg, unsigned &NumberOfFormatSpecs) { dyn_cast(OrigFmtStr->getInitializer()); if (FmtStrData == nullptr) { -#if LLVM_VERSION_MAJOR >= 23 assert(OrigFmtStr->getInitializer()->isNullValue()); -#else - assert(OrigFmtStr->getInitializer()->isZeroValue()); -#endif FmtStrPieces.push_back(""); NumberOfFormatSpecs = 0; return FmtStrPieces; @@ -430,9 +426,22 @@ PreservedAnalyses HipPrintfToOpenCLPrintfPass::run(Module &Mod, GlobalValue *Printf = Mod.getNamedValue("printf"); GlobalValue *HipPrintf = Mod.getNamedValue(ORIG_PRINTF_FUNC_NAME); - // No printf decl in the module, no printf calls to handle. - // 1 use if the "printf" is only used by "_cl_printf" - if (Printf == nullptr || Printf->getNumUses() == 1) + // No printf decl in the module: no printf calls to handle. + if (Printf == nullptr) + return PreservedAnalyses::all(); + + // If the pass already ran on this module it created the "_cl_print_str" + // helper, whose body contains the only remaining printf("%c", ...) call. + // In that case the single printf use is already in the lowered (constant + // address space) form and there is nothing more to do. We must NOT use a + // bare "getNumUses() == 1" test here: a module with exactly one *genuine* + // printf call and no _cl_print_str yet (e.g. only the device-side + // __assert_fail printf) also has a single use, and skipping it would leave + // the format string in a non-constant address space. That forces the + // SPIR-V translator to emit SPV_EXT_relaxed_printf_string_address_space, + // which the consumer (e.g. IGC) then rejects at module load time. + if (Mod.getNamedValue(ORIG_PRINT_STRING_FUNC_NAME) != nullptr && + Printf->getNumUses() == 1) return PreservedAnalyses::all(); LLVM_DEBUG(dbgs() << "Found printf decl: "; Printf->dump()); diff --git a/llvm_passes/HipStripDebugInfo.cpp b/llvm_passes/HipStripDebugInfo.cpp new file mode 100644 index 000000000..c0f6a762c --- /dev/null +++ b/llvm_passes/HipStripDebugInfo.cpp @@ -0,0 +1,40 @@ +//===- HipStripDebugInfo.cpp ----------------------------------------------===// +// +// Part of the chipStar Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// LLVM pass removing debug information from HIP device code modules. +// +// Neither SPIR-V producer emits debug information our consumers accept: the +// SPIRV-LLVM-Translator emits a cyclic DebugTypeComposite reference which +// spirv-val rejects, and the in-tree SPIR-V backend emits a DebugCompilationUnit +// whose DWARF version operand is not a 32-bit unsigned OpConstant. The spec +// answer for the former, SPV_KHR_relaxed_extended_instruction, is implemented by +// none of the drivers chipStar targets. +// +// Only IGC on Intel Data Center GPU Max tolerates the malformed result, which is +// what makes gdb-oneapi usable on Aurora. Everywhere else the invalid SPIR-V +// either fails validation or makes the device compiler ICE, so the debug +// information has to go. Configure with -DCHIP_KEEP_KERNEL_DEBUG_INFO=ON to keep +// it (see llvm_passes/CMakeLists.txt); the default is to strip. +// +// Stripping here, at the head of the link-time pipeline, also means none of the +// HIP lowering passes has to keep debug metadata consistent while it erases +// globals and functions. +//===----------------------------------------------------------------------===// + +#include "HipStripDebugInfo.h" + +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/Module.h" + +using namespace llvm; + +PreservedAnalyses HipStripDebugInfoPass::run(Module &M, + ModuleAnalysisManager &AM) { + return StripDebugInfo(M) ? PreservedAnalyses::none() + : PreservedAnalyses::all(); +} diff --git a/llvm_passes/HipStripDebugInfo.h b/llvm_passes/HipStripDebugInfo.h new file mode 100644 index 000000000..020a2ef55 --- /dev/null +++ b/llvm_passes/HipStripDebugInfo.h @@ -0,0 +1,25 @@ +//===- HipStripDebugInfo.h ------------------------------------------------===// +// +// Part of the chipStar Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// LLVM pass removing debug information from HIP device code modules. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_HIP_STRIP_DEBUG_INFO_H +#define LLVM_PASSES_HIP_STRIP_DEBUG_INFO_H + +#include "llvm/IR/PassManager.h" + +using namespace llvm; + +class HipStripDebugInfoPass : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + static bool isRequired() { return true; } +}; + +#endif diff --git a/samples/hip_sycl_interop/CMakeLists.txt b/samples/hip_sycl_interop/CMakeLists.txt index 3bf39be57..949b4aab2 100644 --- a/samples/hip_sycl_interop/CMakeLists.txt +++ b/samples/hip_sycl_interop/CMakeLists.txt @@ -2,7 +2,14 @@ add_subdirectory(onemkl_gemm_wrapper) add_chip_binary(hip_sycl_interop hip_sycl_interop.cpp) add_dependencies(samples hip_sycl_interop) -target_link_options(hip_sycl_interop PRIVATE -fsycl -L${MKL_ROOT}/lib -L${CMAKE_BINARY_DIR} ${INTEL_LIBS} -Wl,-rpath=${CMAKE_BINARY_DIR}:${CMAKE_CURRENT_BINARY_DIR}/onemkl_gemm_wrapper:${ICPX_CORE_LIBDIR}:${ICPX_SYCL_LIBDIR}) + +# No -fsycl here: this executable has no SYCL device code (all of it lives in +# onemkl_gemm_wrapper, built by icpx), and INTEL_LIBS already supplies -lsycl. +# -fsycl is a driver mode switch, not a -l shortcut: it routes the link through +# clang-linker-wrapper, which from LLVM 23 on adds libLLVMSYCL.so to the link. +# That library only exists in an LLVM built with the SYCL project, which +# chipStar's is not, so the link fails with "cannot find libLLVMSYCL.so". +target_link_options(hip_sycl_interop PRIVATE -L${MKL_ROOT}/lib -L${CMAKE_BINARY_DIR} ${INTEL_LIBS} -Wl,-rpath=${CMAKE_BINARY_DIR}:${CMAKE_CURRENT_BINARY_DIR}/onemkl_gemm_wrapper:${ICPX_CORE_LIBDIR}:${ICPX_SYCL_LIBDIR}) target_link_libraries(hip_sycl_interop onemkl_gemm_wrapper -L${CMAKE_BINARY_DIR} -lCHIP ${LevelZero_LIBRARY} -pthread) target_include_directories(hip_sycl_interop PUBLIC ${CHIP_SRC_DIR}/HIP/include ${CHIP_SRC_DIR}/include) diff --git a/samples/hip_sycl_interop_no_buffers/CMakeLists.txt b/samples/hip_sycl_interop_no_buffers/CMakeLists.txt index 5c364911d..fe404a4d5 100644 --- a/samples/hip_sycl_interop_no_buffers/CMakeLists.txt +++ b/samples/hip_sycl_interop_no_buffers/CMakeLists.txt @@ -2,7 +2,9 @@ add_subdirectory(onemkl_gemm_wrapper_no_buffers) add_chip_binary(hip_sycl_interop_no_buffers hip_sycl_interop.cpp) add_dependencies(samples hip_sycl_interop_no_buffers) -target_link_options(hip_sycl_interop_no_buffers PRIVATE -fsycl -L${MKL_ROOT}/lib -L${CMAKE_BINARY_DIR} ${INTEL_LIBS} -Wl,-rpath=${CMAKE_BINARY_DIR}:${CMAKE_CURRENT_BINARY_DIR}/onemkl_gemm_wrapper_no_buffers:${ICPX_CORE_LIBDIR}:${ICPX_SYCL_LIBDIR}) + +# No -fsycl here; see the comment in ../hip_sycl_interop/CMakeLists.txt. +target_link_options(hip_sycl_interop_no_buffers PRIVATE -L${MKL_ROOT}/lib -L${CMAKE_BINARY_DIR} ${INTEL_LIBS} -Wl,-rpath=${CMAKE_BINARY_DIR}:${CMAKE_CURRENT_BINARY_DIR}/onemkl_gemm_wrapper_no_buffers:${ICPX_CORE_LIBDIR}:${ICPX_SYCL_LIBDIR}) target_link_libraries(hip_sycl_interop_no_buffers onemkl_gemm_wrapper_no_buffers) add_test(NAME "hip_sycl_interop_no_buffers" diff --git a/scripts/configure_llvm.sh b/scripts/configure_llvm.sh index e1ef4c21a..81df2f677 100755 --- a/scripts/configure_llvm.sh +++ b/scripts/configure_llvm.sh @@ -78,8 +78,9 @@ done # check mandatory argument version if [ -z "$VERSION" ]; then echo "Usage: $0 --version --install-dir --link-type static/dynamic(default) [--variant translator|native] [--with-binutils [path]] [--configure-only] [-N]" - echo "--version: LLVM version 20, 21, 22, or latest" - echo " 20/21/22: upstream release branch plus patches from llvm-patches/llvm-/" + echo "--version: LLVM version 21, 22, 23, or latest" + echo " 21/22: upstream release branch plus patches from llvm-patches/llvm-/" + echo " 23: upstream tag llvmorg-23.1.0-rc2 plus patches from llvm-patches/llvm-23/" echo " latest (experimental): CHIP-SPV/llvm-project branch chipStar-llvm-23, maintained" echo " directly with no patches (patches exist only for the release-pinned versions)" echo "--install-dir: installation directory" @@ -98,10 +99,10 @@ if [ -z "$INSTALL_DIR" ]; then fi # validate version argument -if [ "$VERSION" != "20" ] && [ "$VERSION" != "21" ] && [ "$VERSION" != "22" ] \ +if [ "$VERSION" != "21" ] && [ "$VERSION" != "22" ] && [ "$VERSION" != "23" ] \ && [ "$VERSION" != "latest" ]; then - echo "Invalid version '$VERSION'. Must be 20, 21, 22, or latest." - echo "(Support for LLVM 17, 18, and 19 has been dropped.)" + echo "Invalid version '$VERSION'. Must be 21, 22, 23, or latest." + echo "(Support for LLVM 17 through 20 has been dropped.)" exit 1 fi @@ -137,12 +138,31 @@ if [ "$VERSION" == "latest" ]; then LLVM_REPO="https://github.com/CHIP-SPV/llvm-project.git" LLVM_BRANCH="chipStar-llvm-23" TRANSLATOR_BRANCH="llvm_release_230" +elif [ "$VERSION" == "23" ]; then + # Pinned to a release candidate tag rather than release/23.x: the branch + # moves, and the llvm-patches/llvm-23 series (in particular the llvm#213052 + # backport) is verified against this exact tree. + LLVM_REPO="https://github.com/llvm/llvm-project.git" + LLVM_BRANCH="llvmorg-23.1.0-rc2" + TRANSLATOR_BRANCH="llvm_release_230" else LLVM_REPO="https://github.com/llvm/llvm-project.git" LLVM_BRANCH="release/${VERSION}.x" TRANSLATOR_BRANCH="llvm_release_${VERSION}0" fi +# LLVM 23 removed the LLVM_ENABLE_PROJECTS=openmp build mode; openmp has to be +# built as a runtime there. Earlier versions still expect it as a project, and +# CI hard-fails when omp.h is missing from the install (TestHipccFopenmp), so +# this has to stay version conditional. +if [ "$VERSION" == "23" ] || [ "$VERSION" == "latest" ]; then + LLVM_PROJECTS="clang;clang-tools-extra" + LLVM_RUNTIMES="openmp" +else + LLVM_PROJECTS="clang;openmp;clang-tools-extra" + LLVM_RUNTIMES="" +fi + export LLVM_DIR=`pwd`/llvm-project/llvm # If we're only emitting the cmake command, skip the git operations @@ -301,7 +321,7 @@ COMMON_CMAKE_OPTIONS=( "-DCMAKE_C_COMPILER=${CC}" "-DCMAKE_INSTALL_PREFIX=${INSTALL_DIR}" "-DCMAKE_BUILD_TYPE=Release" - "-DLLVM_ENABLE_PROJECTS=\"clang;openmp;clang-tools-extra\"" + "-DLLVM_ENABLE_PROJECTS=\"${LLVM_PROJECTS}\"" "-DLLVM_TARGETS_TO_BUILD=\"${LLVM_TARGETS}\"" "-DLLVM_ENABLE_ASSERTIONS=On" "-DLLVM_INCLUDE_TESTS=OFF" @@ -310,6 +330,10 @@ COMMON_CMAKE_OPTIONS=( "-DLLVM_INCLUDE_DOCS=OFF" ) +if [ -n "${LLVM_RUNTIMES}" ]; then + COMMON_CMAKE_OPTIONS+=("-DLLVM_ENABLE_RUNTIMES=\"${LLVM_RUNTIMES}\"") +fi + # Linux-specific flags if [[ "$(uname)" != "Darwin" ]]; then COMMON_CMAKE_OPTIONS+=( diff --git a/scripts/unit_tests.sh b/scripts/unit_tests.sh index c01fc73fa..d841dbc41 100755 --- a/scripts/unit_tests.sh +++ b/scripts/unit_tests.sh @@ -44,7 +44,7 @@ build_type=$(echo "$1" | tr '[:lower:]' '[:upper:]') # Check if the second argument starts with "llvm-" and is followed by a valid version number if [[ ! "$2" =~ ^llvm-(1[6-9]|[2-9][0-9])$ ]]; then - echo "Error: Invalid LLVM version. Must be llvm-20, llvm-21, llvm-22, or higher." + echo "Error: Invalid LLVM version. Must be llvm-21, llvm-22, llvm-23, or higher." exit 1 fi @@ -133,13 +133,29 @@ detect_build_tool() { echo "Detected CMake generator: $generator, using build tool: $BUILD_TOOL" } -# For LLVM 22+ with variant, use module name llvm/22.0-translator or llvm/22.0-native +# How --variant selects the SPIR-V producer depends on the LLVM version. +# +# LLVM 22 has no in-tree HIPSPV backend support (llvm#213052 landed after the 23 +# branch was cut), so the two producers need two separate toolchains and the +# variant picks between the modules llvm/22.0-translator and llvm/22.0-native. +# +# From LLVM 23 on, chipStar patches in llvm#213052, so a single toolchain built +# with the SPIRV target serves both: the translator is built either way, and the +# producer is chosen per compilation by -f[no-]integrated-objemitter. One module, +# llvm/23.0, and the variant becomes a compile flag. +VARIANT_OPTS="" if [[ -n "$variant" ]]; then if [[ "$llvm_version" -lt 22 ]]; then echo "Error: --variant is only supported for LLVM 22 and later." exit 1 fi - CLANG="llvm/${llvm_version}.0-${variant}" + if [[ "$llvm_version" -lt 23 ]]; then + CLANG="llvm/${llvm_version}.0-${variant}" + elif [[ "$variant" == "native" ]]; then + VARIANT_OPTS="-DCHIP_LLVM_USE_INTERGRATED_SPIRV=ON" + else + VARIANT_OPTS="-DCHIP_LLVM_USE_INTERGRATED_SPIRV=OFF" + fi fi # Print out the arguments @@ -230,7 +246,7 @@ else echo "building with $CLANG" LLVM_CONFIG_BIN=$(module show $CLANG 2>&1 | grep -E 'prepend-path\s+PATH' | awk '{print $NF}' | head -1)/llvm-config - cmake ../ -DLLVM_CONFIG_BIN=$LLVM_CONFIG_BIN -DCMAKE_BUILD_TYPE="$build_type" ${CHIP_OPTIONS} + cmake ../ -DLLVM_CONFIG_BIN=$LLVM_CONFIG_BIN -DCMAKE_BUILD_TYPE="$build_type" ${CHIP_OPTIONS} ${VARIANT_OPTS} detect_build_tool $BUILD_TOOL all install -j $(nproc) #&> /dev/null $BUILD_TOOL build_tests install -j $(nproc) #&> /dev/null diff --git a/src/CHIPDriver.cc b/src/CHIPDriver.cc index 903488fec..80faba594 100644 --- a/src/CHIPDriver.cc +++ b/src/CHIPDriver.cc @@ -230,12 +230,19 @@ void CHIPUninitializeCallOnce() { if (LegacyQueue) { LegacyQueue->finish(); } - if (Dev->isPerThreadStreamUsed()) { - auto PerThreadQueue = Dev->getPerThreadDefaultQueue(); - if (PerThreadQueue) { - PerThreadQueue->finish(); - } - } + // Note: the per-thread default queue is deliberately NOT synced here. + // PerThreadDefaultQueue is a thread_local unique_ptr whose destructor + // may already have run by the time this atexit handler executes (TLS + // destruction order versus atexit order is implementation-defined). + // Reading destroyed TLS is UB and segfaults with some compilers (e.g. + // clang 23). A null check cannot help: it reads the same destroyed + // storage. + // + // Nothing else syncs it either. ~Queue() is empty, ~CHIPQueueOpenCL() + // only logs, and ~CHIPQueueLevel0() skips finish() on purpose because + // the Level Zero context may already be gone. So in-flight work on a + // per-thread stream is not awaited at exit. Fixing that needs a + // non-TLS registry of the per-thread queues; see issue #1439. } // call deallocateDeviceVariables on all devices.