diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1180,6 +1180,13 @@ for (auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv2f64}) { + for (auto InnerVT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, + MVT::nxv2f32, MVT::nxv4f32, MVT::nxv2f64}) { + // Avoid marking truncating FP stores as legal to prevent the + // DAGCombiner from creating unsupported truncating stores. + setTruncStoreAction(VT, InnerVT, Expand); + } + setOperationAction(ISD::CONCAT_VECTORS, VT, Custom); setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom); setOperationAction(ISD::MGATHER, VT, Custom); diff --git a/llvm/test/CodeGen/AArch64/sve-fptrunc-store.ll b/llvm/test/CodeGen/AArch64/sve-fptrunc-store.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-fptrunc-store.ll @@ -0,0 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64--linux-gnu -mattr=+sve < %s | FileCheck %s + +define void @fptrunc2_f64_f32( *%dst, *%src) { +; CHECK-LABEL: fptrunc2_f64_f32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: ld1d { z0.d }, p0/z, [x1] +; CHECK-NEXT: fcvt z0.s, p0/m, z0.d +; CHECK-NEXT: st1w { z0.d }, p0, [x0] +; CHECK-NEXT: ret +entry: + %0 = load , * %src, align 8 + %1 = fptrunc %0 to + store %1, * %dst, align 4 + ret void +} + +define void @fptrunc2_f64_f16( *%dst, *%src) { +; CHECK-LABEL: fptrunc2_f64_f16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: ld1d { z0.d }, p0/z, [x1] +; CHECK-NEXT: fcvt z0.h, p0/m, z0.d +; CHECK-NEXT: st1h { z0.d }, p0, [x0] +; CHECK-NEXT: ret +entry: + %0 = load , * %src, align 8 + %1 = fptrunc %0 to + store %1, * %dst, align 2 + ret void +} + +define void @fptrunc4_f32_f16( *%dst, *%src) { +; CHECK-LABEL: fptrunc4_f32_f16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: ld1w { z0.s }, p0/z, [x1] +; CHECK-NEXT: fcvt z0.h, p0/m, z0.s +; CHECK-NEXT: st1h { z0.s }, p0, [x0] +; CHECK-NEXT: ret +entry: + %0 = load , * %src, align 8 + %1 = fptrunc %0 to + store %1, * %dst, align 2 + ret void +} + +define void @fptrunc2_f32_f16( *%dst, *%src) { +; CHECK-LABEL: fptrunc2_f32_f16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: ld1w { z0.d }, p0/z, [x1] +; CHECK-NEXT: fcvt z0.h, p0/m, z0.s +; CHECK-NEXT: st1h { z0.d }, p0, [x0] +; CHECK-NEXT: ret +entry: + %0 = load , * %src, align 8 + %1 = fptrunc %0 to + store %1, * %dst, align 2 + ret void +}