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 @@ -14109,6 +14109,9 @@ SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); unsigned N0Opc = N0->getOpcode(), N1Opc = N1->getOpcode(); + if (VT.isScalableVector()) + return SDValue(); + // Optimize concat_vectors of truncated vectors, where the intermediate // type is illegal, to avoid said illegality, e.g., // (v4i16 (concat_vectors (v2i16 (truncate (v2i64))), diff --git a/llvm/test/CodeGen/AArch64/concat_vector-truncate-combine.ll b/llvm/test/CodeGen/AArch64/concat_vector-truncate-combine.ll --- a/llvm/test/CodeGen/AArch64/concat_vector-truncate-combine.ll +++ b/llvm/test/CodeGen/AArch64/concat_vector-truncate-combine.ll @@ -40,4 +40,24 @@ ret <8 x i16> %shuffle } + +; The concat_vectors operation in this test is introduced when splitting +; the fptrunc operation due to the split input operand. +define void @test_concat_fptrunc_v4f64_to_v4f32(* %ptr) #1 { +entry: +; CHECK-LABEL: test_concat_fptrunc_v4f64_to_v4f32: +; CHECK: fmov z0.d, #1.00000000 +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: fcvt z0.s, p0/m, z0.d +; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s +; CHECK-NEXT: st1w { z0.s }, p0, [x0] +; CHECK-NEXT: ret + %0 = shufflevector insertelement ( poison, double 1.000000e+00, i32 0), poison, zeroinitializer + %1 = fptrunc %0 to + store %1, * %ptr, align 4 + ret void +} + attributes #0 = { nounwind } +attributes #1 = { "target-features"="+sve" }