From 22fcb4c1138002dbfca0cd5624b66b5080a1199c Mon Sep 17 00:00:00 2001 From: Bernhard Manfred Gruber Date: Tue, 14 Jul 2026 15:30:24 +0200 Subject: [PATCH 1/4] Move SASS diff description to a SKILL Fixes: #7829 --- .agent/skills/sass-diff/SKILL.md | 50 ++++++++++++++++++++++++++++++++ AGENTS.md | 48 ------------------------------ 2 files changed, 50 insertions(+), 48 deletions(-) create mode 100644 .agent/skills/sass-diff/SKILL.md diff --git a/.agent/skills/sass-diff/SKILL.md b/.agent/skills/sass-diff/SKILL.md new file mode 100644 index 00000000000..0a0bcc4fd38 --- /dev/null +++ b/.agent/skills/sass-diff/SKILL.md @@ -0,0 +1,50 @@ +--- +name: sass-diff +description: Use when asked to check for SASS (or PTX) changes between commits, branches, or a local changeset; guides normalization, comparison, and reporting of CUDA disassembly diffs. +--- + +# SASS Diffs + +Use this when asked to check for SASS changes between commits, branches or a local changeset. + +## Goal + +Detect relevant changes in generated CUDA machine code (i.e. SASS) while filtering noise from addresses, symbols, metadata, etc. +Any non-trivial change must be detected. + +## Inputs to establish + +* Compilation target under test +* The CUDA SM architectures to compile for. Try to detect this from the code and offer the user a list of suggestions. + The user must confirm or provide this list. +* Baseline disassembly (from the previous commit/branch or the current commit without the changes in the working copy). +* Comparison disassembly (from the current commit/branch or the current commit with the changes in the working copy). +* By default, prefer `cuobjdump -sass` to inspect SASS changes. + Use `cuobjdump -ptx` if the request is to check for PTX changes instead. + +## Normalization rules (strip known noise) + +Apply these transforms to both baseline and candidate listings before diffing. +Write the normalized listings to separate files. + +* Remove addresses/offsets/hex location prefixes. +* Remove build IDs, timestamps, absolute paths, temp directories, and compiler banners. +* Normalize whitespace and alignment to single spaces. +* Remove empty lines and purely comment lines. + +## Comparison rules (what matters) + +Ignore as trivial: + +* Register renaming with identical instruction sequence and operands. +* Pure label renumbering or reordering of identical basic blocks. +* Formatting-only differences or reordered symbol tables. + +## Reporting + +* If any non-trivial change was detected, the top 5 regions where a non-trivial change was detected, + including the name of the kernel they appeared in. +* A short summary of the diff type (opcode change, memory access size change, size delta, control-flow, etc.). +* Explicitly state if only noise was detected after normalization. +* If you are not sure if the differences are impactful, show it and ask the user for guidance. +* Keep the disassembly dumps available for reference and show the command to the user to generate a diff. diff --git a/AGENTS.md b/AGENTS.md index 2141892202c..3517c3a5e1d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -273,54 +273,6 @@ Test organization: --- -## SASS Diffs - -Use this test when asked to check for SASS changes between commits, branches or a local changeset. - -### Goal - -Detect relevant changes in generated CUDA machine code (i.e. SASS) while filtering noise from addresses, symbols, metadata, etc. -Any non-trivial change must be detected. - -### Inputs to establish - -* Compiled binary under test -* The CUDA SM architectures to compile for. Try to detect this from the code and offer the user a list of suggestions. - The user must conform or provide this list. -* Baseline disassembly (from the previous commit/branch or the current commit without the changes in the working copy). -* Comparison disassembly (form the current commit/branch or the current commit with the changes in the working copy). -* By default, prefer `cuobjdump -sass` to inspect SASS changes. - Use `cuobjdump -ptx` if the request is to check for PTX changes instead. - -### Normalization rules (strip known noise) - -Apply these transforms to both baseline and candidate listings before diffing. -Write the normalized listings to separate files. - -* Remove addresses/offsets/hex location prefixes. -* Remove build IDs, timestamps, absolute paths, temp directories, and compiler banners. -* Normalize whitespace and alignment to single spaces. -* Remove empty lines and purely comment lines. - -### Comparison rules (what matters) - -Ignore as trivial: - -* Register renaming with identical instruction sequence and operands. -* Pure label renumbering or reordering of identical basic blocks. -* Formatting-only differences or reordered symbol tables. - -### Reporting - -* If any non-trivial change was detected, the top 5 regions where a non-trivial change was detected, - including the name of the kernel they appeared in. -* A short summary of the diff type (opcode change, memory access size change, size delta, control-flow, etc.). -* Explicitly state if only noise was detected after normalization. -* If you are not sure if the differences are impactful, show it and ask the user for guidance. -* Keep the disassembly dumps available for reference and show the command to the user to generate a diff. - ---- - ## Continuous Integration (CI) See `ci-overview.md` for detailed examples and troubleshooting guidance. From 06d16dd7c170cff21ed625b5fad51e3073671df4 Mon Sep 17 00:00:00 2001 From: Bernhard Manfred Gruber Date: Tue, 14 Jul 2026 15:53:12 +0200 Subject: [PATCH 2/4] Split input and disasm section + comp script --- .agent/skills/sass-diff/SKILL.md | 30 +++++---- .agent/skills/sass-diff/normalize_codegen.py | 71 ++++++++++++++++++++ 2 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 .agent/skills/sass-diff/normalize_codegen.py diff --git a/.agent/skills/sass-diff/SKILL.md b/.agent/skills/sass-diff/SKILL.md index 0a0bcc4fd38..749c2ed523b 100644 --- a/.agent/skills/sass-diff/SKILL.md +++ b/.agent/skills/sass-diff/SKILL.md @@ -17,20 +17,21 @@ Any non-trivial change must be detected. * Compilation target under test * The CUDA SM architectures to compile for. Try to detect this from the code and offer the user a list of suggestions. The user must confirm or provide this list. -* Baseline disassembly (from the previous commit/branch or the current commit without the changes in the working copy). -* Comparison disassembly (from the current commit/branch or the current commit with the changes in the working copy). -* By default, prefer `cuobjdump -sass` to inspect SASS changes. - Use `cuobjdump -ptx` if the request is to check for PTX changes instead. +* Baseline source (e.g. the previous commit/branch or the current commit without the changes in the working copy). +* Comparison source (e.g. the current commit/branch or the current commit with the changes in the working copy). +* Whether a SASS (default) or PTX diff is requested. -## Normalization rules (strip known noise) +## Disassembly listing generation + +* Compile both, the baseline and comparison source, with the same compiler flags and options. + When not specified otherwise, lookup the options from `compile_commands.json` + or the current build system (i.e. CMake files). + Make sure the CUDA SM architectures (`CMAKE_CUDA_ARCHITECTURES`) are set to the user-provided or approved list. +* Dump the disassembly from the binaries produced in the previous set using `cuobjdump -sass` or `cuobjdump -ptx`. -Apply these transforms to both baseline and candidate listings before diffing. -Write the normalized listings to separate files. +## Normalization rules (strip known noise) -* Remove addresses/offsets/hex location prefixes. -* Remove build IDs, timestamps, absolute paths, temp directories, and compiler banners. -* Normalize whitespace and alignment to single spaces. -* Remove empty lines and purely comment lines. +Use the `normalize_codegen.py` script to produce normalized disassembly listings for both the baseline and comparison. ## Comparison rules (what matters) @@ -39,12 +40,13 @@ Ignore as trivial: * Register renaming with identical instruction sequence and operands. * Pure label renumbering or reordering of identical basic blocks. * Formatting-only differences or reordered symbol tables. +* Changes to symbol names (global function names) ## Reporting -* If any non-trivial change was detected, the top 5 regions where a non-trivial change was detected, +* If any non-trivial change was detected, report the top 5 regions where a non-trivial change was detected, including the name of the kernel they appeared in. -* A short summary of the diff type (opcode change, memory access size change, size delta, control-flow, etc.). +* Provide short summary of the diff type (opcode change, memory access size change, size delta, control-flow, etc.). * Explicitly state if only noise was detected after normalization. * If you are not sure if the differences are impactful, show it and ask the user for guidance. -* Keep the disassembly dumps available for reference and show the command to the user to generate a diff. +* Keep the original and normalized disassembly dumps available and tell the user where they can find them. diff --git a/.agent/skills/sass-diff/normalize_codegen.py b/.agent/skills/sass-diff/normalize_codegen.py new file mode 100644 index 00000000000..1e4af0c4235 --- /dev/null +++ b/.agent/skills/sass-diff/normalize_codegen.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Normalize CUDA PTX/SASS dumps for lightweight textual diffs. + +This intentionally removes common non-semantic noise but does not try to prove +semantic equivalence. Always inspect meaningful opcode, operand, and control-flow +changes manually after diffing normalized output. +""" + +from __future__ import annotations + +import argparse +import re +import sys +from pathlib import Path + + +def normalize_common(line: str) -> str: + line = line.rstrip() + line = re.sub(r"/tmp/[^\s,)]+", "/tmp/PATH", line) + line = re.sub(r"/home/[^\s,)]+", "/home/PATH", line) + line = re.sub(r"0x[0-9a-fA-F]+", "0xHEX", line) + line = re.sub(r"\b[0-9a-fA-F]{16,}\b", "HEX", line) + line = re.sub(r"\s+", " ", line).strip() + return line + + +def normalize_sass(line: str) -> str: + line = re.sub(r"^\s*/\*[0-9a-fA-F]+\*/\s*", "", line) + line = re.sub(r"^\s*/\*\s*[0-9]+\s*\*/\s*", "", line) + line = re.sub(r"^\s*//.*$", "", line) + line = normalize_common(line) + line = re.sub(r"`\(.*\)$", "`(target)", line) + return line + + +def normalize_ptx(line: str) -> str: + line = re.sub(r"^\s*//.*$", "", line) + line = re.sub(r"^\s*\.file\s+\d+\s+.*$", ".file N PATH", line) + line = re.sub(r"^\s*\.loc\s+\d+\s+\d+.*$", ".loc N N", line) + line = re.sub(r"\$L__[A-Za-z0-9_]+", "$L__LABEL", line) + line = normalize_common(line) + return line + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("path", nargs="?", help="Input file; defaults to stdin") + parser.add_argument("--kind", choices=("sass", "ptx"), required=True) + args = parser.parse_args() + + if args.path: + lines = Path(args.path).read_text(errors="replace").splitlines() + else: + lines = sys.stdin.read().splitlines() + + normalizer = normalize_sass if args.kind == "sass" else normalize_ptx + previous_blank = False + for raw in lines: + line = normalizer(raw) + if not line: + if not previous_blank: + print() + previous_blank = True + continue + print(line) + previous_blank = False + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) From e9fe056d7610ebf0a5f1653e634817f6b3262afb Mon Sep 17 00:00:00 2001 From: Bernhard Manfred Gruber Date: Tue, 14 Jul 2026 15:54:41 +0200 Subject: [PATCH 3/4] Review --- .agent/skills/sass-diff/SKILL.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.agent/skills/sass-diff/SKILL.md b/.agent/skills/sass-diff/SKILL.md index 749c2ed523b..c92e9461495 100644 --- a/.agent/skills/sass-diff/SKILL.md +++ b/.agent/skills/sass-diff/SKILL.md @@ -46,7 +46,9 @@ Ignore as trivial: * If any non-trivial change was detected, report the top 5 regions where a non-trivial change was detected, including the name of the kernel they appeared in. -* Provide short summary of the diff type (opcode change, memory access size change, size delta, control-flow, etc.). +* Provide a short summary of the diff type, + including opcode changes, memory access size/cache policy changes, control-flow changes, register-count changes, + spills/local memory, shared memory, and occupancy-relevant resource deltas. * Explicitly state if only noise was detected after normalization. * If you are not sure if the differences are impactful, show it and ask the user for guidance. * Keep the original and normalized disassembly dumps available and tell the user where they can find them. From d09845a052b3b93404afe96b666a22d645d49828 Mon Sep 17 00:00:00 2001 From: Bernhard Manfred Gruber Date: Tue, 14 Jul 2026 16:18:44 +0200 Subject: [PATCH 4/4] Remove SASS normalization again --- .agent/skills/sass-diff/SKILL.md | 8 +-- .agent/skills/sass-diff/normalize_codegen.py | 71 -------------------- 2 files changed, 2 insertions(+), 77 deletions(-) delete mode 100644 .agent/skills/sass-diff/normalize_codegen.py diff --git a/.agent/skills/sass-diff/SKILL.md b/.agent/skills/sass-diff/SKILL.md index c92e9461495..4dd594e2e55 100644 --- a/.agent/skills/sass-diff/SKILL.md +++ b/.agent/skills/sass-diff/SKILL.md @@ -29,10 +29,6 @@ Any non-trivial change must be detected. Make sure the CUDA SM architectures (`CMAKE_CUDA_ARCHITECTURES`) are set to the user-provided or approved list. * Dump the disassembly from the binaries produced in the previous set using `cuobjdump -sass` or `cuobjdump -ptx`. -## Normalization rules (strip known noise) - -Use the `normalize_codegen.py` script to produce normalized disassembly listings for both the baseline and comparison. - ## Comparison rules (what matters) Ignore as trivial: @@ -49,6 +45,6 @@ Ignore as trivial: * Provide a short summary of the diff type, including opcode changes, memory access size/cache policy changes, control-flow changes, register-count changes, spills/local memory, shared memory, and occupancy-relevant resource deltas. -* Explicitly state if only noise was detected after normalization. +* Explicitly state if only noise was detected. * If you are not sure if the differences are impactful, show it and ask the user for guidance. -* Keep the original and normalized disassembly dumps available and tell the user where they can find them. +* Keep the disassembly dumps available and tell the user where they can find them. diff --git a/.agent/skills/sass-diff/normalize_codegen.py b/.agent/skills/sass-diff/normalize_codegen.py deleted file mode 100644 index 1e4af0c4235..00000000000 --- a/.agent/skills/sass-diff/normalize_codegen.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 -"""Normalize CUDA PTX/SASS dumps for lightweight textual diffs. - -This intentionally removes common non-semantic noise but does not try to prove -semantic equivalence. Always inspect meaningful opcode, operand, and control-flow -changes manually after diffing normalized output. -""" - -from __future__ import annotations - -import argparse -import re -import sys -from pathlib import Path - - -def normalize_common(line: str) -> str: - line = line.rstrip() - line = re.sub(r"/tmp/[^\s,)]+", "/tmp/PATH", line) - line = re.sub(r"/home/[^\s,)]+", "/home/PATH", line) - line = re.sub(r"0x[0-9a-fA-F]+", "0xHEX", line) - line = re.sub(r"\b[0-9a-fA-F]{16,}\b", "HEX", line) - line = re.sub(r"\s+", " ", line).strip() - return line - - -def normalize_sass(line: str) -> str: - line = re.sub(r"^\s*/\*[0-9a-fA-F]+\*/\s*", "", line) - line = re.sub(r"^\s*/\*\s*[0-9]+\s*\*/\s*", "", line) - line = re.sub(r"^\s*//.*$", "", line) - line = normalize_common(line) - line = re.sub(r"`\(.*\)$", "`(target)", line) - return line - - -def normalize_ptx(line: str) -> str: - line = re.sub(r"^\s*//.*$", "", line) - line = re.sub(r"^\s*\.file\s+\d+\s+.*$", ".file N PATH", line) - line = re.sub(r"^\s*\.loc\s+\d+\s+\d+.*$", ".loc N N", line) - line = re.sub(r"\$L__[A-Za-z0-9_]+", "$L__LABEL", line) - line = normalize_common(line) - return line - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("path", nargs="?", help="Input file; defaults to stdin") - parser.add_argument("--kind", choices=("sass", "ptx"), required=True) - args = parser.parse_args() - - if args.path: - lines = Path(args.path).read_text(errors="replace").splitlines() - else: - lines = sys.stdin.read().splitlines() - - normalizer = normalize_sass if args.kind == "sass" else normalize_ptx - previous_blank = False - for raw in lines: - line = normalizer(raw) - if not line: - if not previous_blank: - print() - previous_blank = True - continue - print(line) - previous_blank = False - return 0 - - -if __name__ == "__main__": - raise SystemExit(main())