diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -5712,11 +5712,12 @@ SDLoc dl(N); // Check if we can convert between two legal vector types and extract. - unsigned InWidenSize = InWidenVT.getSizeInBits(); - unsigned Size = VT.getSizeInBits(); + TypeSize InWidenSize = InWidenVT.getSizeInBits(); + TypeSize Size = VT.getSizeInBits(); // x86mmx is not an acceptable vector element type, so don't try. - if (InWidenSize % Size == 0 && !VT.isVector() && VT != MVT::x86mmx) { - unsigned NewNumElts = InWidenSize / Size; + if (!VT.isVector() && VT != MVT::x86mmx && + InWidenSize.hasKnownScalarFactor(Size)) { + unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size); EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts); if (TLI.isTypeLegal(NewVT)) { SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp); @@ -5731,9 +5732,11 @@ // having to copy via memory. if (VT.isVector()) { EVT EltVT = VT.getVectorElementType(); - unsigned EltSize = EltVT.getSizeInBits(); - if (InWidenSize % EltSize == 0) { - unsigned NewNumElts = InWidenSize / EltSize; + unsigned EltSize = EltVT.getFixedSizeInBits(); + if (InWidenSize.isKnownMultipleOf(EltSize)) { + ElementCount NewNumElts = + (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits()) + .divideCoefficientBy(EltSize); EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts); if (TLI.isTypeLegal(NewVT)) { SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp); diff --git a/llvm/test/CodeGen/AArch64/sve-bitcast.ll b/llvm/test/CodeGen/AArch64/sve-bitcast.ll --- a/llvm/test/CodeGen/AArch64/sve-bitcast.ll +++ b/llvm/test/CodeGen/AArch64/sve-bitcast.ll @@ -874,7 +874,14 @@ ret %bc } -; @bitcast_nxv1i64_to_nxv4f16 is missing +define @bitcast_nxv1i64_to_nxv4f16( %v) #0 { +; CHECK-LABEL: bitcast_nxv1i64_to_nxv4f16: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} define @bitcast_nxv2f32_to_nxv4f16( %v) #0 { ; CHECK-LABEL: bitcast_nxv2f32_to_nxv4f16: @@ -892,7 +899,14 @@ ret %bc } -; @bitcast_nxv1f64_to_nxv4f16 is missing +define @bitcast_nxv1f64_to_nxv4f16( %v) #0 { +; CHECK-LABEL: bitcast_nxv1f64_to_nxv4f16: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} define @bitcast_nxv4bf16_to_nxv4f16( %v) #0 { ; CHECK-LABEL: bitcast_nxv4bf16_to_nxv4f16: @@ -946,7 +960,14 @@ ret %bc } -; @bitcast_nxv1i64_to_nxv2f32 is missing +define @bitcast_nxv1i64_to_nxv2f32( %v) #0 { +; CHECK-LABEL: bitcast_nxv1i64_to_nxv2f32: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.d, z0.s +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} define @bitcast_nxv4f16_to_nxv2f32( %v) #0 { ; CHECK-LABEL: bitcast_nxv4f16_to_nxv2f32: @@ -964,7 +985,14 @@ ret %bc } -; @bitcast_nxv1f64_to_nxv2f32 is missing +define @bitcast_nxv1f64_to_nxv2f32( %v) #0 { +; CHECK-LABEL: bitcast_nxv1f64_to_nxv2f32: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.d, z0.s +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} define @bitcast_nxv4bf16_to_nxv2f32( %v) #0 { ; CHECK-LABEL: bitcast_nxv4bf16_to_nxv2f32: @@ -986,13 +1014,67 @@ ; bitcast to nxv1f64 ; -; @bitcast_nxv8i8_to_nxv1f64 is missing -; @bitcast_nxv4i16_to_nxv1f64 is missing -; @bitcast_nxv2i32_to_nxv1f64 is missing -; @bitcast_nxv1i64_to_nxv1f64 is missing -; @bitcast_nxv4f16_to_nxv1f64 is missing -; @bitcast_nxv2f32_to_nxv1f64 is missing -; @bitcast_nxv4bf16_to_nxv1f64 is missing +define @bitcast_nxv8i8_to_nxv1f64( %v) #0 { +; CHECK-LABEL: bitcast_nxv8i8_to_nxv1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.b, z0.b, z0.b +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} + +define @bitcast_nxv4i16_to_nxv1f64( %v) #0 { +; CHECK-LABEL: bitcast_nxv4i16_to_nxv1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} + +define @bitcast_nxv2i32_to_nxv1f64( %v) #0 { +; CHECK-LABEL: bitcast_nxv2i32_to_nxv1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} + +define @bitcast_nxv1i64_to_nxv1f64( %v) #0 { +; CHECK-LABEL: bitcast_nxv1i64_to_nxv1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} + +define @bitcast_nxv4f16_to_nxv1f64( %v) #0 { +; CHECK-LABEL: bitcast_nxv4f16_to_nxv1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} + +define @bitcast_nxv2f32_to_nxv1f64( %v) #0 { +; CHECK-LABEL: bitcast_nxv2f32_to_nxv1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.s, z0.s, z0.s +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} + +define @bitcast_nxv4bf16_to_nxv1f64( %v) #0 { +; CHECK-LABEL: bitcast_nxv4bf16_to_nxv1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.h, z0.h, z0.h +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} ; ; bitcast to nxv4bf16 @@ -1038,7 +1120,14 @@ ret %bc } -; @bitcast_nxv1i64_to_nxv4bf16 is missing +define @bitcast_nxv1i64_to_nxv4bf16( %v) #0 { +; CHECK-LABEL: bitcast_nxv1i64_to_nxv4bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} define @bitcast_nxv4f16_to_nxv4bf16( %v) #0 { ; CHECK-LABEL: bitcast_nxv4f16_to_nxv4bf16: @@ -1064,7 +1153,14 @@ ret %bc } -; @bitcast_nxv1f64_to_nxv4bf16 is missing +define @bitcast_nxv1f64_to_nxv4bf16( %v) #0 { +; CHECK-LABEL: bitcast_nxv1f64_to_nxv4bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: ret + %bc = bitcast %v to + ret %bc +} ; ; bitcast to nxv4i8 @@ -1275,6 +1371,16 @@ ret %bc } +; +; bitcast to nxv1f32 +; + +; @bitcast_nxv4i8_to_nxv1f32 is missing +; @bitcast_nxv2i16_to_nxv1f32 is missing +; @bitcast_nxv1i32_to_nxv1f32 is missing +; @bitcast_nxv2f16_to_nxv1f32 is missing +; @bitcast_nxv2bf16_to_nxv1f32 is missing + ; ; bitcast to nxv2bf16 ; @@ -1351,6 +1457,22 @@ ; @bitcast_nxv1f16_to_nxv1i16 is missing ; @bitcast_nxv1bf16_to_nxv1i16 is missing +; +; bitcast to nxv1f16 +; + +; @bitcast_nxv2i8_to_nxv1f16 is missing +; @bitcast_nxv1i16_to_nxv1f16 is missing +; @bitcast_nxv1bf16_to_nxv1f16 is missing + +; +; bitcast to nxv1bf16 +; + +; @bitcast_nxv2i8_to_nxv1bf16 is missing +; @bitcast_nxv1i16_to_nxv1bf16 is missing +; @bitcast_nxv1f16_to_nxv1bf16 is missing + ; ; Other ;