Skip to content

GCC ARMV9SME: SGEMM/SSYMM/SSYRK/SSYR2K/STRMM direct C kernels can return without computing #6099

Open

Description

@BenKnill

GCC ARMV9SME: SGEMM/SSYMM/SSYRK/SSYR2K/STRMM direct C kernels can return without computing

The attached results reproduce incorrect output on OpenBLAS develop commit
31e82fa8c509e6f0d96288de3c20d8916d894e72, built with GCC 15.2.0,
using GNU make, DYNAMIC_ARCH=1, and forced ARMV9SME dispatch under QEMU
10.2.1. A separate build of the same source with Clang 21.1.8 produces the
expected results for these calls.

Minimal SGEMM reproduction

This uses a 3-by-2 output matrix, k=2, alpha=2, beta=1, all-one A and B,
and C initially filled with 3. Every result should be exactly 7.

#include <cblas.h>
#include <stdio.h>
int main(void) {
    float a[6]={1,1,1,1,1,1}, b[4]={1,1,1,1}, c[6]={3,3,3,3,3,3};
    cblas_sgemm(CblasRowMajor,CblasNoTrans,CblasNoTrans,3,2,2,2,a,2,b,2,1,c,2);
    int wrong=0;
    for(int i=0;i<6;i++) wrong+=c[i]!=7;
    printf("N1-REPRO: %s core=%s C[0]=%g want=7 wrong=%d/6\n",
           wrong?"WRONG":"RIGHT",openblas_get_corename(),c[0],wrong);
    return wrong?1:0;
}

GCC build:

N1-REPRO: WRONG core=armv9sme C[0]=3 want=7 wrong=6/6
empty sgemm_alpha_beta2x2 should never get called!!!

Clang build:

N1-REPRO: RIGHT core=armv9sme C[0]=7 want=7 wrong=0/6

Build and run

On an x86-64 Linux host with the AArch64 GCC cross toolchain, AArch64 sysroot
at /usr/aarch64-linux-gnu, and QEMU installed, save the program as repro.c
next to the source directory. In a clean checkout of the pinned commit:

make -j4 ARCH=arm64 BINARY=64 TARGET=ARMV8 DYNAMIC_ARCH=1 \
  DYNAMIC_LIST='ARMV9SME ARMV8SVE A64FX' NOFORTRAN=1 NO_LAPACK=1 \
  USE_THREAD=0 NUM_THREADS=1 HOSTCC=gcc CC=aarch64-linux-gnu-gcc \
  AR=aarch64-linux-gnu-ar RANLIB=aarch64-linux-gnu-ranlib

make ARCH=arm64 BINARY=64 TARGET=ARMV8 DYNAMIC_ARCH=1 \
  DYNAMIC_LIST='ARMV9SME ARMV8SVE A64FX' NOFORTRAN=1 NO_LAPACK=1 \
  USE_THREAD=0 NUM_THREADS=1 HOSTCC=gcc CC=aarch64-linux-gnu-gcc \
  AR=aarch64-linux-gnu-ar RANLIB=aarch64-linux-gnu-ranlib \
  PREFIX="$PWD/../openblas-gcc-install" install

aarch64-linux-gnu-gcc -O2 -Wall -Wextra \
  -I../openblas-gcc-install/include ../repro.c \
  ../openblas-gcc-install/lib/libopenblas.a -lm -lpthread -o ../repro-gcc

OPENBLAS_CORETYPE=ARMV9SME OPENBLAS_NUM_THREADS=1 \
  qemu-aarch64 -L /usr/aarch64-linux-gnu -cpu max ../repro-gcc

For the comparison, use a separate clean source checkout and install prefix,
with the same make flags except
CC='clang-21 --target=aarch64-linux-gnu --gcc-toolchain=/usr'. The small C
reproducer can still be linked with aarch64-linux-gnu-gcc; the library compiler
is the changed variable. Both library builds include all four precisions.
These are emulated runtime results; native SME hardware reproduction is not
included.

Scope and source cause

The original census witness also reports GCC wrong / Clang right for tight
row-major SSYMM, SSYRK and STRMM calls. An additional finite-input SSYR2K witness
does the same for both triangles at n=40, k=8, alpha=beta=1. The sources
and recorded output are in openblas-sme-repro.zip.

The specialized C kernels require HAVE_SME and a feature condition that
includes __ARM_FEATURE_SME, __ARM_FEATURE_LOCALLY_STREAMING, and
Clang >=16. GCC therefore compiles empty helpers even when it can assemble SME
instructions. For example,
sgemm_direct_alpha_beta_arm64_sme1.c
replaces its arithmetic helper with the diagnostic printed above.

The interface checks the selected core and call shape without checking that
the corresponding C backend was compiled. The relevant blocks are in
gemm.c,
symm.c,
syrk.c,
syr2k.c, and
trsm.c's TRMM block.

A fix should gate these direct entries on the capability of the compiled
backend, then validate the path used when they are unavailable. In dynamic
builds, the interface and kernel translation units can have different target
flags, so the interface needs a build capability that reflects the kernel's
full condition. In SGEMM, skipping the first direct block still reaches a
separate general SME dispatch below it; that destination also needs testing.

Related reports: #5763 concerned a misplaced return affecting non-SME cores;
this reproduction explicitly selects armv9sme. #5414 discussed older Apple
M4 SGEMMT failures and fragile SME routing. The present report supplies a
GCC-versus-Clang reproduction of the compiler-gated C helpers at the pinned
commit. STRSM solves the attached cases: #5898 already restricted this direct
multiplication block to TRMM builds.

First surfaced by differential testing in an automated arm64 SRU census;
the pinned develop reproductions and sibling investigation were prepared by
Codex.

openblas-sme-repro.zip

Activity

  1. martin-frbg commented on Oct 15, 2026

    @martin-frbg
    Collaborator

    Expectation was that SME would be working with gcc 16 at least, but sadly that does not appear to be the case (at least as far as building with modified compiler guards on Apple M4 or in a QEMU VM with armv9.3 characteristics is concerned - no compiler errors but no sane GEMM results either)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions