Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -4557,8 +4557,8 @@ EVT VT = Op.getValueType(); // If SVE is available then i64 vector multiplications can also be made legal. - bool OverrideNEON = VT == MVT::v2i64 || VT == MVT::v1i64 || - Subtarget->forceStreamingCompatibleSVE(); + bool OverrideNEON = + VT == MVT::v1i64 || Subtarget->forceStreamingCompatibleSVE(); if (VT.isScalableVector() || useSVEForFixedLengthVectorVT(VT, OverrideNEON)) return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED); @@ -4574,10 +4574,14 @@ unsigned NewOpc = selectUmullSmull(N0, N1, DAG, DL, isMLA); if (!NewOpc) { - if (VT == MVT::v2i64) + if (VT == MVT::v2i64) { + // If SVE is available then i64 vector multiplications can also be made + // legal. + if (useSVEForFixedLengthVectorVT(VT, true)) + return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED); // Fall through to expand this. It is not legal. return SDValue(); - else + } else // Other vector multiplications are legal. return Op; } Index: llvm/test/CodeGen/AArch64/sve-mull.ll =================================================================== --- llvm/test/CodeGen/AArch64/sve-mull.ll +++ llvm/test/CodeGen/AArch64/sve-mull.ll @@ -4,11 +4,7 @@ define <2 x i64> @smull_v2i64(<2 x i32> %op1, <2 x i32> %op2) #0 { ; CHECK-LABEL: smull_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: sshll v0.2d, v0.2s, #0 -; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: sshll v1.2d, v1.2s, #0 -; CHECK-NEXT: mul z0.d, p0/m, z0.d, z1.d -; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 +; CHECK-NEXT: smull v0.2d, v0.2s, v1.2s ; CHECK-NEXT: ret %a = sext <2 x i32> %op1 to <2 x i64> %b = sext <2 x i32> %op2 to <2 x i64> @@ -19,11 +15,7 @@ define <2 x i64> @umull_v2i64(<2 x i32> %op1, <2 x i32> %op2) #0 { ; CHECK-LABEL: umull_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: ushll v0.2d, v0.2s, #0 -; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: ushll v1.2d, v1.2s, #0 -; CHECK-NEXT: mul z0.d, p0/m, z0.d, z1.d -; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 +; CHECK-NEXT: umull v0.2d, v0.2s, v1.2s ; CHECK-NEXT: ret %a = zext <2 x i32> %op1 to <2 x i64> %b = zext <2 x i32> %op2 to <2 x i64> @@ -34,16 +26,9 @@ define <4 x i64> @smull_v4i64(<4 x i32> %op1, <4 x i32> %op2) #0 { ; CHECK-LABEL: smull_v4i64: ; CHECK: // %bb.0: -; CHECK-NEXT: sshll v2.2d, v0.2s, #0 -; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: sshll2 v0.2d, v0.4s, #0 -; CHECK-NEXT: sshll v3.2d, v1.2s, #0 -; CHECK-NEXT: sshll2 v1.2d, v1.4s, #0 -; CHECK-NEXT: mul z1.d, p0/m, z1.d, z0.d -; CHECK-NEXT: movprfx z0, z2 -; CHECK-NEXT: mul z0.d, p0/m, z0.d, z3.d -; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: // kill: def $q1 killed $q1 killed $z1 +; CHECK-NEXT: smull2 v2.2d, v0.4s, v1.4s +; CHECK-NEXT: smull v0.2d, v0.2s, v1.2s +; CHECK-NEXT: mov v1.16b, v2.16b ; CHECK-NEXT: ret %a = sext <4 x i32> %op1 to <4 x i64> %b = sext <4 x i32> %op2 to <4 x i64> @@ -54,16 +39,9 @@ define <4 x i64> @umull_v4i64(<4 x i32> %op1, <4 x i32> %op2) #0 { ; CHECK-LABEL: umull_v4i64: ; CHECK: // %bb.0: -; CHECK-NEXT: ushll v2.2d, v0.2s, #0 -; CHECK-NEXT: ptrue p0.d, vl2 -; CHECK-NEXT: ushll2 v0.2d, v0.4s, #0 -; CHECK-NEXT: ushll v3.2d, v1.2s, #0 -; CHECK-NEXT: ushll2 v1.2d, v1.4s, #0 -; CHECK-NEXT: mul z1.d, p0/m, z1.d, z0.d -; CHECK-NEXT: movprfx z0, z2 -; CHECK-NEXT: mul z0.d, p0/m, z0.d, z3.d -; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: // kill: def $q1 killed $q1 killed $z1 +; CHECK-NEXT: umull2 v2.2d, v0.4s, v1.4s +; CHECK-NEXT: umull v0.2d, v0.2s, v1.2s +; CHECK-NEXT: mov v1.16b, v2.16b ; CHECK-NEXT: ret %a = zext <4 x i32> %op1 to <4 x i64> %b = zext <4 x i32> %op2 to <4 x i64>