Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -14537,6 +14537,17 @@ } } + // concat(zip1(a, b), zip2(a, b)) is zip1(a, b) + if (N->getNumOperands() == 2 && N0Opc == AArch64ISD::ZIP1 && + N1Opc == AArch64ISD::ZIP2 && N0.getOperand(0) == N1.getOperand(0) && + N0.getOperand(1) == N1.getOperand(1)) { + SDValue E0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, VT, N0.getOperand(0), + DAG.getUNDEF(N0.getValueType())); + SDValue E1 = DAG.getNode(ISD::CONCAT_VECTORS, dl, VT, N0.getOperand(1), + DAG.getUNDEF(N0.getValueType())); + return DAG.getNode(AArch64ISD::ZIP1, dl, VT, E0, E1); + } + // If we see a (concat_vectors (v1x64 A), (v1x64 A)) it's really a vector // splat. The indexed instructions are going to be expecting a DUPLANE64, so // canonicalise to that. Index: llvm/test/CodeGen/AArch64/arm64-zip.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64-zip.ll +++ llvm/test/CodeGen/AArch64/arm64-zip.ll @@ -142,9 +142,9 @@ define <16 x i8> @combine_v16i8(<8 x i8> %0, <8 x i8> %1) { ; CHECK-LABEL: combine_v16i8: ; CHECK: // %bb.0: -; CHECK-NEXT: zip2.8b v2, v0, v1 -; CHECK-NEXT: zip1.8b v0, v0, v1 -; CHECK-NEXT: mov.d v0[1], v2[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: zip1.16b v0, v0, v1 ; CHECK-NEXT: ret %3 = shufflevector <8 x i8> %0, <8 x i8> %1, <16 x i32> ret <16 x i8> %3 @@ -153,10 +153,9 @@ define <16 x i8> @combine2_v16i8(<8 x i8> %0, <8 x i8> %1) { ; CHECK-LABEL: combine2_v16i8: ; CHECK: // %bb.0: -; CHECK-NEXT: zip1.8b v2, v0, v1 -; CHECK-NEXT: zip2.8b v0, v0, v1 -; CHECK-NEXT: mov.d v2[1], v0[0] -; CHECK-NEXT: mov.16b v0, v2 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: zip1.16b v0, v0, v1 ; CHECK-NEXT: ret %3 = shufflevector <8 x i8> %0, <8 x i8> %1, <8 x i32> %4 = shufflevector <8 x i8> %0, <8 x i8> %1, <8 x i32> @@ -167,9 +166,9 @@ define <8 x i16> @combine_v8i16(<4 x i16> %0, <4 x i16> %1) { ; CHECK-LABEL: combine_v8i16: ; CHECK: // %bb.0: -; CHECK-NEXT: zip2.4h v2, v0, v1 -; CHECK-NEXT: zip1.4h v0, v0, v1 -; CHECK-NEXT: mov.d v0[1], v2[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: zip1.8h v0, v0, v1 ; CHECK-NEXT: ret %3 = shufflevector <4 x i16> %0, <4 x i16> %1, <8 x i32> ret <8 x i16> %3 @@ -178,10 +177,9 @@ define <8 x i16> @combine2_v8i16(<4 x i16> %0, <4 x i16> %1) { ; CHECK-LABEL: combine2_v8i16: ; CHECK: // %bb.0: -; CHECK-NEXT: zip1.4h v2, v0, v1 -; CHECK-NEXT: zip2.4h v0, v0, v1 -; CHECK-NEXT: mov.d v2[1], v0[0] -; CHECK-NEXT: mov.16b v0, v2 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: zip1.8h v0, v0, v1 ; CHECK-NEXT: ret %3 = shufflevector <4 x i16> %0, <4 x i16> %1, <4 x i32> %4 = shufflevector <4 x i16> %0, <4 x i16> %1, <4 x i32> @@ -192,9 +190,9 @@ define <4 x i32> @combine_v4i32(<2 x i32> %0, <2 x i32> %1) { ; CHECK-LABEL: combine_v4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: zip2.2s v2, v0, v1 -; CHECK-NEXT: zip1.2s v0, v0, v1 -; CHECK-NEXT: mov.d v0[1], v2[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: zip1.4s v0, v0, v1 ; CHECK-NEXT: ret %3 = shufflevector <2 x i32> %0, <2 x i32> %1, <4 x i32> ret <4 x i32> %3 @@ -203,10 +201,9 @@ define <4 x i32> @combine2_v4i32(<2 x i32> %0, <2 x i32> %1) { ; CHECK-LABEL: combine2_v4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: zip1.2s v2, v0, v1 -; CHECK-NEXT: zip2.2s v0, v0, v1 -; CHECK-NEXT: mov.d v2[1], v0[0] -; CHECK-NEXT: mov.16b v0, v2 +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: zip1.4s v0, v0, v1 ; CHECK-NEXT: ret %3 = shufflevector <2 x i32> %0, <2 x i32> %1, <2 x i32> %4 = shufflevector <2 x i32> %0, <2 x i32> %1, <2 x i32>