Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -16181,6 +16181,30 @@ vector index constant type (for most targets this will be an integer pointer type). +'``llvm.experimental.vector.extract.evens``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. + +:: + + declare <4 x float> @llvm.experimental.vector.extract.evens.v4f32( %vec1, %vec2) + declare <2 x double> @llvm.experimental.vector.extract.evens.v2f64( %vec1, %vec2) + +Overview: +""""""""" + +The '``llvm.experimental.vector.extract.evens.*``' intrinsic extracts a vector +of even elements from a pair of input vectors. The result type matches the type +of the input vectors. + +Arguments: +"""""""""" + +The arguments to this intrinsic must be vectors of the same type. + Matrix Intrinsics ----------------- Index: llvm/include/llvm/CodeGen/ISDOpcodes.h =================================================================== --- llvm/include/llvm/CodeGen/ISDOpcodes.h +++ llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -540,6 +540,11 @@ /// vector, but not the other way around. EXTRACT_SUBVECTOR, + /// EXTRACT_EVENS_VECTOR(VEC1, VEC2) - Returns a vector of all the even + /// elements from VEC1 and VEC2. The result vector type will match the input + /// vector type. Both input vectors must have the same type. + EXTRACT_EVENS_VECTOR, + /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int /// values that indicate which value (or undef) each result element will Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ llvm/include/llvm/IR/Intrinsics.td @@ -1633,8 +1633,9 @@ def int_experimental_vector_extract : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i64_ty], [IntrNoMem, ImmArg>]>; - -//===----------------------------------------------------------------------===// +def int_experimental_vector_extract_evens : DefaultAttrsIntrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; //===----------------------------------------------------------------------===// // Target-specific intrinsics Index: llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -96,6 +96,8 @@ case ISD::EXTRACT_SUBVECTOR: Res = PromoteIntRes_EXTRACT_SUBVECTOR(N); break; + case ISD::EXTRACT_EVENS_VECTOR: + Res = PromoteIntRes_EXTRACT_EVENS_VECTOR(N); break; case ISD::VECTOR_SHUFFLE: Res = PromoteIntRes_VECTOR_SHUFFLE(N); break; case ISD::INSERT_VECTOR_ELT: @@ -4648,6 +4650,14 @@ return DAG.getBuildVector(NOutVT, dl, Ops); } +SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_EVENS_VECTOR(SDNode *N) { + SDLoc dl(N); + SDValue V0 = GetPromotedInteger(N->getOperand(0)); + SDValue V1 = GetPromotedInteger(N->getOperand(1)); + EVT OutVT = V0.getValueType(); + + return DAG.getNode(ISD::EXTRACT_EVENS_VECTOR, dl, OutVT, V0, V1); +} SDValue DAGTypeLegalizer::PromoteIntRes_VECTOR_SHUFFLE(SDNode *N) { ShuffleVectorSDNode *SV = cast(N); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -298,6 +298,7 @@ SDValue PromoteIntRes_Atomic1(AtomicSDNode *N); SDValue PromoteIntRes_AtomicCmpSwap(AtomicSDNode *N, unsigned ResNo); SDValue PromoteIntRes_EXTRACT_SUBVECTOR(SDNode *N); + SDValue PromoteIntRes_EXTRACT_EVENS_VECTOR(SDNode *N); SDValue PromoteIntRes_VECTOR_SHUFFLE(SDNode *N); SDValue PromoteIntRes_BUILD_VECTOR(SDNode *N); SDValue PromoteIntRes_SCALAR_TO_VECTOR(SDNode *N); @@ -825,6 +826,7 @@ void SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_EXTRACT_EVENS_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_FCOPYSIGN(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -910,6 +910,9 @@ case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break; case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break; case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break; + case ISD::EXTRACT_EVENS_VECTOR: + SplitVecRes_EXTRACT_EVENS_VECTOR(N, Lo, Hi); + break; case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; case ISD::FCOPYSIGN: SplitVecRes_FCOPYSIGN(N, Lo, Hi); break; case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; @@ -1304,6 +1307,20 @@ PtrInfo.getWithOffset(IncrementSize), SmallestAlign); } +void DAGTypeLegalizer::SplitVecRes_EXTRACT_EVENS_VECTOR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDLoc dl(N); + SDValue Src1Lo, Src1Hi; + GetSplitVector(N->getOperand(0), Src1Lo, Src1Hi); + SDValue Src2Lo, Src2Hi; + GetSplitVector(N->getOperand(1), Src2Lo, Src2Hi); + + Lo = DAG.getNode(ISD::EXTRACT_EVENS_VECTOR, dl, Src1Lo.getValueType(), + Src1Lo, Src2Lo); + Hi = DAG.getNode(ISD::EXTRACT_EVENS_VECTOR, dl, Src1Hi.getValueType(), + Src1Hi, Src2Hi); +} + void DAGTypeLegalizer::SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, SDValue &Hi) { SDLoc dl(N); Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6976,6 +6976,31 @@ setValue(&I, DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, ResultVT, Vec, Index)); return; } + case Intrinsic::experimental_vector_extract_evens: { + auto DL = getCurSDLoc(); + + SDValue Src1 = getValue(I.getOperand(0)); + SDValue Src2 = getValue(I.getOperand(1)); + EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType()); + + if (VT.isScalableVector()) { + setValue(&I, DAG.getNode(ISD::EXTRACT_EVENS_VECTOR, DL, VT, Src1, Src2)); + return; + } + + assert(VT.isFixedLengthVector() && + "Unexpected scalable vector in vector_extract_evens!"); + + // If a FixedLengthVector, canonicalize to a SHUFFLE_VECTOR with even + // mask indicies. + unsigned NumElts = VT.getVectorElementCount().getKnownMinValue(); + SmallVector Mask(NumElts, -1); + for (unsigned i = 0; i < NumElts; ++i) + Mask[i] = i*2; + + setValue(&I, DAG.getVectorShuffle(VT, DL, Src1, Src2, Mask)); + return; + } } } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -286,6 +286,7 @@ case ISD::CONCAT_VECTORS: return "concat_vectors"; case ISD::INSERT_SUBVECTOR: return "insert_subvector"; case ISD::EXTRACT_SUBVECTOR: return "extract_subvector"; + case ISD::EXTRACT_EVENS_VECTOR: return "extract_evens_vector"; case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector"; case ISD::VECTOR_SHUFFLE: return "vector_shuffle"; case ISD::SPLAT_VECTOR: return "splat_vector"; Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -5163,6 +5163,21 @@ &Call); break; } + case Intrinsic::experimental_vector_extract_evens: { + VectorType *ResultTy = cast(Call.getType()); + VectorType *Op1Ty = cast(Call.getArgOperand(0)->getType()); + VectorType *Op2Ty = cast(Call.getArgOperand(1)->getType()); + + Assert(ResultTy == Op1Ty, + "experimental_vector_extract_evens result must have the same " + "type as the input vectors.", + &Call); + Assert(Op1Ty == Op2Ty, + "experimental_vector_extract_evens operands must have the same " + "type.", + &Call); + break; + } }; } Index: llvm/lib/Target/AArch64/AArch64ISelLowering.h =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -932,6 +932,7 @@ SDValue LowerWindowsDYNAMIC_STACKALLOC(SDValue Op, SDValue Chain, SDValue &Size, SelectionDAG &DAG) const; + SDValue LowerExtractEvensVector(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSVEStructLoad(unsigned Intrinsic, ArrayRef LoadOps, EVT VT, SelectionDAG &DAG, const SDLoc &DL) const; Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1105,6 +1105,7 @@ setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom); setOperationAction(ISD::VECREDUCE_SMIN, VT, Custom); setOperationAction(ISD::VECREDUCE_SMAX, VT, Custom); + setOperationAction(ISD::EXTRACT_EVENS_VECTOR, VT, Custom); } // Illegal unpacked integer vector types. @@ -1134,6 +1135,7 @@ MVT::nxv4f32, MVT::nxv2f64}) { setOperationAction(ISD::CONCAT_VECTORS, VT, Custom); setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom); + setOperationAction(ISD::EXTRACT_EVENS_VECTOR, VT, Custom); setOperationAction(ISD::MGATHER, VT, Custom); setOperationAction(ISD::MSCATTER, VT, Custom); setOperationAction(ISD::SPLAT_VECTOR, VT, Custom); @@ -4413,6 +4415,8 @@ /*OverrideNEON=*/true); case ISD::CTTZ: return LowerCTTZ(Op, DAG); + case ISD::EXTRACT_EVENS_VECTOR: + return LowerExtractEvensVector(Op, DAG); } } @@ -7358,6 +7362,18 @@ return DAG.getMergeValues(Ops, dl); } +SDValue AArch64TargetLowering::LowerExtractEvensVector(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + EVT VT = Op.getValueType(); + assert(VT.isScalableVector() && + "Unexpected fixed length vector in LowerExtractEvensVector!"); + + SDValue Src1 = Op.getOperand(0); + SDValue Src2 = Op.getOperand(1); + return DAG.getNode(AArch64ISD::UZP1, DL, VT, Src1, Src2); +} + bool AArch64TargetLowering::isOffsetFoldingLegal( const GlobalAddressSDNode *GA) const { // Offsets are folded in the DAG combine rather than here so that we can Index: llvm/test/CodeGen/AArch64/sve-extract-evens-vector.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/sve-extract-evens-vector.ll @@ -0,0 +1,220 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve < %s 2>%t | FileCheck %s --check-prefixes=CHECK +; RUN: FileCheck --check-prefix=WARN --allow-empty %s < %t + +; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it. +; WARN-NOT: warning + +;; Legal integer types + +define <16 x i8> @extract_evens_v16i8(<16 x i8> %vec1, <16 x i8> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v16i8: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret +%retval = call <16 x i8> @llvm.experimental.vector.extract.evens.v16i8(<16 x i8> %vec1, <16 x i8> %vec2) +ret <16 x i8> %retval +} + +define <8 x i16> @extract_evens_v8i16(<8 x i16> %vec1, <8 x i16> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v8i16: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-NEXT: ret +%retval = call <8 x i16> @llvm.experimental.vector.extract.evens.v8i16(<8 x i16> %vec1, <8 x i16> %vec2) +ret <8 x i16> %retval +} + +define <4 x i32> @extract_evens_v4i32(<4 x i32> %vec1, <4 x i32> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: ret +%retval = call <4 x i32> @llvm.experimental.vector.extract.evens.v4i32(<4 x i32> %vec1, <4 x i32> %vec2) +ret <4 x i32> %retval +} + +; NOTE: Uses ZIP1 since it's only a 2 element vector. +define <2 x i64> @extract_evens_v2i64(<2 x i64> %vec1, <2 x i64> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v2i64: +; CHECK: // %bb.0: +; CHECK-NEXT: zip1 v0.2d, v0.2d, v1.2d +; CHECK-NEXT: ret +%retval = call <2 x i64> @llvm.experimental.vector.extract.evens.v2i64(<2 x i64> %vec1, <2 x i64> %vec2) +ret <2 x i64> %retval +} + +define @extract_evens_nxv16i8( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv16i8: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.b, z0.b, z1.b +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv16i8( %vec1, %vec2) +ret %retval +} + +define @extract_evens_nxv8i16( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv8i16: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.h, z0.h, z1.h +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv8i16( %vec1, %vec2) +ret %retval +} + +define @extract_evens_nxv4i32( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.s, z0.s, z1.s +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv4i32( %vec1, %vec2) +ret %retval +} + +define @extract_evens_nxv2i64( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv2i64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.d, z0.d, z1.d +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv2i64( %vec1, %vec2) +ret %retval +} + +;; Illegal integer types + +define @extract_evens_nxv2i32_promote( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv2i32_promote: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.d, z0.d, z1.d +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv2i32( %vec1, %vec2) +ret %retval +} + +define @extract_evens_nxv4i64_split( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv4i64_split: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.d, z0.d, z2.d +; CHECK-NEXT: uzp1 z1.d, z1.d, z3.d +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv4i64( %vec1, %vec2) +ret %retval +} + + +;; Legal floating point types + +define <8 x half> @extract_evens_v8f16(<8 x half> %vec1, <8 x half> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v8f16: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-NEXT: ret +%retval = call <8 x half> @llvm.experimental.vector.extract.evens.v8f16(<8 x half> %vec1, <8 x half> %vec2) +ret <8 x half> %retval +} + +; NOTE: Uses ZIP1 since it's only a 2 element vector. +define <2 x float> @extract_evens_v2f32(<2 x float> %vec1, <2 x float> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v2f32: +; CHECK: // %bb.0: +; CHECK-NEXT: zip1 v0.2s, v0.2s, v1.2s +; CHECK-NEXT: ret +%retval = call <2 x float> @llvm.experimental.vector.extract.evens.v2f32(<2 x float> %vec1, <2 x float> %vec2) +ret <2 x float> %retval +} + +define <4 x float> @extract_evens_v4f32(<4 x float> %vec1, <4 x float> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v4f32: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: ret +%retval = call <4 x float> @llvm.experimental.vector.extract.evens.v4f32(<4 x float> %vec1, <4 x float> %vec2) +ret <4 x float> %retval +} + +; NOTE: Uses ZIP1 since it's only a 2 element vector. +define <2 x double> @extract_evens_v2f64(<2 x double> %vec1, <2 x double> %vec2) nounwind { +; CHECK-LABEL: extract_evens_v2f64: +; CHECK: // %bb.0: +; CHECK-NEXT: zip1 v0.2d, v0.2d, v1.2d +; CHECK-NEXT: ret +%retval = call <2 x double> @llvm.experimental.vector.extract.evens.v2f64(<2 x double> %vec1, <2 x double> %vec2) +ret <2 x double> %retval +} + +define @extract_evens_nxv8f16( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv8f16: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.h, z0.h, z1.h +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv8f16( %vec1, %vec2) +ret %retval +} + +define @extract_evens_nxv2f32( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv2f32: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.d, z0.d, z1.d +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv2f32( %vec1, %vec2) +ret %retval +} + +define @extract_evens_nxv4f32( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv4f32: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.s, z0.s, z1.s +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv4f32( %vec1, %vec2) +ret %retval +} + +define @extract_evens_nxv2f64( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv2f64: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.d, z0.d, z1.d +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv2f64( %vec1, %vec2) +ret %retval +} + +;; Illegal floating point types + +define @extract_evens_nxv4f64_split( %vec1, %vec2) nounwind { +; CHECK-LABEL: extract_evens_nxv4f64_split: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 z0.d, z0.d, z2.d +; CHECK-NEXT: uzp1 z1.d, z1.d, z3.d +; CHECK-NEXT: ret +%retval = call @llvm.experimental.vector.extract.evens.nxv4f64( %vec1, %vec2) +ret %retval +} + + +; Legal integer declarations +declare <16 x i8> @llvm.experimental.vector.extract.evens.v16i8(<16 x i8>, <16 x i8>) +declare <8 x i16> @llvm.experimental.vector.extract.evens.v8i16(<8 x i16>, <8 x i16>) +declare <4 x i32> @llvm.experimental.vector.extract.evens.v4i32(<4 x i32>, <4 x i32>) +declare <2 x i64> @llvm.experimental.vector.extract.evens.v2i64(<2 x i64>, <2 x i64>) +declare @llvm.experimental.vector.extract.evens.nxv16i8(, ) +declare @llvm.experimental.vector.extract.evens.nxv8i16(, ) +declare @llvm.experimental.vector.extract.evens.nxv4i32(, ) +declare @llvm.experimental.vector.extract.evens.nxv2i64(, ) + +; Illegal integer declarations +declare @llvm.experimental.vector.extract.evens.nxv2i32(, ) +declare @llvm.experimental.vector.extract.evens.nxv4i64(, ) + +; Legal floating point declarations +declare <8 x half> @llvm.experimental.vector.extract.evens.v8f16(<8 x half>, <8 x half>) +declare <2 x float> @llvm.experimental.vector.extract.evens.v2f32(<2 x float>, <2 x float>) +declare <4 x float> @llvm.experimental.vector.extract.evens.v4f32(<4 x float>, <4 x float>) +declare <2 x double> @llvm.experimental.vector.extract.evens.v2f64(<2 x double>, <2 x double>) +declare @llvm.experimental.vector.extract.evens.nxv8f16(, ) +declare @llvm.experimental.vector.extract.evens.nxv2f32(, ) +declare @llvm.experimental.vector.extract.evens.nxv4f32(, ) +declare @llvm.experimental.vector.extract.evens.nxv2f64(, ) + +; Illegal floating point declarations +declare @llvm.experimental.vector.extract.evens.nxv4f64(, ) + +