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 @@ -17462,6 +17462,21 @@ return DAG.getNode(N0.getOpcode(), SDLoc(N), VT, Op); } + // (v2i32 trunc (v2i64 concat_vectors x, undef)) -> (bitcast x, v2i32) + if (N0.getOpcode() == ISD::CONCAT_VECTORS && N0.getValueType() == MVT::v2i64) { + bool AllButFirstUndef = true; + for (unsigned i = 1, e = N0.getNumOperands(); i < e; ++i) { + if (!N0.getOperand(i).isUndef()) { + AllButFirstUndef = false; + break; + } + } + + if (AllButFirstUndef) { + return DAG.getNode(ISD::BITCAST, SDLoc(N), VT, N0.getOperand(0)); + } + } + return SDValue(); } diff --git a/llvm/test/CodeGen/AArch64/trunc-v1i64.ll b/llvm/test/CodeGen/AArch64/trunc-v1i64.ll --- a/llvm/test/CodeGen/AArch64/trunc-v1i64.ll +++ b/llvm/test/CodeGen/AArch64/trunc-v1i64.ll @@ -8,12 +8,9 @@ ; scalarization will cause an assertion failure, as v1i64 is a legal type in ; AArch64. We change the default behaviour from be scalarized to be widen. -; FIXME: Currently XTN is generated for v1i32, but it can be optimized. -; Just like v1i16 and v1i8, there is no XTN generated. - define <2 x i32> @test_v1i32_0(<1 x i64> %in0) { ; CHECK-LABEL: test_v1i32_0: -; CHECK: xtn v0.2s, v0.2d +; CHECK-NOT: xtn %1 = shufflevector <1 x i64> %in0, <1 x i64> undef, <2 x i32> %2 = trunc <2 x i64> %1 to <2 x i32> ret <2 x i32> %2