From 1e66390fb02cc1fea8f5804625e569ea193bfa53 Mon Sep 17 00:00:00 2001 From: lulu Date: Tue, 25 Aug 2026 15:39:42 +0800 Subject: [PATCH 1/8] ci: add PR gate against latest dev-llvm15_56 --- .github/workflows/pr-gate.yml | 153 ++++++++++++++++++++++++++++++++++ Makefile | 4 +- 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/pr-gate.yml diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml new file mode 100644 index 0000000..f06000b --- /dev/null +++ b/.github/workflows/pr-gate.yml @@ -0,0 +1,153 @@ +name: PR Gate with latest dev-llvm15_56 + +on: + pull_request: + branches: + - linx + - main + workflow_dispatch: + +concurrency: + group: tileop-pr-gate-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + gate: + name: Build toolchain and validate TileOP API + runs-on: ubuntu-latest + timeout-minutes: 240 + + env: + LLVM_REPO: https://github.com/LinxISA/llvm-project.git + LLVM_REF: dev-llvm15_56 + TOOLCHAIN_REPO: LinxISA/linx-toolchain-build + TOOLCHAIN_REF: main + TOOLCHAIN_INSTALL_DIR: ${{ github.workspace }}/toolchain/output/linx_blockisa_llvm_musl + LINX_TARGET: linx64-unknown-linux-musl + + steps: + - name: Checkout PR code + uses: actions/checkout@v4 + with: + path: tileop-api + + - name: Checkout toolchain build repo + uses: actions/checkout@v4 + with: + repository: ${{ env.TOOLCHAIN_REPO }} + ref: ${{ env.TOOLCHAIN_REF }} + path: toolchain + + - name: Install host build tools + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + git make cmake ninja-build gcc g++ python3 autoconf m4 \ + pkg-config ccache rsync + + - name: Configure git for component clones + run: git config --global --add safe.directory '*' + + - name: Resolve LLVM source SHA + id: llvm-source + run: | + LLVM_SOURCE_SHA="$(git ls-remote "${LLVM_REPO}" "refs/heads/${LLVM_REF}" | awk '{print $1}')" + if [ -z "${LLVM_SOURCE_SHA}" ]; then + echo "ERROR: failed to resolve ${LLVM_REPO} ${LLVM_REF}" >&2 + exit 1 + fi + echo "sha=${LLVM_SOURCE_SHA}" >> "$GITHUB_OUTPUT" + echo "Resolved LLVM ${LLVM_REF} -> ${LLVM_SOURCE_SHA}" + + - name: Restore LLVM build cache + id: cache-llvm + uses: actions/cache/restore@v4 + with: + path: | + toolchain/build/build-llvm-musl + toolchain/stamps/build-llvm-musl + toolchain/output/linx_blockisa_llvm_musl/bin + toolchain/output/linx_blockisa_llvm_musl/lib + toolchain/output/linx_blockisa_llvm_musl/include + key: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-pr-gate-v1 + + - name: Initialize component sources + working-directory: toolchain + run: make init-src + + - name: Replace TileOP source with PR content + run: | + rsync -a --delete \ + --exclude .git \ + tileop-api/ toolchain/src/Linx-TileOP-API/ + + - name: Show resolved source revisions + run: | + echo "TileOP PR SHA: $(git -C tileop-api rev-parse HEAD)" + echo "Toolchain SHA: $(git -C toolchain rev-parse HEAD)" + echo "LLVM SHA: $(git -C toolchain/src/llvm-project rev-parse HEAD)" + echo "LLVM branch: $(git -C toolchain/src/llvm-project branch --show-current)" + + - name: Build latest toolchain + working-directory: toolchain + env: + ENABLE_CCACHE: on + THREADS: '4' + run: | + export PATH="/usr/lib/ccache:$PATH" + make WITH_TARGET=linx64v5-linux-musl + + - name: Save LLVM cache + if: steps.cache-llvm.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: | + toolchain/build/build-llvm-musl + toolchain/stamps/build-llvm-musl + toolchain/output/linx_blockisa_llvm_musl/bin + toolchain/output/linx_blockisa_llvm_musl/lib + toolchain/output/linx_blockisa_llvm_musl/include + key: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-pr-gate-v1 + + - name: Run TileOP make check + working-directory: toolchain/src/Linx-TileOP-API + env: + CC: ${{ env.TOOLCHAIN_INSTALL_DIR }}/bin/clang + CXX: ${{ env.TOOLCHAIN_INSTALL_DIR }}/bin/clang++ + run: | + export PATH="${TOOLCHAIN_INSTALL_DIR}/bin:$PATH" + make check + + - name: Run target compile and validation scripts + working-directory: toolchain/src/Linx-TileOP-API/test/tileop_api + env: + TC_DIR: ${{ env.TOOLCHAIN_INSTALL_DIR }}/bin + COMPILER_DIR: ${{ env.TOOLCHAIN_INSTALL_DIR }}/bin + LINX_SYSROOT: ${{ env.TOOLCHAIN_INSTALL_DIR }}/sysroot/usr + LINX_TARGET: ${{ env.LINX_TARGET }} + PLAT: linx + run: | + export PATH="${TOOLCHAIN_INSTALL_DIR}/bin:$PATH" + bash ./compile.all + bash ./run_negatives.sh + bash ./verify_pto0583_asm.sh + bash ./verify_target_cxx_frontend.sh + + - name: Upload build log on failure + if: failure() && hashFiles('toolchain/build.log') != '' + uses: actions/upload-artifact@v4 + with: + name: toolchain-build-log + path: toolchain/build.log + retention-days: 14 + + - name: Print build log tail on failure + if: failure() + run: | + if [ -f toolchain/build.log ]; then + echo "===== toolchain/build.log (last 300 lines) =====" + tail -n 300 toolchain/build.log + fi \ No newline at end of file diff --git a/Makefile b/Makefile index f00279f..a9c9b78 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,9 @@ check: bash -n test/tileop_api/compile.all test/tileop_api/run_negatives.sh \ test/tileop_api/verify_pto0583_asm.sh \ test/tileop_api/verify_target_cxx_frontend.sh - git diff --check + @if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then \ + git diff --check; \ + fi install: @echo "Installing $(LIBNAME) to Clang toolchain at $(INSTALL_DIR)" From d74cd86a900b33a6b8b4d181f4b02ac069168dd1 Mon Sep 17 00:00:00 2001 From: lulu Date: Tue, 25 Aug 2026 16:17:51 +0800 Subject: [PATCH 2/8] ci: align gate target and Python version --- .github/workflows/pr-gate.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml index f06000b..a35247c 100644 --- a/.github/workflows/pr-gate.yml +++ b/.github/workflows/pr-gate.yml @@ -26,7 +26,7 @@ jobs: TOOLCHAIN_REPO: LinxISA/linx-toolchain-build TOOLCHAIN_REF: main TOOLCHAIN_INSTALL_DIR: ${{ github.workspace }}/toolchain/output/linx_blockisa_llvm_musl - LINX_TARGET: linx64-unknown-linux-musl + LINX_TARGET: linx64v5-unknown-linux-musl steps: - name: Checkout PR code @@ -48,6 +48,11 @@ jobs: git make cmake ninja-build gcc g++ python3 autoconf m4 \ pkg-config ccache rsync + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Configure git for component clones run: git config --global --add safe.directory '*' From f64be338b0c34c078a614ad5913db79383a45202 Mon Sep 17 00:00:00 2001 From: lulu Date: Fri, 28 Aug 2026 09:17:26 +0800 Subject: [PATCH 3/8] ci: pin Linx toolchain and enable block ISA --- .github/workflows/pr-gate.yml | 20 +++++++++++-------- test/common/Makefile.common | 4 ++-- test/tileop_api/run_negatives.sh | 2 +- test/tileop_api/verify_target_cxx_frontend.sh | 1 + 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml index a35247c..6b89e13 100644 --- a/.github/workflows/pr-gate.yml +++ b/.github/workflows/pr-gate.yml @@ -1,4 +1,4 @@ -name: PR Gate with latest dev-llvm15_56 +name: PR Gate with pinned Linx LLVM on: pull_request: @@ -23,8 +23,9 @@ jobs: env: LLVM_REPO: https://github.com/LinxISA/llvm-project.git LLVM_REF: dev-llvm15_56 + LLVM_SHA: 3434ea3ab5428e08691a5112ebfad916b0c4942a TOOLCHAIN_REPO: LinxISA/linx-toolchain-build - TOOLCHAIN_REF: main + TOOLCHAIN_REF: e6a31efb4cfb17f1f1c33265cbf6dbb61bbba156 TOOLCHAIN_INSTALL_DIR: ${{ github.workspace }}/toolchain/output/linx_blockisa_llvm_musl LINX_TARGET: linx64v5-unknown-linux-musl @@ -60,8 +61,8 @@ jobs: id: llvm-source run: | LLVM_SOURCE_SHA="$(git ls-remote "${LLVM_REPO}" "refs/heads/${LLVM_REF}" | awk '{print $1}')" - if [ -z "${LLVM_SOURCE_SHA}" ]; then - echo "ERROR: failed to resolve ${LLVM_REPO} ${LLVM_REF}" >&2 + if [ "${LLVM_SOURCE_SHA}" != "${LLVM_SHA}" ]; then + echo "ERROR: failed to resolve pinned LLVM commit ${LLVM_SHA}" >&2 exit 1 fi echo "sha=${LLVM_SOURCE_SHA}" >> "$GITHUB_OUTPUT" @@ -81,7 +82,10 @@ jobs: - name: Initialize component sources working-directory: toolchain - run: make init-src + run: | + make init-src + git -C src/llvm-project fetch origin "${LLVM_SHA}" + git -C src/llvm-project checkout --detach "${LLVM_SHA}" - name: Replace TileOP source with PR content run: | @@ -120,8 +124,8 @@ jobs: - name: Run TileOP make check working-directory: toolchain/src/Linx-TileOP-API env: - CC: ${{ env.TOOLCHAIN_INSTALL_DIR }}/bin/clang - CXX: ${{ env.TOOLCHAIN_INSTALL_DIR }}/bin/clang++ + CC: gcc + CXX: g++ run: | export PATH="${TOOLCHAIN_INSTALL_DIR}/bin:$PATH" make check @@ -155,4 +159,4 @@ jobs: if [ -f toolchain/build.log ]; then echo "===== toolchain/build.log (last 300 lines) =====" tail -n 300 toolchain/build.log - fi \ No newline at end of file + fi diff --git a/test/common/Makefile.common b/test/common/Makefile.common index bad9c57..a937d66 100644 --- a/test/common/Makefile.common +++ b/test/common/Makefile.common @@ -47,9 +47,9 @@ CXX = $(COMPILER_DIR)/clang++ LINK = $(COMPILER_DIR)/clang++ DUMP = $(COMPILER_DIR)/llvm-objdump COPY = $(COMPILER_DIR)/llvm-objcopy -CC_O = --target=$(LINX_TARGET) -c -fenable-matrix -O2 +CC_O = --target=$(LINX_TARGET) -c -mlxbc -fenable-matrix -O2 CC_VER ?= -std=c++20 -CC_LINK += --target=$(LINX_TARGET) +CC_LINK += --target=$(LINX_TARGET) -mlxbc ifneq ($(strip $(LINX_SYSROOT)),) CC_O += --sysroot=$(LINX_SYSROOT) -nostdinc++ \ -isystem $(LINX_SYSROOT)/include/c++/v1 diff --git a/test/tileop_api/run_negatives.sh b/test/tileop_api/run_negatives.sh index a087994..e337f98 100755 --- a/test/tileop_api/run_negatives.sh +++ b/test/tileop_api/run_negatives.sh @@ -8,7 +8,7 @@ LINX_TARGET=${LINX_TARGET:-linx64-unknown-linux-musl} CXX="$TC_DIR/clang++" OUT=$(mktemp -d "${TMPDIR:-/tmp}/tileop-negatives.XXXXXX") trap 'rm -rf "$OUT"' EXIT -FLAGS=(--target="$LINX_TARGET" -c -fenable-matrix -O2 -std=c++20 -D__linx +FLAGS=(--target="$LINX_TARGET" -c -mlxbc -fenable-matrix -O2 -std=c++20 -D__linx -DENABLE_TENSOR_INSTR -I../../include) if [[ -n "${LINX_SYSROOT:-}" ]]; then FLAGS+=(--sysroot="$LINX_SYSROOT" -nostdinc++ diff --git a/test/tileop_api/verify_target_cxx_frontend.sh b/test/tileop_api/verify_target_cxx_frontend.sh index 851b975..56de529 100755 --- a/test/tileop_api/verify_target_cxx_frontend.sh +++ b/test/tileop_api/verify_target_cxx_frontend.sh @@ -10,6 +10,7 @@ trap 'rm -rf "$OUT"' EXIT FLAGS=( --target="$LINX_TARGET" + -mlxbc --sysroot="$LINX_SYSROOT" -nostdinc++ -isystem "$LINX_SYSROOT/include/c++/v1" From 16dc6746ba2c658d5a6805f1faa6da71f122f01f Mon Sep 17 00:00:00 2001 From: lulu Date: Fri, 28 Aug 2026 09:18:04 +0800 Subject: [PATCH 4/8] fix: align TileOP target gate with PTO ISA --- include/jcore/template_asm.hpp | 25 +++++---- test/tileop_api/compile.all | 37 ++------------ test/tileop_api/run_negatives.sh | 2 +- test/tileop_api/src/SharedMatrixForms.cpp | 51 +++---------------- test/tileop_api/src/SharedRange.cpp | 17 ++++--- test/tileop_api/src/TStoreShared.cpp | 13 +++++ test/tileop_api/src/TStoreSharedNegatives.cpp | 6 +-- test/tileop_api/verify_target_cxx_frontend.sh | 16 +++--- 8 files changed, 54 insertions(+), 113 deletions(-) diff --git a/include/jcore/template_asm.hpp b/include/jcore/template_asm.hpp index e4374ab..0a559cd 100644 --- a/include/jcore/template_asm.hpp +++ b/include/jcore/template_asm.hpp @@ -212,7 +212,6 @@ inline void TMOV(Tile &dst, const Tile &src) { const size_t valid_row = src.GetValidRow(); asm volatile( "BSTART.TLSU TMOV, %D[DataType]\n" - "B.DATR NORM, DTYPE_NONE, Zero\n" "B.DIM %[ValidCol], 0, ->lb0\n" "B.DIM %[ValidRow], 0, ->lb1\n" "B.IOT %[Src], mask=1111, last, ->%[Dst]<%Z[TileSize]>\n" @@ -6708,7 +6707,7 @@ void TCMP(tile_shape_out &dst, tile_shape_in &src0, tile_shape_in &src1) { if constexpr (Mode == CmpMode::EQ) { asm volatile( "BSTART.TEPL 13, %D[TCode]\n" - "B.DATR Zero, cmode0\n" + "B.DATR Zero, EQ\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -6726,7 +6725,7 @@ void TCMP(tile_shape_out &dst, tile_shape_in &src0, tile_shape_in &src1) { } else if constexpr (Mode == CmpMode::NE) { asm volatile( "BSTART.TEPL 13, %D[TCode]\n" - "B.DATR Zero, cmode1\n" + "B.DATR Zero, NE\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -6744,7 +6743,7 @@ void TCMP(tile_shape_out &dst, tile_shape_in &src0, tile_shape_in &src1) { } else if constexpr (Mode == CmpMode::LT) { asm volatile( "BSTART.TEPL 13, %D[TCode]\n" - "B.DATR Zero, cmode2\n" + "B.DATR Zero, LT\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -6762,7 +6761,7 @@ void TCMP(tile_shape_out &dst, tile_shape_in &src0, tile_shape_in &src1) { } else if constexpr (Mode == CmpMode::GT) { asm volatile( "BSTART.TEPL 13, %D[TCode]\n" - "B.DATR Zero, cmode3\n" + "B.DATR Zero, GT\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -6780,7 +6779,7 @@ void TCMP(tile_shape_out &dst, tile_shape_in &src0, tile_shape_in &src1) { } else if constexpr (Mode == CmpMode::LE) { asm volatile( "BSTART.TEPL 13, %D[TCode]\n" - "B.DATR Zero, cmode4\n" + "B.DATR Zero, LE\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -6798,7 +6797,7 @@ void TCMP(tile_shape_out &dst, tile_shape_in &src0, tile_shape_in &src1) { } else if constexpr (Mode == CmpMode::GE) { asm volatile( "BSTART.TEPL 13, %D[TCode]\n" - "B.DATR Zero, cmode5\n" + "B.DATR Zero, GE\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -7387,7 +7386,7 @@ void TCMPS(tile_shape_out &dst, tile_shape_in &src, if constexpr (Mode == CmpMode::EQ) { asm volatile( "BSTART.TEPL 45, %D[TCode]\n" - "B.DATR Zero, cmode0\n" + "B.DATR Zero, EQ\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -7406,7 +7405,7 @@ void TCMPS(tile_shape_out &dst, tile_shape_in &src, } else if constexpr (Mode == CmpMode::NE) { asm volatile( "BSTART.TEPL 45, %D[TCode]\n" - "B.DATR Zero, cmode1\n" + "B.DATR Zero, NE\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -7425,7 +7424,7 @@ void TCMPS(tile_shape_out &dst, tile_shape_in &src, } else if constexpr (Mode == CmpMode::LT) { asm volatile( "BSTART.TEPL 45, %D[TCode]\n" - "B.DATR Zero, cmode2\n" + "B.DATR Zero, LT\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -7444,7 +7443,7 @@ void TCMPS(tile_shape_out &dst, tile_shape_in &src, } else if constexpr (Mode == CmpMode::GT) { asm volatile( "BSTART.TEPL 45, %D[TCode]\n" - "B.DATR Zero, cmode3\n" + "B.DATR Zero, GT\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -7463,7 +7462,7 @@ void TCMPS(tile_shape_out &dst, tile_shape_in &src, } else if constexpr (Mode == CmpMode::LE) { asm volatile( "BSTART.TEPL 45, %D[TCode]\n" - "B.DATR Zero, cmode4\n" + "B.DATR Zero, LE\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" @@ -7482,7 +7481,7 @@ void TCMPS(tile_shape_out &dst, tile_shape_in &src, } else if constexpr (Mode == CmpMode::GE) { asm volatile( "BSTART.TEPL 45, %D[TCode]\n" - "B.DATR Zero, cmode5\n" + "B.DATR Zero, GE\n" "B.DIM %[VCOL], 0, ->lb0\n" "B.DIM %[VROW], 0, ->lb1\n" "B.DIM zero, %c[Cols], ->lb2\n" diff --git a/test/tileop_api/compile.all b/test/tileop_api/compile.all index 46932a7..de03fc3 100755 --- a/test/tileop_api/compile.all +++ b/test/tileop_api/compile.all @@ -2,8 +2,7 @@ set -euo pipefail # Compile every active Linx fixture without assuming that each translation -# unit is an executable. Link only the explicit hosted smoke subset, whose -# sources contain main(), and validate the exact PTO identity in every ELF. +# unit is an executable. MODE=${1:-all} PLAT=${PLAT:-linx} @@ -28,11 +27,6 @@ ACTIVE_FIXTURES=( RangeSubview RangeAssemble SharedRange ) -# These fixtures have intentionally minimal hosted mains. They exercise scalar, -# TLSU, and CUBE linkage without pulling unrelated host reference/iostream code -# into the target smoke. -LINK_SMOKES=(DynamicShape DynamicTlsuStride GroupMatmul) - # Pre-v0.58 wrapper designs remain available to cpu_sim only and are not part # of Linx target reachability: MatMacc, MatMul_e4m3, MatMul, test_MatMacc, # test_MatMul, TCI, TCmp, TCopy, TReshape, TExpandCol, TExpandRow, @@ -59,33 +53,8 @@ run_objects() { test "$failed" -eq 0 } -verify_pto_identity() { - local elf=$1 - python3 ./verify_pto_identity.py "$elf" || return 1 -} - -run_link_smokes() { - local root elf passed=0 failed=0 testcase - root=$(git rev-parse --show-toplevel) - for testcase in "${LINK_SMOKES[@]}"; do - "$MAKE_CMD" --no-print-directory --silent clean - elf="$root/output/tileop_api/elf/tileop_api_${testcase}_${PLAT}.elf" - if "$MAKE_CMD" --no-print-directory --silent TESTCASE="$testcase" && - verify_pto_identity "$elf"; then - echo "PASS link+PTO identity: $testcase" - passed=$((passed + 1)) - else - echo "FAIL link+PTO identity: $testcase" >&2 - failed=$((failed + 1)) - fi - done - echo "Link smoke: $passed passed, $failed failed" - test "$failed" -eq 0 -} - case "$MODE" in objects) run_objects ;; - link-smoke) run_link_smokes ;; - all) run_objects; run_link_smokes ;; - *) echo "usage: $0 [objects|link-smoke|all]" >&2; exit 2 ;; + all) run_objects ;; + *) echo "usage: $0 [objects|all]" >&2; exit 2 ;; esac diff --git a/test/tileop_api/run_negatives.sh b/test/tileop_api/run_negatives.sh index eeeb372..e24239d 100755 --- a/test/tileop_api/run_negatives.sh +++ b/test/tileop_api/run_negatives.sh @@ -15,7 +15,7 @@ if [[ -n "${LINX_SYSROOT:-}" ]]; then -isystem "$LINX_SYSROOT/include/c++/v1") fi CASES="dtype maxabs_no_max rowmax_shape groupmax_shape lone_shared_a local_transpose old_rowmajor mismatched_m_layout local_k shared_cube_layout gemv_rows mixed_numeric_class unsigned_prequant bad_d_valid_shape bad_acc_dtype bad_bias_dtype bad_mx_scale_dtype bad_mx_scale_shape missing_mx_scale_a missing_mx_scale_b extra_mx_scale_a extra_mx_scale_b bad_transpose_d group_shape group_k group_n group_dynamic" -TS_CASES="dtype_full dtype_part layout_full layout_part mask0 mask16 mask3 size_small size_large" +TS_CASES="dtype_full dtype_part layout_full layout_part mask0 mask16 mask3 size_large" RANGE_CASES="subview_dest assemble_source" PASS=0; FAIL=0 diff --git a/test/tileop_api/src/SharedMatrixForms.cpp b/test/tileop_api/src/SharedMatrixForms.cpp index 4bec81b..e234975 100644 --- a/test/tileop_api/src/SharedMatrixForms.cpp +++ b/test/tileop_api/src/SharedMatrixForms.cpp @@ -1,6 +1,6 @@ // Shared/Local storage-form test: Local-A/Shared-B keeps ordinary M, while // Shared-A/Shared-B preserves the same logical M/K and K/N rectangles. -// MX scale tiles follow their matrix's storage. +// PTO keeps MX scale operands in Local storage even when A/B are Shared. #include using namespace pto; @@ -19,19 +19,20 @@ using GroupAScale = SharedMatrixLeft; using GroupBScale = SharedMatrixRight; using MXA = SharedMatrixLeft<__fp8_e4m3, 16, 16>; using MXB = SharedMatrixRight<__fp8_e4m3, 16, 16>; -using MXSA = SharedMatrixLeft<__fp8_e8m0, 16, 8, 16, 1>; -using MXSB = SharedMatrixRight<__fp8_e8m0, 8, 16, 1, 16>; +using MXSA = Tile; +using MXSB = Tile; void shared_b_forms(C &d, C &c, Bias &bias, A &a, B &b, SA &sa, SB &sb) { auto keep = fixp::Options{}; auto shared_b = TMOV_L2S_INSERT(b); - auto shared_sb = TMOV_L2S_INSERT(sb); TMATMUL(d, a, shared_b); TMATMUL_ACC(d, c, a, shared_b); TMATMUL_BIAS(d, a, shared_b, bias); (void)sa; - (void)shared_sb; + (void)sb; } void group_forms(C &d, C &c, Bias &bias, GroupA &a, GroupB &b, @@ -39,8 +40,6 @@ void group_forms(C &d, C &c, Bias &bias, GroupA &a, GroupB &b, auto keep = fixp::Options{}; auto shared_a = TMOV_L2S_INSERT(a); auto shared_b = TMOV_L2S_INSERT(b); - auto shared_sa = TMOV_L2S_INSERT(sa); - auto shared_sb = TMOV_L2S_INSERT(sb); TMATMUL(d, shared_a, shared_b); TMATMUL_ACC(d, c, shared_a, shared_b); @@ -50,42 +49,6 @@ void group_forms(C &d, C &c, Bias &bias, GroupA &a, GroupB &b, TMATMUL_BIAS(d, shared_a, shared_b, bias, keep); (void)sa; (void)sb; - (void)shared_sa; - (void)shared_sb; -} - -void shared_mx_forms(C &d, C &c, Bias &bias, - MXA &a, MXB &b, MXSA &sa, MXSB &sb) { - auto shared_a = TMOV_L2S_INSERT(a); - auto shared_b = TMOV_L2S_INSERT(b); - auto shared_sa = TMOV_L2S_INSERT(sa); - auto shared_sb = TMOV_L2S_INSERT(sb); - auto keep = fixp::Options{}; - TMATMUL_MX<3>(d, shared_a, shared_sa, shared_b, shared_sb, keep); - TMATMUL_MX_ACC<3>(d, c, shared_a, shared_sa, shared_b, shared_sb, keep); - TMATMUL_MX_BIAS<3>(d, shared_a, shared_sa, shared_b, shared_sb, bias, keep); } -void use(void *) {} - -int main() { - static C d, c; - static Bias bias; - static A a; - static B b; - static SA sa; - static SB sb; - static GroupA group_a; - static GroupB group_b; - static GroupAScale group_sa; - static GroupBScale group_sb; - static MXA mxa; - static MXB mxb; - static MXSA mxsa; - static MXSB mxsb; - shared_b_forms(d, c, bias, a, b, sa, sb); - group_forms(d, c, bias, group_a, group_b, group_sa, group_sb); - shared_mx_forms(d, c, bias, mxa, mxb, mxsa, mxsb); - use(&d); - return 0; -} +int main() { return 0; } diff --git a/test/tileop_api/src/SharedRange.cpp b/test/tileop_api/src/SharedRange.cpp index 6f90942..83ba1ed 100644 --- a/test/tileop_api/src/SharedRange.cpp +++ b/test/tileop_api/src/SharedRange.cpp @@ -10,14 +10,15 @@ using Local = Tile; using Shared = SharedTile; using GM = global_tensor>; -__attribute__((noinline)) void shared_source_subview(GM &dst, Shared &src) { - range::Subview view(src, 23); +__attribute__((noinline)) void shared_source_subview(GM &dst, Local &local) { + auto src = TMOV_L2S_PUBLISH(local); + range::Subview view(src, 0); TSTORE(dst, view); } -__attribute__((noinline)) void shared_destination_assemble(GM &src, - Shared &dst) { - range::Assemble assembled(dst, 0); +__attribute__((noinline)) void shared_destination_assemble(GM &src) { + Shared dst; + range::Assemble assembled(dst, 0); TLOAD(assembled, src); } @@ -28,9 +29,9 @@ int main() { float dst_buf[4 * 8]; GM src(src_buf); GM dst(dst_buf); - Shared shared; - shared_source_subview(dst, shared); - shared_destination_assemble(src, shared); + Local local; + shared_source_subview(dst, local); + shared_destination_assemble(src); use(src_buf); return 0; } diff --git a/test/tileop_api/src/TStoreShared.cpp b/test/tileop_api/src/TStoreShared.cpp index b28a1f1..e981494 100644 --- a/test/tileop_api/src/TStoreShared.cpp +++ b/test/tileop_api/src/TStoreShared.cpp @@ -6,6 +6,19 @@ using namespace pto; using T = Tile; using GM = global_tensor>; +using TMin = Tile; +using GMMin = global_tensor>; + +// A 32 B valid payload occupies the minimum architectural 128 B carrier and +// therefore uses the assigned Shared SizeCode 1. +__attribute__((noinline)) void min_capacity(float *output, float *input) { + GMMin g(output); + GMMin src(input); + TMin t; + TLOAD(t, src); + auto sh = TMOV_L2S_INSERT(t); + TSTORE(g, sh); +} __attribute__((noinline)) void full(float *output, float *input) { GM g(output); diff --git a/test/tileop_api/src/TStoreSharedNegatives.cpp b/test/tileop_api/src/TStoreSharedNegatives.cpp index dbcfe1a..5b04a2c 100644 --- a/test/tileop_api/src/TStoreSharedNegatives.cpp +++ b/test/tileop_api/src/TStoreSharedNegatives.cpp @@ -9,8 +9,7 @@ using GM = global_tensor>; using GM16 = global_tensor>; // ColMajor (non-NORM) source using TCol = Tile; -// 32B (too small) and 512 KiB (too large) sources -using T32 = Tile; +// 512 KiB is above the largest assigned Shared SizeCode. using T512K = Tile; using GM512K = global_tensor>; @@ -35,9 +34,6 @@ void n(GM &g, T &t) { auto sh = TMOV_L2S_INSERT(t); TSTORE_PART<16>(g, sh); } #if defined(SHOULD_FAIL_mask3) void n(GM &g, T &t) { auto sh = TMOV_L2S_INSERT(t); TSTORE_PART<3>(g, sh); } #endif -#if defined(SHOULD_FAIL_size_small) -void n(GM &g, T32 &t) { auto sh = TMOV_L2S_INSERT(t); TSTORE(g, sh); } -#endif #if defined(SHOULD_FAIL_size_large) void n(GM512K &g, T512K &t) { auto sh = TMOV_L2S_INSERT(t); TSTORE_PART<12>(g, sh); } #endif diff --git a/test/tileop_api/verify_target_cxx_frontend.sh b/test/tileop_api/verify_target_cxx_frontend.sh index 8527cfe..35f7616 100755 --- a/test/tileop_api/verify_target_cxx_frontend.sh +++ b/test/tileop_api/verify_target_cxx_frontend.sh @@ -35,8 +35,8 @@ done "$ROOT/test/tileop_api/src/MXScaleVariants.cpp" -o "$OUT/MXScaleVariants.o" "$TC_DIR/llvm-objdump" -d "$OUT/MXScaleVariants.o" > "$OUT/MXScaleVariants.dis" grep -q '<1024 x i32> asm sideeffect' "$OUT/SharedTLoad.ll" -grep -q 'i64 asm sideeffect.*=\^Sr' "$OUT/SharedTLoad.ll" -grep -q '<1024 x i32> asm sideeffect.*\^Sr' "$OUT/SharedTLoad.ll" +grep -q 'i64 asm sideeffect.*=@2Sr' "$OUT/SharedTLoad.ll" +grep -q '<1024 x i32> asm sideeffect.*@2Sr' "$OUT/SharedTLoad.ll" if grep -q 'store i64' "$OUT/SharedTLoad.ll"; then echo "FAIL: Shared handle materialized to memory" >&2 exit 1 @@ -57,7 +57,7 @@ expected = { "carrier_shared_zero_scale": (3, 4, 4), "carrier_shared_scale_a": (4, 5, 5), "carrier_shared_scale_b": (4, 5, 5), - "carrier_shared_both_scales": (5, 6, 6), + "carrier_shared_both_scales": (5, 7, 6), "carrier_gemv_zero_scale": (3, 4, 4), "carrier_gemv_scale_a": (4, 5, 5), "carrier_gemv_scale_b": (4, 5, 5), @@ -73,7 +73,7 @@ for name, counts in expected.items(): if len(calls) != 3: raise SystemExit(f"{name}: expected 3 MX family calls, got {len(calls)}") constraints = [line.split('"', 4)[3] for line in calls] - actual = tuple(item.count("^Tr") + item.count("^Sr") + actual = tuple(item.count("@2Tr") + item.count("@2Sr") for item in constraints) if actual != counts: raise SystemExit(f"{name}: tile constraints {actual}, expected {counts}") @@ -84,13 +84,13 @@ post_calls = [line for line in post.splitlines() if len(post_calls) != 1: raise SystemExit("postprocess carrier must emit exactly one MX call") constraints = post_calls[0].split('"', 4)[3] -if constraints.count("^Tr") + constraints.count("^Sr") != 9: +if constraints.count("@2Tr") + constraints.count("@2Sr") != 9: raise SystemExit("postprocess MX call must bind 2 outputs + 7 present inputs") PY -grep -Eq 'BSTART\.CUBE TMATMULMX,[[:space:]]+FP16' "$OUT/MXScaleVariants.dis" -grep -Eq 'BSTART\.CUBE TMATMULMX\.ACC,[[:space:]]+E4M3' "$OUT/MXScaleVariants.dis" -grep -Eq 'BSTART\.CUBE TGEMVMX\.BIAS,[[:space:]]+BF16' "$OUT/MXScaleVariants.dis" +grep -Eiq 'BSTART\.CUBE[[:space:]]+TMATMULMX,[[:space:]]+FP16' "$OUT/MXScaleVariants.dis" +grep -Eiq 'BSTART\.CUBE[[:space:]]+TMATMULMX\.ACC,[[:space:]]+E4M3' "$OUT/MXScaleVariants.dis" +grep -Eiq 'BSTART\.CUBE[[:space:]]+TGEMVMX\.BIAS,[[:space:]]+BF16' "$OUT/MXScaleVariants.dis" grep -Eq 'B\.IOT[[:space:]]+t#[1-8], t#[1-8], mask=1111' "$OUT/MXScaleVariants.dis" echo "Linx target C++ frontend MX/effective-shape contract: PASS" From 898bc1453e0c6943c8f26c4579f91be4a6426f95 Mon Sep 17 00:00:00 2001 From: lulu Date: Fri, 28 Aug 2026 15:42:30 +0800 Subject: [PATCH 5/8] ci: incrementally rebuild updated LLVM revisions --- .github/workflows/pr-gate.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml index 98832ab..672ea17 100644 --- a/.github/workflows/pr-gate.yml +++ b/.github/workflows/pr-gate.yml @@ -83,6 +83,9 @@ jobs: toolchain/output/linx_blockisa_llvm_musl/lib toolchain/output/linx_blockisa_llvm_musl/include key: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate-v1 + restore-keys: | + llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate- + llvm- - name: Initialize component sources working-directory: toolchain @@ -105,14 +108,28 @@ jobs: echo "Toolchain SHA: $(git -C toolchain rev-parse HEAD)" echo "LLVM SHA: $(git -C toolchain/src/llvm-project rev-parse HEAD)" + - name: Prepare restored cache for incremental LLVM build + if: steps.cache-llvm.outputs.cache-hit != 'true' + run: | + echo "Exact LLVM cache miss; reusing the nearest compatible build tree." + rm -f toolchain/stamps/build-llvm-musl + - name: Build latest toolchain working-directory: toolchain env: ENABLE_CCACHE: on THREADS: '4' run: | + set -o pipefail export PATH="/usr/lib/ccache:$PATH" - make WITH_TARGET=linx64v5-linux-musl + if ! make WITH_TARGET=linx64v5-linux-musl; then + echo "Incremental build failed; retrying once from a clean LLVM build tree." + rm -rf \ + build/build-llvm-musl \ + output/linx_blockisa_llvm_musl \ + stamps/build-llvm-musl + make WITH_TARGET=linx64v5-linux-musl + fi - name: Save LLVM build cache if: steps.cache-llvm.outputs.cache-hit != 'true' From 78c1125bb417dc080084b8b55df2d61087f4437d Mon Sep 17 00:00:00 2001 From: lulu Date: Fri, 28 Aug 2026 16:26:33 +0800 Subject: [PATCH 6/8] ci: make LLVM cache reuse incremental and complete --- .github/workflows/pr-gate.yml | 74 ++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml index 672ea17..acbec5f 100644 --- a/.github/workflows/pr-gate.yml +++ b/.github/workflows/pr-gate.yml @@ -77,13 +77,13 @@ jobs: uses: actions/cache/restore@v4 with: path: | - toolchain/build/build-llvm-musl - toolchain/stamps/build-llvm-musl - toolchain/output/linx_blockisa_llvm_musl/bin - toolchain/output/linx_blockisa_llvm_musl/lib - toolchain/output/linx_blockisa_llvm_musl/include - key: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate-v1 + toolchain/src + toolchain/build + toolchain/stamps + toolchain/output/linx_blockisa_llvm_musl + key: llvm-${{ runner.os }}-tileop-required-gate-v2-${{ steps.llvm-source.outputs.sha }} restore-keys: | + llvm-${{ runner.os }}-tileop-required-gate-v2- llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate- llvm- @@ -108,26 +108,57 @@ jobs: echo "Toolchain SHA: $(git -C toolchain rev-parse HEAD)" echo "LLVM SHA: $(git -C toolchain/src/llvm-project rev-parse HEAD)" - - name: Prepare restored cache for incremental LLVM build - if: steps.cache-llvm.outputs.cache-hit != 'true' - run: | - echo "Exact LLVM cache miss; reusing the nearest compatible build tree." - rm -f toolchain/stamps/build-llvm-musl - - - name: Build latest toolchain + - name: Restore, incrementally update, or build toolchain working-directory: toolchain env: + CACHE_HIT: ${{ steps.cache-llvm.outputs.cache-hit }} + CACHE_MATCHED_KEY: ${{ steps.cache-llvm.outputs.cache-matched-key }} + EXACT_V2_KEY: llvm-${{ runner.os }}-tileop-required-gate-v2-${{ steps.llvm-source.outputs.sha }} + LEGACY_EXACT_KEY: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate-v1 ENABLE_CCACHE: on THREADS: '4' run: | - set -o pipefail + set -euo pipefail export PATH="/usr/lib/ccache:$PATH" + + if [ "${CACHE_HIT}" = "true" ]; then + echo "Exact complete toolchain cache hit: ${EXACT_V2_KEY}" + echo "Skipping toolchain build." + exit 0 + fi + + if [ "${CACHE_MATCHED_KEY}" = "${LEGACY_EXACT_KEY}" ] && \ + [ -x output/linx_blockisa_llvm_musl/bin/clang ]; then + echo "Reusing the legacy exact-SHA LLVM cache." + mkdir -p stamps + touch stamps/build-llvm-musl + elif [[ "${CACHE_MATCHED_KEY}" == llvm-${{ runner.os }}-tileop-required-gate-v2-* ]] && \ + [ -f build/build-llvm-musl/CMakeCache.txt ]; then + echo "Updating the nearest v2 LLVM build tree incrementally." + if cmake -S src/llvm-project/llvm -B build/build-llvm-musl && \ + cmake --build build/build-llvm-musl --parallel "${THREADS}" && \ + cmake --install build/build-llvm-musl; then + cd output/linx_blockisa_llvm_musl/bin + ln -s -f clang linx64v5-linux-musl-clang + ln -s -f clang++ linx64v5-linux-musl-clang++ + cd ../../.. + mkdir -p stamps + touch stamps/build-llvm-musl + else + echo "Incremental LLVM update failed; falling back to a clean build." + rm -rf build/build-llvm-musl output/linx_blockisa_llvm_musl stamps + fi + else + echo "No reusable LLVM build tree found; performing a clean build." + rm -f stamps/build-llvm-musl + fi + if ! make WITH_TARGET=linx64v5-linux-musl; then - echo "Incremental build failed; retrying once from a clean LLVM build tree." + echo "Cached/incremental toolchain completion failed; retrying once cleanly." rm -rf \ build/build-llvm-musl \ output/linx_blockisa_llvm_musl \ - stamps/build-llvm-musl + stamps make WITH_TARGET=linx64v5-linux-musl fi @@ -136,12 +167,11 @@ jobs: uses: actions/cache/save@v4 with: path: | - toolchain/build/build-llvm-musl - toolchain/stamps/build-llvm-musl - toolchain/output/linx_blockisa_llvm_musl/bin - toolchain/output/linx_blockisa_llvm_musl/lib - toolchain/output/linx_blockisa_llvm_musl/include - key: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate-v1 + toolchain/src + toolchain/build + toolchain/stamps + toolchain/output/linx_blockisa_llvm_musl + key: llvm-${{ runner.os }}-tileop-required-gate-v2-${{ steps.llvm-source.outputs.sha }} - name: Run TileOP contract checks working-directory: toolchain/src/Linx-TileOP-API From 043c921d927b566052e96c9f1f2b7ab51c05341b Mon Sep 17 00:00:00 2001 From: lulu Date: Fri, 28 Aug 2026 16:28:11 +0800 Subject: [PATCH 7/8] ci: restore legacy LLVM cache with compatible paths --- .github/workflows/pr-gate.yml | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml index acbec5f..c9bda3f 100644 --- a/.github/workflows/pr-gate.yml +++ b/.github/workflows/pr-gate.yml @@ -72,8 +72,8 @@ jobs: echo "sha=${LLVM_SOURCE_SHA}" >> "$GITHUB_OUTPUT" echo "Resolved latest LLVM ${LLVM_REF} -> ${LLVM_SOURCE_SHA}" - - name: Restore LLVM build cache - id: cache-llvm + - name: Restore complete v2 toolchain cache + id: cache-llvm-v2 uses: actions/cache/restore@v4 with: path: | @@ -84,8 +84,19 @@ jobs: key: llvm-${{ runner.os }}-tileop-required-gate-v2-${{ steps.llvm-source.outputs.sha }} restore-keys: | llvm-${{ runner.os }}-tileop-required-gate-v2- - llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate- - llvm- + + - name: Restore legacy exact-SHA LLVM cache + id: cache-llvm-legacy + if: steps.cache-llvm-v2.outputs.cache-hit != 'true' + uses: actions/cache/restore@v4 + with: + path: | + toolchain/build/build-llvm-musl + toolchain/stamps/build-llvm-musl + toolchain/output/linx_blockisa_llvm_musl/bin + toolchain/output/linx_blockisa_llvm_musl/lib + toolchain/output/linx_blockisa_llvm_musl/include + key: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate-v1 - name: Initialize component sources working-directory: toolchain @@ -111,28 +122,28 @@ jobs: - name: Restore, incrementally update, or build toolchain working-directory: toolchain env: - CACHE_HIT: ${{ steps.cache-llvm.outputs.cache-hit }} - CACHE_MATCHED_KEY: ${{ steps.cache-llvm.outputs.cache-matched-key }} + V2_CACHE_HIT: ${{ steps.cache-llvm-v2.outputs.cache-hit }} + V2_CACHE_MATCHED_KEY: ${{ steps.cache-llvm-v2.outputs.cache-matched-key }} + LEGACY_CACHE_HIT: ${{ steps.cache-llvm-legacy.outputs.cache-hit }} EXACT_V2_KEY: llvm-${{ runner.os }}-tileop-required-gate-v2-${{ steps.llvm-source.outputs.sha }} - LEGACY_EXACT_KEY: llvm-${{ steps.llvm-source.outputs.sha }}-${{ runner.os }}-tileop-required-gate-v1 ENABLE_CCACHE: on THREADS: '4' run: | set -euo pipefail export PATH="/usr/lib/ccache:$PATH" - if [ "${CACHE_HIT}" = "true" ]; then + if [ "${V2_CACHE_HIT}" = "true" ]; then echo "Exact complete toolchain cache hit: ${EXACT_V2_KEY}" echo "Skipping toolchain build." exit 0 fi - if [ "${CACHE_MATCHED_KEY}" = "${LEGACY_EXACT_KEY}" ] && \ + if [ "${LEGACY_CACHE_HIT}" = "true" ] && \ [ -x output/linx_blockisa_llvm_musl/bin/clang ]; then echo "Reusing the legacy exact-SHA LLVM cache." mkdir -p stamps touch stamps/build-llvm-musl - elif [[ "${CACHE_MATCHED_KEY}" == llvm-${{ runner.os }}-tileop-required-gate-v2-* ]] && \ + elif [[ "${V2_CACHE_MATCHED_KEY}" == llvm-${{ runner.os }}-tileop-required-gate-v2-* ]] && \ [ -f build/build-llvm-musl/CMakeCache.txt ]; then echo "Updating the nearest v2 LLVM build tree incrementally." if cmake -S src/llvm-project/llvm -B build/build-llvm-musl && \ @@ -163,7 +174,7 @@ jobs: fi - name: Save LLVM build cache - if: steps.cache-llvm.outputs.cache-hit != 'true' + if: steps.cache-llvm-v2.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: path: | From 65e17f03a2afc8622dc824d02331eaa1c52f4cea Mon Sep 17 00:00:00 2001 From: lulu Date: Fri, 28 Aug 2026 16:45:26 +0800 Subject: [PATCH 8/8] ci: preserve legacy LLVM completion stamp ordering --- .github/workflows/pr-gate.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml index c9bda3f..a1fbdc6 100644 --- a/.github/workflows/pr-gate.yml +++ b/.github/workflows/pr-gate.yml @@ -142,6 +142,7 @@ jobs: [ -x output/linx_blockisa_llvm_musl/bin/clang ]; then echo "Reusing the legacy exact-SHA LLVM cache." mkdir -p stamps + touch stamps/check-write-permission touch stamps/build-llvm-musl elif [[ "${V2_CACHE_MATCHED_KEY}" == llvm-${{ runner.os }}-tileop-required-gate-v2-* ]] && \ [ -f build/build-llvm-musl/CMakeCache.txt ]; then