Issue 179448
Summary Miscompile with _BitInt
Labels new issue
Assignees
Reporter bjope
    The test case here show a regression on trunk for clang-23: https://godbolt.org/z/xT7zG9ed9

What we have is a test case like this on C level:
```
#include <stdio.h>

signed _BitInt(121) idbi(signed _BitInt(121) b) {
  return b;
}

unsigned int test_zero_llrr(unsigned int tnr) {
  {
    signed _BitInt(121) x;
 signed _BitInt(121) res1, res2;
    x = idbi(0);
    res1 = x << 35;
 tnr += 0x100U + (res1 == 0 ? 0 : 1) ;
    x = idbi(0);
    res2 = x << 35;
    tnr += 0x200U + (res2 == res1 ? 0 : 2) ;
  }
  {
    signed _BitInt(121) x;
    signed _BitInt(121) res1, res2;
    x = idbi(0);
 res1 = x << 23;
    tnr += 0x400U + (res1 == 0 ? 0 : 4) ;
    x = idbi(0);
    res2 = x << 23;
    tnr += 0x800U + (res2 == res1 ? 0 : 8) ;
 }
  {
    signed _BitInt(121) x;
    signed _BitInt(121) res1, res2;
 x = idbi(0);
    res1 = x >> 61;
    tnr += 0x1000U + (res1 == 0 ? 0 : 16) ;
    x = idbi(0);
    res2 = x >> 61;
    tnr += 0x2000U + (res2 == res1 ? 0 : 32) ;
  }
  {
    signed _BitInt(121) x;
    signed _BitInt(121) res1, res2;
    x = idbi(0);
    res1 = x >> 23;
    tnr += 0x4000U + (res1 == 0 ? 0 : 64) ;
    x = idbi(0);
    res2 = x >> 23;
    tnr += 0x8000U + (res2 == res1 ? 0 : 128) ;
  }
  return tnr;
}

int main(void)
{
  unsigned int tnr = test_zero_llrr(0);
  printf("0x%x\n", tnr);

  return tnr % 0xff;
}
```

Expected printout is "0xff00", but after commit a52177421743 ([pull request #177578](https://github.com/llvm/llvm-project/pull/177578)) the test case started to fail like this (when using x86-64 as a target and enabling ubsan):
```
> clang -O2 -fsanitize=undefined -fno-sanitize-recover=undefined test.c -o a.out
> ./a.out
0xff0f
```

I'm not quite sure if #177578 is to blame for this, or if instruction selection just is a victim for earlier misbehavior in the front/middle end.

One thing I've noticed is that the "idbi" function result in IR such as:
```
  %3 = alloca i121, align 8
  ...
  %12 = trunc i128 %11 to i121
  store i121 %12, ptr %3, align 8
  %13 = load { i64, i64 }, ptr %3, align 8
  ret { i64, i64 } %13
```
which looks a bit suspicious. It stores an i121 and then loads { i64, i64 }.

This example show that changing the store to an i128 store would avoid the miscompile: https://godbolt.org/z/vabnsc11r

Maybe the real problem is a bit more related to commit 9ad72df55cb74b291932 ([#91364](https://github.com/llvm/llvm-project/pull/91364)), which changed a lot around ABI lowering to no longer use the non-byte-sized types. Here we still use i121 for the temporary return value alloca.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to