baseline: /scratch/old_ab8cca3bd.cu
kernels compared: 152   IDENTICAL SASS: 149
  of which exl3_i8_gemm_kernel instantiations: 138
  EXPECTED void windows_probe_kernel<1>: 48 -> 48 instructions, 35 positional mismatches, same multiset=False
  EXPECTED void windows_probe_kernel<2>: 48 -> 48 instructions, 35 positional mismatches, same multiset=False
  EXPECTED void windows_probe_kernel<4>: 48 -> 48 instructions, 30 positional mismatches, same multiset=False
SASS 4 BPW IDENTITY: PASS

# Baseline: the tree at ab8cca3bd (this branch's first commit), where the
# mainloop still called dq8_i8_4bit and every B stride read 32.
#
# All 138 exl3_i8_gemm_kernel instantiations are SASS-identical, so the
# SHIPPED 4 bpw path did not move: not its instructions, not their order,
# not its register allocation.  dq_dense_i8_kernel<4> and
# decode_table_kernel are identical too.
#
# The three exemptions are the CPU-gate instrument windows_probe_kernel,
# where win8_aligned's word index was rewritten from the signed division
# (lane << 3) / (32 / BITS) to a right shift.  It is strictly cheaper --
# the instruction COUNT is unchanged only because ptxas pads with NOPs:
#
#   void windows_probe_kernel<1>: 48 -> 48 instructions, opcode delta {'IADD3': 2, 'SHF': -2, 'IMAD': -1, 'LEA': -2, 'NOP': 2, 'LOP3': 1}
#   void windows_probe_kernel<2>: 48 -> 48 instructions, opcode delta {'SHF': -1, 'LEA': -1, 'NOP': 2}
#   void windows_probe_kernel<4>: 48 -> 48 instructions, opcode delta {'SHF': -1, 'NOP': 1}
#
# and the two readers still agree: gate_bitwidth_windows.py checks the same
# extraction against tools/exl3_dq_reference.py at all 8 widths and all 32
# lanes, with a negative control that fires.
#
# Reproduce:
#   git show ab8cca3bd:tools/int8_gemm/exl3_i8_gemm.cu > /tmp/old.cu
#   python3 sass_4bpw_identity.py --old /tmp/old.cu
