llvm / llvm-project

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

[AArch64] crash on compiling umaxv/vcvtfxu2fp neon intrinsics, assertion "unexpected vector type" #55606

Closed Benjins closed 2 years ago

Benjins commented 2 years ago

The following IR when compiled via llc for the aarch64 backend will crash or hit in assertion if they're enabled.

Godbolt link

; Compiled with llc --mtriple=aarch64-none-none -O0
; Function Attrs: mustprogress nofree nosync nounwind readnone willreturn uwtable
define dso_local float @do_stuff(<8 x i16> noundef %var_135) local_unnamed_addr #0 {
entry:
  %vmaxv.i = call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> %var_135) #2
  %vcvts_n_f32_u32 = call float @llvm.aarch64.neon.vcvtfxu2fp.f32.i32(i32 %vmaxv.i, i32 1)
  ret float %vcvts_n_f32_u32
}

; Function Attrs: mustprogress nocallback nofree nosync nounwind readnone willreturn
declare float @llvm.aarch64.neon.vcvtfxu2fp.f32.i32(i32, i32) #1

; Function Attrs: mustprogress nocallback nofree nosync nounwind readnone willreturn
declare i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16>) #1

The assertion we get is in tryCombineFixedPointConvert:

unexpected vector type!
UNREACHABLE executed at /root/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp:15076!

Full LLC crash log

The DAG at the point of the assertion:

SelectionDAG has 12 nodes:
  t0: ch = EntryToken
          t2: v8i16,ch = CopyFromReg t0, Register:v8i16 %0
        t14: v8i16 = AArch64ISD::UMAXV t2
      t15: i32 = extract_vector_elt t14, Constant:i64<0>
    t9: f32 = llvm.aarch64.neon.vcvtfxu2fp TargetConstant:i64<627>, t15, Constant:i32<2>
  t11: ch,glue = CopyToReg t0, Register:f32 $s0, t9
  t12: ch = AArch64ISD::RET_FLAG t11, Register:f32 $s0, t11:1

The following is a minimal repro of the error via C++ when compiled with -O1:

Godbolt link

#include <arm_neon.h>
float32_t do_stuff(uint16x8_t Input) {
    uint16_t MaxElem = vmaxvq_u16(Input);
    float32_t MaxAsFloat = vcvts_n_f32_u32(MaxElem, 1);
    return MaxAsFloat;
}

I have verified that this repros on the latest trunk (6e00a34cdb49ba1d4b72ec274e52260da9c52380).

For context: this code was generated by a fuzzer, it was not manually written.

llvmbot commented 2 years ago

@llvm/issue-subscribers-backend-aarch64

fhahn commented 2 years ago

@oToToT I added the backend:AArch64 label. Not sure if it is worth having a separate backend:NEON label, as technically NEON isn't an LLVM backend.

davemgreen commented 2 years ago

Thanks.

This looks like a very similar issue to before, where tryCombineFixedPointConvert has incorrect assumptions about the types of the inputs. I'll put together another patch.