Skip to content

[AArch64] wrong code at -O1: sign extension of a shifted 8-bit value is selected as sbfiz #241864

Open

Description

@hazohelet

Live Reproducer: https://godbolt.org/z/KTGEEfbr8

Compiling the following C code for aarch64 with clang -O1 and running it prints the wrong result.

#include <stdio.h>
static volatile int X = -1;
unsigned _BitInt(65) m;
__int128 sign(signed char a) { return a < 0 ? -1 : 0; }
int main(void) {
  signed char x = X;
  m = sign(x);
  unsigned long c = x;
  for (int i = 0; i < 8; i++)
    c *= m;
  printf("%lu\n", c);
}

clang command:

clang --target=aarch64-linux-gnu -static -O1 repro.c && qemu-aarch64 ./a.out

Output (wrong):

0

Expected (what -O0 prints, and what x86-64 prints):

18446744073709551615

x is -1, so sign(x) is -1 and m is all ones. The low word of m is computed as (long)(signed char)X << 33 instead of the sign of (signed char)X:

        ldr     w9, [x8, :lo12:X]
        sxtb    w10, w9
        mov     w8, w9
        sxtb    x1, w9
        sbfiz   x8, x8, #33, #8
        ...
        stp     x8, x9, [x10]                   // m

Notes:

  • Correct at -O0; -O1, -O2, -O3, -Os and -Oz are wrong

clang version:

clang version 24.0.0git (https://github.com/llvm/llvm-project f5744e07d2dba7367ec68426fd6b6b07e2916b39)

This reproduces with current LLVM trunk.

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

    generated by fuzzerRegression test generated by fuzzing or AI analysis - not a real world code snippetllvm:optimizations

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions