llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.81k stars 11.91k forks source link

RISCV64 vector miscompile at -O2 #80910

Closed patrick-rivos closed 8 months ago

patrick-rivos commented 8 months ago

Testcase:

int printf(const char *, ...);
int b, e, z, v, h;
short i, j;
int *k = &b;
static int l;
static int *n = &l;
static int o;

static int r() {
  long x = 0;
  signed char y = 0;
  short w = 0;
  *k = 1;
  h = 0;
  n;
  while (h < 2) {
    e = i = 0;
    while (i < 3) {
      j = o << l;
      w = b * 3;
      e ^= j >= 0;
      long q = e;
      x = w & -q ?: w;
      y = x;
      z |= y;
      while (o < 2)
        o += 1;
      i += 1;
    }
    h++;
  }
  return z;
}

int main() {
  v = r();
  printf("%d\n", v);
}

Commands:

> /scratch/tc-testing/llvm-feb-5/build/bin/clang -O2 -march=rv64gcv red.c -o user-config.out -Wno-unused-value
> QEMU_CPU=rv64,Zve32f=true,Zve64f=true /scratch/tc-testing/llvm-feb-5/build/bin/qemu-riscv64 user-config.out
0
> /scratch/tc-testing/llvm-feb-5/build/bin/clang -O1 -march=rv64gcv red.c -o user-config.out -Wno-unused-value
> QEMU_CPU=rv64,Zve32f=true,Zve64f=true /scratch/tc-testing/llvm-feb-5/build/bin/qemu-riscv64 user-config.out
3

.c, .bc, .asm: c-bc-asm.zip

--opt-bisect-limit points to InstCombinePass

Discovered/tested using a7bc9cb6ffa91ff0ebabc45c0c7263c7c2c3a4de (not bisected) Found using fuzzer.

80792 also fails with -march=rv64gcv -O2 so these might be related?

topperc commented 8 months ago

The IR difference before and after InstCombine looks ok to me. So InstCombine may be exposing some bug in the backend.

topperc commented 8 months ago

This looks suspect

Combining: t65: v4i32 = BUILD_VECTOR t8, undef:i64, undef:i64, undef:i64         
Creating new node: t82: v4i32 = BUILD_VECTOR t6, undef:i64, undef:i64, undef:i64 
Creating new node: t83: v4i32 = BUILD_VECTOR Constant:i64<48>, undef:i64, undef:i64, undef:i64
Creating new node: t84: v4i32 = sra t82, t83                                     
 ... into: t84: v4i32 = sra t82, t83 

That shows the v4i32 sra now has a shift value of 48 from t83. That's out of bounds.

topperc commented 8 months ago

Looks like the problem is performBUILD_VECTORCombine in RISCVISelLowering.cpp. If the scalar type is larger than the vector type for the BUILD_VECTOR, the transform is not valid for shifts operations.

preames commented 8 months ago

Reduced test case, fix pending.

; RUN: llc -mtriple=riscv64 -mattr=+v < %s
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define <2 x i32> @bar(i64 %a, i64 %b) {
entry:
  %conv11.i = ashr i64 %a, 1
  %conv11.2 = ashr i64 %b, 1
  %0 = trunc i64 %conv11.i to i32
  %1 = trunc i64 %conv11.2 to i32
  %2 = insertelement <2 x i32> zeroinitializer, i32 %0, i64 0
  %3 = insertelement <2 x i32> %2, i32 %1, i64 1
  ret <2 x i32> %3
}
llvmbot commented 8 months ago

@llvm/issue-subscribers-backend-risc-v

Author: Patrick O'Neill (patrick-rivos)

Testcase: ```c int printf(const char *, ...); int b, e, z, v, h; short i, j; int *k = &b; static int l; static int *n = &l; static int o; static int r() { long x = 0; signed char y = 0; short w = 0; *k = 1; h = 0; n; while (h < 2) { e = i = 0; while (i < 3) { j = o << l; w = b * 3; e ^= j >= 0; long q = e; x = w & -q ?: w; y = x; z |= y; while (o < 2) o += 1; i += 1; } h++; } return z; } int main() { v = r(); printf("%d\n", v); } ``` Commands: ```bash > /scratch/tc-testing/llvm-feb-5/build/bin/clang -O2 -march=rv64gcv red.c -o user-config.out -Wno-unused-value > QEMU_CPU=rv64,Zve32f=true,Zve64f=true /scratch/tc-testing/llvm-feb-5/build/bin/qemu-riscv64 user-config.out 0 > /scratch/tc-testing/llvm-feb-5/build/bin/clang -O1 -march=rv64gcv red.c -o user-config.out -Wno-unused-value > QEMU_CPU=rv64,Zve32f=true,Zve64f=true /scratch/tc-testing/llvm-feb-5/build/bin/qemu-riscv64 user-config.out 3 ``` .c, .bc, .asm: [c-bc-asm.zip](https://github.com/llvm/llvm-project/files/14186745/c-bc-asm.zip) `--opt-bisect-limit` points to `InstCombinePass` Discovered/tested using a7bc9cb6ffa91ff0ebabc45c0c7263c7c2c3a4de (not bisected) Found using fuzzer. #80792 also fails with `-march=rv64gcv -O2` so these might be related?