Skip to content

[LoongArch] wrong code: select between a _BitInt(16) value and a sign-extended _BitInt(8) value is sign-extended from bit 7 #241868

Open

Description

@hazohelet

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

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

int printf(const char *, ...);
static volatile unsigned long long A = 128;
int main(void) {
  _BitInt(16) a = A;
  unsigned u = a;
  signed char c = u;
  long long r = 4ULL == u ? (_BitInt(8))~c : a;
  printf("%llu\n", (unsigned long long)r);
  return 0;
}

clang command:

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

Output (wrong):

18446744073709551488

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

128

u is 128, so the condition is false and r should be a, which is 128. The generated code instead sign-extends the selected value from bit 7:

	ext.w.h	$a1, $a0
	bstrpick.d	$a1, $a1, 31, 0
	addi.d	$a1, $a1, -4
	sltui	$a1, $a1, 1           # u == 4 -> 0
	addi.d	$a2, $zero, -1
	maskeqz	$a1, $a2, $a1         # mask = 0
	xor	$a0, $a0, $a1         # a ^ mask = 128
	ext.w.b	$a1, $a0              # r = (signed char)128 = -128 (wrong)

Notes:

  • Correct at -O0

clang version:

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

Activity

  1. added
    generated by fuzzerRegression test generated by fuzzing or AI analysis - not a real world code snippet
    on Nov 12, 2026
  2. llvmorg-github-actions commented on Nov 12, 2026

    @llvmorg-github-actions

    @llvm/issue-subscribers-backend-loongarch

    Author: Takuya Shizuka (hazohelet)

    Details Live Reproducer: https://godbolt.org/z/TEfWGMefz

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

    int printf(const char *, ...);
    static volatile unsigned long long A = 128;
    int main(void) {
      _BitInt(16) a = A;
      unsigned u = a;
      signed char c = u;
      long long r = 4ULL == u ? (_BitInt(8))~c : a;
      printf("%llu\n", (unsigned long long)r);
      return 0;
    }

    clang command:

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

    Output (wrong):

    18446744073709551488
    

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

    128
    

    u is 128, so the condition is false and r should be a, which is 128. The generated code instead sign-extends the selected value from bit 7:

    	ext.w.h	$a1, $a0
    	bstrpick.d	$a1, $a1, 31, 0
    	addi.d	$a1, $a1, -4
    	sltui	$a1, $a1, 1           # u == 4 -> 0
    	addi.d	$a2, $zero, -1
    	maskeqz	$a1, $a2, $a1         # mask = 0
    	xor	$a0, $a0, $a1         # a ^ mask = 128
    	ext.w.b	$a1, $a0              # r = (signed char)128 = -128 (wrong)

    Notes:

    • Correct at -O0

    clang version:

    clang version 24.0.0git (https://github.com/llvm/llvm-project f5744e07d2dba7367ec68426fd6b6b07e2916b39)
    
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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions