diff --git a/.github/workflows/test-llvm23.yml b/.github/workflows/test-llvm23.yml new file mode 100644 index 000000000..0d4fb1638 --- /dev/null +++ b/.github/workflows/test-llvm23.yml @@ -0,0 +1,276 @@ +name: Test LLVM 23 (Fork-based) + +on: + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + +jobs: + step1-configure-linux: + if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' + name: 'Step 1: Configure LLVM 23 (${{ matrix.variant }})' + runs-on: + - self-hosted + - Linux + - X64 + strategy: + matrix: + variant: [translator, native] + fail-fast: true + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + fetch-depth: 0 + submodules: 'recursive' + - name: Configure LLVM 23 (${{ matrix.variant }}) + run: | + BUILD_DIR="$HOME/llvm-builds/23-${{ matrix.variant }}" + rm -rf "$BUILD_DIR" + mkdir -p "$BUILD_DIR" + cd "$BUILD_DIR" + rm -rf scripts llvm-patches + cp -r ${{ github.workspace }}/scripts . + cp -r ${{ github.workspace }}/llvm-patches . + chmod +x scripts/configure_llvm.sh + ./scripts/configure_llvm.sh --version 23 \ + --install-dir $HOME/install/llvm/23.0-${{ matrix.variant }} \ + --variant ${{ matrix.variant }} --configure-only + + step2-build-test-linux: + needs: step1-configure-linux + if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' + name: Build LLVM 23 (${{ matrix.variant }}) and test chipStar + runs-on: + - self-hosted + - Linux + - X64 + env: + IGC_EnableDPEmulation: 1 + OverrideDefaultFP64Settings: 1 + CHIP_LOGLEVEL: err + CHIP_MODULE_CACHE_DIR: "" + POCL_KERNEL_CACHE: 0 + CHIP_L0_EVENT_TIMEOUT: 1790 + strategy: + matrix: + variant: [translator, native] + fail-fast: false + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + fetch-depth: 0 + submodules: 'recursive' + - name: Build LLVM 23 (${{ matrix.variant }}) + id: build_llvm + continue-on-error: true + run: | + BUILD_DIR="$HOME/llvm-builds/23-${{ matrix.variant }}/llvm-project/llvm/build_23" + if [ ! -d "$BUILD_DIR" ]; then + echo "Error: Build directory $BUILD_DIR does not exist. Step 1 may have failed." + exit 1 + fi + cd "$BUILD_DIR" + make -j$(nproc) + timeout-minutes: 300 + - name: Build chipStar with LLVM 23 (${{ matrix.variant }}) + id: build_chipstar + if: steps.build_llvm.outcome == 'success' + run: | + # Source modules for device drivers + if [ -f "$HOME/.local/init/bash" ]; then + export MODULESHOME=$HOME/.local + source "$MODULESHOME/init/bash" + 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 + module load oneapi/2025.0.4 opencl/dgpu + + LLVM_BIN="$HOME/llvm-builds/23-${{ matrix.variant }}/llvm-project/llvm/build_23/bin" + test -f "${LLVM_BIN}/clang" || exit 1 + cd ${{ github.workspace }} + rm -rf build-llvm23-${{ matrix.variant }} + mkdir -p build-llvm23-${{ matrix.variant }} + cd build-llvm23-${{ matrix.variant }} + cmake .. -DLLVM_CONFIG_BIN=${LLVM_BIN}/llvm-config -GNinja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCHIP_BUILD_SAMPLES=ON -DCHIP_BUILD_TESTS=ON + ninja all install -j$(nproc) + ninja build_tests install -j$(nproc) + timeout-minutes: 60 + - name: Test chipStar (iGPU OpenCL) + if: always() && steps.build_chipstar.outcome == 'success' + continue-on-error: true + run: | + if [ -f "$HOME/.local/init/bash" ]; then + export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash" + 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 + module load opencl/igpu + cd ${{ github.workspace }}/build-llvm23-${{ matrix.variant }} + ../scripts/check.py ./ igpu opencl + timeout-minutes: 60 + - name: Test chipStar (iGPU Level0) + if: always() && steps.build_chipstar.outcome == 'success' + continue-on-error: true + run: | + if [ -f "$HOME/.local/init/bash" ]; then + export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash" + 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 + module load level-zero/igpu + cd ${{ github.workspace }}/build-llvm23-${{ matrix.variant }} + ../scripts/check.py ./ igpu level0 + timeout-minutes: 60 + - name: Test chipStar (dGPU Level0) + if: always() && steps.build_chipstar.outcome == 'success' + run: | + if [ -f "$HOME/.local/init/bash" ]; then + export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash" + 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 + module load level-zero/dgpu + cd ${{ github.workspace }}/build-llvm23-${{ matrix.variant }} + ../scripts/check.py ./ dgpu level0 + timeout-minutes: 60 + - name: Test chipStar (dGPU OpenCL) + if: always() && steps.build_chipstar.outcome == 'success' + run: | + if [ -f "$HOME/.local/init/bash" ]; then + export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash" + 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 + module load opencl/dgpu + cd ${{ github.workspace }}/build-llvm23-${{ matrix.variant }} + ../scripts/check.py ./ dgpu opencl + timeout-minutes: 60 + - name: Test chipStar (CPU OpenCL) + if: always() && steps.build_chipstar.outcome == 'success' + run: | + if [ -f "$HOME/.local/init/bash" ]; then + export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash" + 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 + module load opencl/cpu + cd ${{ github.workspace }}/build-llvm23-${{ matrix.variant }} + ../scripts/check.py ./ cpu opencl --num-tries=3 + timeout-minutes: 60 + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: test-logs-llvm23-${{ matrix.variant }} + path: | + ${{ github.workspace }}/build-llvm23-${{ matrix.variant }}/checkpy_*.txt + ${{ github.workspace }}/build-llvm23-${{ matrix.variant }}/Testing/Temporary/LastTest.log + + step1-configure-macos: + if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' + name: 'Step 1: Configure LLVM 23 (macOS ${{ matrix.variant }})' + runs-on: [self-hosted, ARM64, MacOS] + strategy: + matrix: + variant: [translator, native] + fail-fast: true + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + fetch-depth: 0 + submodules: 'recursive' + - name: Configure LLVM 23 (${{ matrix.variant }}) + shell: /bin/bash {0} + run: | + export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" + BUILD_DIR="$HOME/llvm-builds/23-${{ matrix.variant }}" + rm -rf "$BUILD_DIR" + mkdir -p "$BUILD_DIR" + cd "$BUILD_DIR" + rm -rf scripts llvm-patches + cp -r ${{ github.workspace }}/scripts . + cp -r ${{ github.workspace }}/llvm-patches . + chmod +x scripts/configure_llvm.sh + ./scripts/configure_llvm.sh --version 23 \ + --install-dir $HOME/install/llvm/23.0-${{ matrix.variant }} \ + --variant ${{ matrix.variant }} --configure-only + + step2-build-test-macos: + needs: step1-configure-macos + if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' + name: Build LLVM 23 (${{ matrix.variant }}) (macOS) and test chipStar + runs-on: [self-hosted, ARM64, MacOS] + env: + CHIP_DEVICE_TYPE: pocl + CHIP_MODULE_CACHE_DIR: "" + strategy: + matrix: + variant: [translator, native] + fail-fast: false + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + fetch-depth: 0 + submodules: 'recursive' + - name: Build LLVM 23 (${{ matrix.variant }}) + id: build_llvm + shell: /bin/bash {0} + continue-on-error: true + run: | + export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" + BUILD_DIR="$HOME/llvm-builds/23-${{ matrix.variant }}/llvm-project/llvm/build_23" + if [ ! -d "$BUILD_DIR" ]; then + echo "Error: Build directory $BUILD_DIR does not exist. Step 1 may have failed." + exit 1 + fi + cd "$BUILD_DIR" + cmake --build . -j$(sysctl -n hw.ncpu) + timeout-minutes: 300 + - name: Test chipStar with LLVM 23 (${{ matrix.variant }}) (PoCL OpenCL) + if: steps.build_llvm.outcome == 'success' + shell: /bin/bash {0} + run: | + source /opt/homebrew/Cellar/modules/5.6.0/init/bash + export MODULEPATH="/Users/paulius/modulefiles:$MODULEPATH" + module load pocl + + LLVM_BIN="$HOME/llvm-builds/23-${{ matrix.variant }}/llvm-project/llvm/build_23/bin" + test -f "${LLVM_BIN}/clang" || exit 1 + + 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/ + export SPIRV_TOOLS_PREFIX=$(brew --prefix spirv-tools) + export CMAKE_PREFIX_PATH="${SPIRV_TOOLS_PREFIX}:${CMAKE_PREFIX_PATH}" + + cd ${{ github.workspace }} + rm -rf build-23-${{ matrix.variant }} + mkdir -p build-23-${{ matrix.variant }} + cd build-23-${{ matrix.variant }} + /opt/homebrew/bin/cmake .. \ + -DLLVM_CONFIG_BIN=${LLVM_BIN}/llvm-config \ + -DOpenCL_LIBRARY=/Users/paulius/install/pocl/lib/libpocl.dylib \ + -GNinja -DCMAKE_BUILD_TYPE=Debug + ninja CHIP + ninja build_tests + ninja + ../scripts/check.py ./ pocl opencl + timeout-minutes: 60 + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: test-logs-macos-llvm23-${{ matrix.variant }} + path: | + build-23-${{ matrix.variant }}/checkpy_*.txt + build-23-${{ matrix.variant }}/Testing/Temporary/LastTest.log diff --git a/CMakeLists.txt b/CMakeLists.txt index 88bb47329..aec77f008 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,10 @@ include(LLVMCheck) include(chip_spv_cmake_macros) enable_testing() +# Exclude ROCm-Device-Libs tests that target amdgcn (not applicable to SPIR-V builds). +file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" + "set(CTEST_CUSTOM_TESTS_IGNORE \"constant_fold_lgamma_r\")\n") + if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "..." FORCE) endif() @@ -236,7 +240,7 @@ set(CONFIG_PACKAGE_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/hip CACHE PATH "cmake co set(CONFIG_LANG_PACKAGE_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/hip-lang CACHE PATH "cmake lang install dir") set(HAVE_CLANG_NEW_OFFLOAD_DRIVER OFF) -if(LLVM_VERSION_MAJOR GREATER_EQUAL 23) +if(LLVM_VERSION_MAJOR GREATER_EQUAL 23 AND NOT APPLE) # LLVM-22: The new offload driver exists on this version but HIPSPV # toolchain doesn't support it. # @@ -246,6 +250,13 @@ if(LLVM_VERSION_MAJOR GREATER_EQUAL 23) # link steps. # # LLVM-23+: the old offload driver may be removed. + # + # macOS (APPLE): the new offload driver crashes clang while building the + # offload compilation jobs. Constructing the host (Darwin) toolchain args + # for the SPIR-V offload kind re-enters Darwin::AddDeploymentTarget, which + # asserts in setTarget() ("Target already initialized!", Darwin.h:453). + # Until that upstream Darwin driver bug is fixed, fall back to the old + # offload driver on macOS (adds --no-offload-new-driver below). set(HAVE_CLANG_NEW_OFFLOAD_DRIVER ON) endif() diff --git a/bitcode/CMakeLists.txt b/bitcode/CMakeLists.txt index 276db6599..0ca51d39a 100644 --- a/bitcode/CMakeLists.txt +++ b/bitcode/CMakeLists.txt @@ -158,9 +158,10 @@ set(RTDEVLIB_SOURCES_v1_2 set(RTDEVLIB_SOURCES_v1_3 ballot_native) -# Set rtdevlib compile triples. With integrated SPIR-V (LLVM 22+), use chipstar -# triples. With external translator, use OFFLOAD_TRIPLE (spirv64). -if(LLVM_VERSION_MAJOR GREATER_EQUAL 22 AND CHIP_LLVM_USE_INTERGRATED_SPIRV) +# Set rtdevlib compile triples. LLVM 23+ and integrated SPIR-V builds know the +# chipstar triples (spirv64v1.X-unknown-chipstar). Otherwise fall back to +# OFFLOAD_TRIPLE (spirv64). +if(LLVM_VERSION_MAJOR GREATER_EQUAL 23 OR CHIP_LLVM_USE_INTERGRATED_SPIRV) set(RTDEVLIB_TRIPLE_v1_2 spirv64v1.2-unknown-chipstar) set(RTDEVLIB_TRIPLE_v1_3 spirv64v1.3-unknown-chipstar) else() 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/samples/CMakeLists.txt b/samples/CMakeLists.txt index e1f16591c..78bde167e 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -150,9 +150,19 @@ include(mkl_and_icpx) # Add samples that depend on Intel's oneAPI compiler - if available. if (SYCL_AVAILABLE) list(APPEND SAMPLES sycl_hip_interop) - if (LevelZero_LIBRARY) + # The hip_sycl_interop[_no_buffers] samples link their executables with + # -fsycl using chipStar's clang++ (not icpx). Starting with LLVM 23 the + # upstream -fsycl driver makes clang-linker-wrapper pull in libLLVMSYCL.so, + # which is only produced by an LLVM build that enables the SYCL project. + # chipStar's LLVM is built with LLVM_ENABLE_PROJECTS="clang;clang-tools-extra" + # (no SYCL), so the library does not exist and the link fails. Only build + # these -fsycl-linked samples on LLVM < 23. + if (LevelZero_LIBRARY AND LLVM_VERSION_MAJOR LESS 23) list(APPEND SAMPLES hip_sycl_interop) list(APPEND SAMPLES hip_sycl_interop_no_buffers) + elseif (LevelZero_LIBRARY) + message(STATUS "LLVM ${LLVM_VERSION_MAJOR}: not building hip_sycl_interop[_no_buffers] " + "(-fsycl link requires libLLVMSYCL.so, not provided by chipStar's LLVM build)") endif() else() diff --git a/scripts/configure_llvm.sh b/scripts/configure_llvm.sh index 4e8887e35..67acc0a23 100755 --- a/scripts/configure_llvm.sh +++ b/scripts/configure_llvm.sh @@ -78,7 +78,7 @@ 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 17, 18, 19, 20, 21 or 22" + echo "--version: LLVM version 17, 18, 19, 20, 21, 22 or 23" echo "--install-dir: installation directory" echo "--link-type: static or dynamic (default: dynamic)" echo "--variant: translator (host only) or native (host;SPIRV) (default: translator)" @@ -96,8 +96,9 @@ fi # validate version argument if [ "$VERSION" != "17" ] && [ "$VERSION" != "18" ] && [ "$VERSION" != "19" ] \ - && [ "$VERSION" != "20" ] && [ "$VERSION" != "21" ] && [ "$VERSION" != "22" ]; then - echo "Invalid version. Must be 17, 18, 19, 20, 21 or 22." + && [ "$VERSION" != "20" ] && [ "$VERSION" != "21" ] && [ "$VERSION" != "22" ] \ + && [ "$VERSION" != "23" ]; then + echo "Invalid version. Must be 17, 18, 19, 20, 21, 22 or 23." exit 1 fi @@ -127,9 +128,22 @@ fi NPROC=$(nproc 2>/dev/null || sysctl -n hw.ncpu) -# Map version to upstream LLVM branch and SPIRV-Translator branch -LLVM_BRANCH="release/${VERSION}.x" -TRANSLATOR_BRANCH="llvm_release_${VERSION}0" +# Set up repos and branches based on version +if [ "$VERSION" == "23" ]; then + # LLVM 23: use CHIP-SPV forks with patches pre-applied + LLVM_REPO="https://github.com/CHIP-SPV/llvm-project.git" + LLVM_BRANCH="chipstar-native-spirv" + TRANSLATOR_REPO="https://github.com/CHIP-SPV/SPIRV-LLVM-Translator.git" + TRANSLATOR_BRANCH="chipStar-llvm-23" + SKIP_PATCHES=true +else + # LLVM 17-22: upstream + patches + LLVM_REPO="https://github.com/llvm/llvm-project.git" + LLVM_BRANCH="release/${VERSION}.x" + TRANSLATOR_REPO="https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git" + TRANSLATOR_BRANCH="llvm_release_${VERSION}0" + SKIP_PATCHES=false +fi export LLVM_DIR=`pwd`/llvm-project/llvm @@ -137,29 +151,29 @@ export LLVM_DIR=`pwd`/llvm-project/llvm if [ "$EMIT_ONLY" != "on" ]; then # check if llvm-project exists, if not clone it if [ ! -d llvm-project ]; then - echo "Cloning LLVM from upstream..." - retry git clone https://github.com/llvm/llvm-project.git + echo "Cloning LLVM from ${LLVM_REPO}..." + retry git clone ${LLVM_REPO} cd llvm-project git checkout ${LLVM_BRANCH} - - echo "Cloning SPIRV-LLVM-Translator from upstream..." + + echo "Cloning SPIRV-LLVM-Translator from ${TRANSLATOR_REPO}..." cd llvm/projects - retry git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git + retry git clone ${TRANSLATOR_REPO} cd SPIRV-LLVM-Translator git checkout ${TRANSLATOR_BRANCH} else # Warn the user. - echo "llvm-project directory already exists. Checking out upstream branches..." + echo "llvm-project directory already exists. Checking out branches..." cd llvm-project git fetch origin git reset --hard git clean -fd git checkout ${LLVM_BRANCH} - + if [ ! -d llvm/projects/SPIRV-LLVM-Translator ]; then - echo "Cloning SPIRV-LLVM-Translator from upstream..." + echo "Cloning SPIRV-LLVM-Translator from ${TRANSLATOR_REPO}..." cd llvm/projects - retry git clone https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git + retry git clone ${TRANSLATOR_REPO} cd SPIRV-LLVM-Translator else cd llvm/projects/SPIRV-LLVM-Translator @@ -170,123 +184,127 @@ if [ "$EMIT_ONLY" != "on" ]; then git checkout ${TRANSLATOR_BRANCH} fi cd ${initial_pwd}/llvm-project - - # Apply chipStar-specific patches - echo "Applying chipStar patches..." - - # Apply LLVM patches - LLVM_PATCH_DIR="${THIS_SCRIPT_DIR}/../llvm-patches/llvm" - if [ -d "$LLVM_PATCH_DIR" ]; then - echo "Applying LLVM patches..." - for patch in "$LLVM_PATCH_DIR"/*.patch; do - if [ -f "$patch" ]; then - patch_name=$(basename $patch) - - # Skip SPIR-V data layout patches for LLVM 17-19 (not needed) and 22+ (fixed at chipStar level) - # Note: only match 0002-fix-SPIR-V-data-layout, NOT 0005-fix-archive-data-layout - if [[ "$patch_name" == "0002-fix-SPIR-V-data-layout"* ]] && ([ "$VERSION" -lt 20 ] || [ "$VERSION" -ge 22 ]); then - echo " Skipping $patch_name (not needed for LLVM ${VERSION})" - continue - fi - # Use LLVM 21-specific data layout patch for version 21, skip LLVM 20 version - if [[ "$patch_name" == "0002-fix-SPIR-V-data-layout.patch" ]] && [ "$VERSION" -eq 21 ]; then - echo " Skipping $patch_name (using LLVM 21-specific patch instead)" - continue - fi - if [[ "$patch_name" == *"data-layout-llvm21.patch" ]] && [ "$VERSION" -ne 21 ]; then - echo " Skipping $patch_name (only needed for LLVM 21)" - continue - fi + if [ "$SKIP_PATCHES" = true ]; then + echo "Skipping patch application (patches pre-applied in fork)" + else + # Apply chipStar-specific patches + echo "Applying chipStar patches..." - # Skip Unbundle SDL patch for LLVM 22+ (already upstream) - if [[ "$patch_name" == *"Unbundle-SDL"* ]] && [ "$VERSION" -ge 22 ]; then - echo " Skipping $patch_name (already upstream in LLVM ${VERSION})" - continue - fi + # Apply LLVM patches + LLVM_PATCH_DIR="${THIS_SCRIPT_DIR}/../llvm-patches/llvm" + if [ -d "$LLVM_PATCH_DIR" ]; then + echo "Applying LLVM patches..." + for patch in "$LLVM_PATCH_DIR"/*.patch; do + if [ -f "$patch" ]; then + patch_name=$(basename $patch) - # For LLVM 22+: skip individual 0001/0004 patches (line shifts due to upstream 0003), - # use combined llvm22 patch instead - if [[ "$patch_name" == "0001-Allow-up-to-v1.2-SPIR-V-features.patch" ]] && [ "$VERSION" -ge 22 ]; then - echo " Skipping $patch_name (using LLVM 22-specific combined patch instead)" - continue - fi - if [[ "$patch_name" == "0004-only-necessary-exts.patch" ]] && [ "$VERSION" -ge 22 ]; then - echo " Skipping $patch_name (using LLVM 22-specific combined patch instead)" - continue - fi + # Skip SPIR-V data layout patches for LLVM 17-19 (not needed) and 22+ (fixed at chipStar level) + # Note: only match 0002-fix-SPIR-V-data-layout, NOT 0005-fix-archive-data-layout + if [[ "$patch_name" == "0002-fix-SPIR-V-data-layout"* ]] && ([ "$VERSION" -lt 20 ] || [ "$VERSION" -ge 22 ]); then + echo " Skipping $patch_name (not needed for LLVM ${VERSION})" + continue + fi - # Skip old macOS patch for LLVM 22+ (replaced by llvm22-specific patch) - if [[ "$patch_name" == "0006-fix-macos-hip-spirv.patch" ]] && [ "$VERSION" -ge 22 ]; then - echo " Skipping $patch_name (using LLVM 22-specific macOS patch instead)" - continue - fi + # Use LLVM 21-specific data layout patch for version 21, skip LLVM 20 version + if [[ "$patch_name" == "0002-fix-SPIR-V-data-layout.patch" ]] && [ "$VERSION" -eq 21 ]; then + echo " Skipping $patch_name (using LLVM 21-specific patch instead)" + continue + fi + if [[ "$patch_name" == *"data-layout-llvm21.patch" ]] && [ "$VERSION" -ne 21 ]; then + echo " Skipping $patch_name (only needed for LLVM 21)" + continue + fi - # Skip LLVM 22-specific patches when building older versions - if [[ "$patch_name" == *"-llvm22.patch" ]] && [ "$VERSION" -lt 22 ]; then - echo " Skipping $patch_name (only for LLVM 22+)" - continue - fi - - echo " Applying $patch_name..." - git apply "$patch" || { - echo "Error: Failed to apply $patch_name" - exit 1 - } - fi - done - else - #if the patch directory doesn't exist, good chance somehow this script is being run outside of its intended project - echo "Error: LLVM patch directory not found at $LLVM_PATCH_DIR" - exit 1 - fi - - # Apply SPIRV-Translator patches - cd ${initial_pwd}/llvm-project/llvm/projects/SPIRV-LLVM-Translator - TRANSLATOR_PATCH_DIR="${THIS_SCRIPT_DIR}/../llvm-patches/spirv-translator" - if [ -d "$TRANSLATOR_PATCH_DIR" ]; then - echo "Applying SPIRV-Translator patches..." - for patch in "$TRANSLATOR_PATCH_DIR"/*.patch; do - if [ -f "$patch" ]; then - patch_name=$(basename $patch) - - # Skip fp_fast_mode patch for LLVM 17/18/19 (test file structure changed, opaque pointers are default) - if [[ "$patch_name" == *"fp_fast_mode"* ]] && ([ "$VERSION" -eq 17 ] || [ "$VERSION" -eq 18 ] || [ "$VERSION" -eq 19 ]); then - echo " Skipping $patch_name (not needed for LLVM ${VERSION})" - continue - fi - - # Use version-specific patch for LLVM 17/18, skip the original for LLVM 17/18 - if [[ "$patch_name" == "0002-Pretend-the-SPIR-ver-needed-by-shuffles-is-1.2.patch" ]] && ([ "$VERSION" -eq 17 ] || [ "$VERSION" -eq 18 ]); then - echo " Skipping $patch_name (using LLVM 17/18-specific patch instead)" - continue - fi - if [[ "$patch_name" == "0002-Pretend-the-SPIR-ver-needed-by-shuffles-is-1.2-llvm17-18.patch" ]] && [ "$VERSION" -ne 17 ] && [ "$VERSION" -ne 18 ]; then - echo " Skipping $patch_name (only needed for LLVM 17/18)" - continue + # Skip Unbundle SDL patch for LLVM 22+ (already upstream) + if [[ "$patch_name" == *"Unbundle-SDL"* ]] && [ "$VERSION" -ge 22 ]; then + echo " Skipping $patch_name (already upstream in LLVM ${VERSION})" + continue + fi + + # For LLVM 22+: skip individual 0001/0004 patches (line shifts due to upstream 0003), + # use combined llvm22 patch instead + if [[ "$patch_name" == "0001-Allow-up-to-v1.2-SPIR-V-features.patch" ]] && [ "$VERSION" -ge 22 ]; then + echo " Skipping $patch_name (using LLVM 22-specific combined patch instead)" + continue + fi + if [[ "$patch_name" == "0004-only-necessary-exts.patch" ]] && [ "$VERSION" -ge 22 ]; then + echo " Skipping $patch_name (using LLVM 22-specific combined patch instead)" + continue + fi + + # Skip old macOS patch for LLVM 22+ (replaced by llvm22-specific patch) + if [[ "$patch_name" == "0006-fix-macos-hip-spirv.patch" ]] && [ "$VERSION" -ge 22 ]; then + echo " Skipping $patch_name (using LLVM 22-specific macOS patch instead)" + continue + fi + + # Skip LLVM 22-specific patches when building older versions + if [[ "$patch_name" == *"-llvm22.patch" ]] && [ "$VERSION" -lt 22 ]; then + echo " Skipping $patch_name (only for LLVM 22+)" + continue + fi + + echo " Applying $patch_name..." + git apply "$patch" || { + echo "Error: Failed to apply $patch_name" + exit 1 + } fi - - # Skip LoopMerge and blockMerge patches for LLVM 22+ (already upstream in translator) - if [[ "$patch_name" == *"LoopMerge"* || "$patch_name" == *"blockMerge"* ]] && [ "$VERSION" -ge 22 ]; then - echo " Skipping $patch_name (already upstream in LLVM ${VERSION})" - continue + done + else + #if the patch directory doesn't exist, good chance somehow this script is being run outside of its intended project + echo "Error: LLVM patch directory not found at $LLVM_PATCH_DIR" + exit 1 + fi + + # Apply SPIRV-Translator patches + cd ${initial_pwd}/llvm-project/llvm/projects/SPIRV-LLVM-Translator + TRANSLATOR_PATCH_DIR="${THIS_SCRIPT_DIR}/../llvm-patches/spirv-translator" + if [ -d "$TRANSLATOR_PATCH_DIR" ]; then + echo "Applying SPIRV-Translator patches..." + for patch in "$TRANSLATOR_PATCH_DIR"/*.patch; do + if [ -f "$patch" ]; then + patch_name=$(basename $patch) + + # Skip fp_fast_mode patch for LLVM 17/18/19 (test file structure changed, opaque pointers are default) + if [[ "$patch_name" == *"fp_fast_mode"* ]] && ([ "$VERSION" -eq 17 ] || [ "$VERSION" -eq 18 ] || [ "$VERSION" -eq 19 ]); then + echo " Skipping $patch_name (not needed for LLVM ${VERSION})" + continue + fi + + # Use version-specific patch for LLVM 17/18, skip the original for LLVM 17/18 + if [[ "$patch_name" == "0002-Pretend-the-SPIR-ver-needed-by-shuffles-is-1.2.patch" ]] && ([ "$VERSION" -eq 17 ] || [ "$VERSION" -eq 18 ]); then + echo " Skipping $patch_name (using LLVM 17/18-specific patch instead)" + continue + fi + if [[ "$patch_name" == "0002-Pretend-the-SPIR-ver-needed-by-shuffles-is-1.2-llvm17-18.patch" ]] && [ "$VERSION" -ne 17 ] && [ "$VERSION" -ne 18 ]; then + echo " Skipping $patch_name (only needed for LLVM 17/18)" + continue + fi + + # Skip LoopMerge and blockMerge patches for LLVM 22+ (already upstream in translator) + if [[ "$patch_name" == *"LoopMerge"* || "$patch_name" == *"blockMerge"* ]] && [ "$VERSION" -ge 22 ]; then + echo " Skipping $patch_name (already upstream in LLVM ${VERSION})" + continue + fi + + echo " Applying $patch_name..." + git apply "$patch" || { + echo "Error: Failed to apply $patch_name" + exit 1 + } fi + done + else + #if the patch directory doesn't exist, good chance somehow this script is being run outside of its intended project + echo "Error: SPIRV-Translator patch directory not found at $TRANSLATOR_PATCH_DIR" + exit 1 + fi - echo " Applying $patch_name..." - git apply "$patch" || { - echo "Error: Failed to apply $patch_name" - exit 1 - } - fi - done - else - #if the patch directory doesn't exist, good chance somehow this script is being run outside of its intended project - echo "Error: SPIRV-Translator patch directory not found at $TRANSLATOR_PATCH_DIR" - exit 1 + echo "All patches applied successfully" fi - - echo "All patches applied successfully" - + cd ${LLVM_DIR} rm -rf build_$VERSION @@ -364,7 +382,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=\"clang;clang-tools-extra\"" "-DLLVM_TARGETS_TO_BUILD=\"${LLVM_TARGETS}\"" "-DLLVM_ENABLE_ASSERTIONS=On" "-DLLVM_INCLUDE_TESTS=OFF" diff --git a/src/CHIPDriver.cc b/src/CHIPDriver.cc index a1a9b057b..c64b55875 100644 --- a/src/CHIPDriver.cc +++ b/src/CHIPDriver.cc @@ -193,12 +193,13 @@ void CHIPUninitializeCallOnce() { if (LegacyQueue) { LegacyQueue->finish(); } - if (Dev->isPerThreadStreamUsed()) { - auto PerThreadQueue = Dev->getPerThreadDefaultQueue(); - if (PerThreadQueue) { - PerThreadQueue->finish(); - } - } + // Note: We intentionally do NOT sync the per-thread default queue + // here. PerThreadDefaultQueue is a thread_local unique_ptr whose + // destructor may have already run by the time this atexit handler + // executes (TLS destruction order vs atexit order is + // implementation-defined). Accessing destroyed TLS is UB and + // causes a SEGFAULT with some compilers (e.g. clang 23). The + // per-thread queue will be cleaned up by its own TLS destructor. } // call deallocateDeviceVariables on all devices. diff --git a/src/spirv_hiprtc.cc b/src/spirv_hiprtc.cc index 7dea5942f..b13e75595 100644 --- a/src/spirv_hiprtc.cc +++ b/src/spirv_hiprtc.cc @@ -266,8 +266,8 @@ static void getLoweredNameExpressions(chipstar::Program &Program, // Compiles sources stored in 'chipstar::Program'. Uses 'WorkingDirectory' for // temporary compilation I/O. -static hiprtcResult compile(chipstar::Program &Program, int NumRawOptions, - const char* const* RawOptions, +static hiprtcResult compile(chipstar::Program &Program, + const CompileOptions &ProcessedOptions, fs::path WorkingDirectory) { // Create source and header files. auto SourceFile = WorkingDirectory / "program.hip"; @@ -275,10 +275,6 @@ static hiprtcResult compile(chipstar::Program &Program, int NumRawOptions, auto LoweredNamesFile = WorkingDirectory / "lowerednames.txt"; auto CompileLogFile = WorkingDirectory / "compile.log"; - CompileOptions ProcessedOptions; - if (processOptions(Program, NumRawOptions, RawOptions, ProcessedOptions)) - return HIPRTC_ERROR_INVALID_INPUT; - if (!createHeaderFiles(Program, WorkingDirectory)) { logError("hiprtc: could not create user header files."); return HIPRTC_ERROR_COMPILATION; @@ -618,6 +614,14 @@ hiprtcResult hiprtcCompileProgram(hiprtcProgram Prog, int NumOptions, try { auto &Program = *(chipstar::Program *)Prog; + // Process options up front so option diagnostics (e.g. "ignored option" + // warnings) are recorded in the program log regardless of whether the + // result is served from the cache below. Doing this only on the + // compile path would make the log depend on cache state. + CompileOptions ProcessedOptions; + if (processOptions(Program, NumOptions, Options, ProcessedOptions)) + return HIPRTC_ERROR_INVALID_INPUT; + // Check HIPRTC output cache before invoking clang. auto cacheKey = computeHiprtcCacheKey(Program, NumOptions, Options); auto t0 = std::chrono::steady_clock::now(); @@ -637,7 +641,7 @@ hiprtcResult hiprtcCompileProgram(hiprtcProgram Prog, int NumOptions, } logDebug("hiprtc: Temp directory: '{}'", TmpDir->string()); - hiprtcResult Result = compile(Program, NumOptions, Options, *TmpDir); + hiprtcResult Result = compile(Program, ProcessedOptions, *TmpDir); // HIPCC_VERIFY: run chip-kernel-verify on the produced ELF. Mode is // parsed centrally in EnvVars (CHIPDriver.hh); see HipccVerifyMode. diff --git a/tests/compiler/promoteInt/CMakeLists.txt b/tests/compiler/promoteInt/CMakeLists.txt index ec4192980..3c865e4da 100644 --- a/tests/compiler/promoteInt/CMakeLists.txt +++ b/tests/compiler/promoteInt/CMakeLists.txt @@ -62,6 +62,7 @@ foreach(IR_FILE ${TEST_IR_FILES}) LLVM_OPT=${LLVM_TOOLS_BINARY_DIR}/opt LLVM_SPIRV=${LLVM_TOOLS_BINARY_DIR}/llvm-spirv LLVM_DIS=${LLVM_TOOLS_BINARY_DIR}/llvm-dis + CLANG=${LLVM_TOOLS_BINARY_DIR}/clang HIP_SPV_PASSES_LIB=${CMAKE_BINARY_DIR}/lib/libLLVMHipSpvPasses.so ${CMAKE_CURRENT_BINARY_DIR}/run_promote_int_pass.bash ${CMAKE_CURRENT_BINARY_DIR}/${FILENAME} ) diff --git a/tests/compiler/promoteInt/run_promote_int_pass.bash b/tests/compiler/promoteInt/run_promote_int_pass.bash index 166cc1cbd..d49bcbbc0 100755 --- a/tests/compiler/promoteInt/run_promote_int_pass.bash +++ b/tests/compiler/promoteInt/run_promote_int_pass.bash @@ -29,7 +29,17 @@ if [ "${NON_STD_INT_COUNT}" -gt 0 ]; then exit 1 fi -# Convert to SPIR-V to check validity -${LLVM_SPIRV} "${OUTPUT_BC}" ${SPIRV_OPTS} -o "${OUTPUT_SPV}" || exit 1 +# Convert to SPIR-V to check validity. +# Use llvm-spirv if available, otherwise fall back to the in-tree SPIR-V backend. +if [ -n "${LLVM_SPIRV}" ] && [ -x "${LLVM_SPIRV}" ]; then + ${LLVM_SPIRV} "${OUTPUT_BC}" ${SPIRV_OPTS} -o "${OUTPUT_SPV}" || exit 1 +elif [ -n "${CLANG}" ]; then + ${CLANG} --no-default-config -c --target=spirv64v1.2-unknown-chipstar \ + -mllvm -spirv-ext=+SPV_INTEL_function_pointers,+SPV_INTEL_subgroups,+SPV_EXT_relaxed_printf_string_address_space,+SPV_KHR_bit_instructions,+SPV_EXT_shader_atomic_float_add \ + -x ir "${OUTPUT_BC}" -o "${OUTPUT_SPV}" || exit 1 +else + echo "ERROR: Neither llvm-spirv nor clang available for SPIR-V validation" + exit 1 +fi -exit 0 \ No newline at end of file +exit 0