diff --git a/.github/workflows/spirv-ci.yml b/.github/workflows/spirv-ci.yml
index 52b5de8df..e07faa133 100644
--- a/.github/workflows/spirv-ci.yml
+++ b/.github/workflows/spirv-ci.yml
@@ -102,32 +102,98 @@ jobs:
# Each suite is its own step so failures are individually identifiable
# in the PR check rollup. Add new suites as new steps below.
- - name: Test - SPIRV Translator (check-amd-llvm-spirv)
+ - name: Test - SPIRV Translator (check-amd-llvm-spirv) [PR head]
# Non-blocking: upstream Khronos breaks ~1 translator lit test per
# week (spirv-val drift, LLVM IR changes vs DebugInfo tests, DCE).
# Their fixes typically land within a day; our daily upstream-merge
# cron pulls them in. Blocking here would gate unrelated PRs during
- # those windows. The next step posts a sticky PR comment listing
- # any failing tests so AMD-side regressions stay visible.
+ # those windows. The baseline run below partitions failures into
+ # new / fixed / pre-existing so AMD-side regressions stay visible.
id: check_spirv_xlator
continue-on-error: true
run: |
set -o pipefail
ninja -C build check-amd-llvm-spirv 2>&1 | tee build/check-amd-llvm-spirv.log
- - name: Post translator lit failure summary to PR
+ - name: Capture PR head translator failures
+ if: github.event_name == 'pull_request' && always()
+ run: |
+ grep -oE '^FAIL: LLVM_SPIRV :: \S+' build/check-amd-llvm-spirv.log \
+ | sort -u > build/spirv-fails-pr.txt || true
+ echo "PR head failures:"; cat build/spirv-fails-pr.txt
+
+ - name: Switch translator to amd-staging tip for baseline
+ if: github.event_name == 'pull_request' && always()
+ run: |
+ cd llvm-project/llvm/projects/SPIRV-LLVM-Translator
+ git fetch --depth=1 origin amd-staging
+ git checkout FETCH_HEAD
+
+ - name: Test - SPIRV Translator [baseline amd-staging]
+ # Re-run the lit suite with the translator at amd-staging tip so the
+ # comment script can compute the per-PR delta (new vs fixed vs
+ # pre-existing). Incremental rebuild — only translator objects change.
+ if: github.event_name == 'pull_request' && always()
+ id: check_spirv_baseline
+ continue-on-error: true
+ run: |
+ set -o pipefail
+ # Re-configure to pick up any CMakeLists / file-list changes in the swap
+ cmake -G Ninja -S llvm-project/llvm -B build
+ ninja -C build check-amd-llvm-spirv 2>&1 \
+ | tee build/check-amd-llvm-spirv-baseline.log
+ grep -oE '^FAIL: LLVM_SPIRV :: \S+' build/check-amd-llvm-spirv-baseline.log \
+ | sort -u > build/spirv-fails-baseline.txt || true
+
+ - name: Post translator lit summary to PR
if: github.event_name == 'pull_request' && always()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const marker = '';
- const log = fs.readFileSync('build/check-amd-llvm-spirv.log', 'utf8');
- const failed = [...log.matchAll(/^FAIL: (LLVM_SPIRV :: \S+)/gm)].map(m => m[1]);
+ const read = (p) => {
+ try { return fs.readFileSync(p, 'utf8').split('\n').filter(Boolean); }
+ catch { return null; }
+ };
+ const prList = read('build/spirv-fails-pr.txt');
+ const baseList = read('build/spirv-fails-baseline.txt');
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
- const body = failed.length === 0
- ? `${marker}\n✅ **SPIRV translator lit suite (\`check-amd-llvm-spirv\`)**: all tests passing.`
- : `${marker}\n⚠️ **SPIRV translator lit suite (\`check-amd-llvm-spirv\`)**: ${failed.length} failing — non-blocking (see [run](${runUrl})).\n\nUpstream Khronos churn breaks these intermittently; check whether the failure is also on \`amd-staging\` tip before assuming this PR caused it.\n\nFailing tests
\n\n\`\`\`\n${failed.join('\n')}\n\`\`\`\n `;
+ const fmt = (xs) => xs.length ? '```\n' + xs.join('\n') + '\n```' : '_(none)_';
+
+ let body;
+ if (!prList) {
+ body = `${marker}\n⚠️ **SPIRV translator lit suite**: PR run did not produce a result (see [run](${runUrl})).`;
+ } else if (!baseList) {
+ body = prList.length === 0
+ ? `${marker}\n✅ **SPIRV translator lit suite**: all tests passing on PR head. (Baseline comparison unavailable.)`
+ : `${marker}\n⚠️ **SPIRV translator lit suite**: ${prList.length} failing on PR head; baseline comparison unavailable (see [run](${runUrl})).\n\nFailing tests
\n\n${fmt(prList)}\n `;
+ } else {
+ const prSet = new Set(prList);
+ const baseSet = new Set(baseList);
+ const newFails = prList.filter(t => !baseSet.has(t));
+ const fixed = baseList.filter(t => !prSet.has(t));
+ const common = prList.filter(t => baseSet.has(t));
+
+ let headline;
+ if (newFails.length === 0 && fixed.length === 0 && common.length === 0) {
+ headline = `✅ **SPIRV translator lit suite**: clean on both PR head and \`amd-staging\` baseline.`;
+ } else if (newFails.length > 0) {
+ headline = `🔴 **${newFails.length} new translator lit failure${newFails.length === 1 ? '' : 's'}** introduced by this PR (non-blocking; see [run](${runUrl})).`;
+ } else if (fixed.length > 0 && common.length === 0) {
+ headline = `🟢 **SPIRV translator lit suite**: this PR fixes ${fixed.length} test${fixed.length === 1 ? '' : 's'} that fail on \`amd-staging\`. No remaining failures.`;
+ } else if (fixed.length > 0) {
+ headline = `🟢 This PR fixes ${fixed.length} translator lit test${fixed.length === 1 ? '' : 's'} (vs \`amd-staging\` baseline). ${common.length} pre-existing failure${common.length === 1 ? '' : 's'} remain.`;
+ } else {
+ headline = `⚠️ **${common.length} pre-existing translator lit failure${common.length === 1 ? '' : 's'}** on baseline; not caused by this PR (see [run](${runUrl})).`;
+ }
+
+ body = `${marker}\n${headline}\n\n` +
+ ` 0 ? ' open' : ''}>🔴 New failures (${newFails.length}) — likely caused by this PR
\n\n${fmt(newFails)}\n \n\n` +
+ `🟢 Fixed by this PR (${fixed.length}) — failing on baseline, passing here
\n\n${fmt(fixed)}\n \n\n` +
+ `⚠️ Pre-existing on \`amd-staging\` (${common.length})
\n\n${fmt(common)}\n `;
+ }
+
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: context.payload.pull_request.number,