diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -4803,6 +4803,13 @@ return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, Step2); } + // Try and extract from a widened type. + if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) { + SDValue Ops[] = {GetWidenedVector(InOp0), BaseIdx}; + SDValue Ext = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N), OutVT, Ops); + return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, Ext); + } + // Promote operands and see if this is handled by target lowering, // Otherwise, use the BUILD_VECTOR approach below if (getTypeAction(InVT) == TargetLowering::TypePromoteInteger) { diff --git a/llvm/test/CodeGen/AArch64/sve-extract-vector.ll b/llvm/test/CodeGen/AArch64/sve-extract-vector.ll --- a/llvm/test/CodeGen/AArch64/sve-extract-vector.ll +++ b/llvm/test/CodeGen/AArch64/sve-extract-vector.ll @@ -550,6 +550,87 @@ ret %res } +; +; Extracting illegal vector that needs promotion from a vector that needs widening. +; + +define @extract_nxv2i8_nxv14i8_0( %vec) { +; CHECK-LABEL: extract_nxv2i8_nxv14i8_0: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.h, z0.b +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: uunpklo z0.d, z0.s +; CHECK-NEXT: ret + %res = call @llvm.experimental.vector.extract.nxv2i8.nxv14i8( %vec, i64 0) + ret %res +} + +define @extract_nxv2i8_nxv14i8_2( %vec) { +; CHECK-LABEL: extract_nxv2i8_nxv14i8_2: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.h, z0.b +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: uunpkhi z0.d, z0.s +; CHECK-NEXT: ret + %res = call @llvm.experimental.vector.extract.nxv2i8.nxv14i8( %vec, i64 2) + ret %res +} + +define @extract_nxv2i8_nxv14i8_4( %vec) { +; CHECK-LABEL: extract_nxv2i8_nxv14i8_4: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.h, z0.b +; CHECK-NEXT: uunpkhi z0.s, z0.h +; CHECK-NEXT: uunpklo z0.d, z0.s +; CHECK-NEXT: ret + %res = call @llvm.experimental.vector.extract.nxv2i8.nxv14i8( %vec, i64 4) + ret %res +} + +define @extract_nxv2i8_nxv14i8_6( %vec) { +; CHECK-LABEL: extract_nxv2i8_nxv14i8_6: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z0.h, z0.b +; CHECK-NEXT: uunpkhi z0.s, z0.h +; CHECK-NEXT: uunpkhi z0.d, z0.s +; CHECK-NEXT: ret + %res = call @llvm.experimental.vector.extract.nxv2i8.nxv14i8( %vec, i64 6) + ret %res +} + +define @extract_nxv2i8_nxv14i8_8( %vec) { +; CHECK-LABEL: extract_nxv2i8_nxv14i8_8: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpkhi z0.h, z0.b +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: uunpklo z0.d, z0.s +; CHECK-NEXT: ret + %res = call @llvm.experimental.vector.extract.nxv2i8.nxv14i8( %vec, i64 8) + ret %res +} + +define @extract_nxv2i8_nxv14i8_10( %vec) { +; CHECK-LABEL: extract_nxv2i8_nxv14i8_10: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpkhi z0.h, z0.b +; CHECK-NEXT: uunpklo z0.s, z0.h +; CHECK-NEXT: uunpkhi z0.d, z0.s +; CHECK-NEXT: ret + %res = call @llvm.experimental.vector.extract.nxv2i8.nxv14i8( %vec, i64 10) + ret %res +} + +define @extract_nxv2i8_nxv14i8_12( %vec) { +; CHECK-LABEL: extract_nxv2i8_nxv14i8_12: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpkhi z0.h, z0.b +; CHECK-NEXT: uunpkhi z0.s, z0.h +; CHECK-NEXT: uunpklo z0.d, z0.s +; CHECK-NEXT: ret + %res = call @llvm.experimental.vector.extract.nxv2i8.nxv14i8( %vec, i64 12) + ret %res +} + attributes #0 = { vscale_range(2,2) } declare <2 x i64> @llvm.experimental.vector.extract.v2i64.nxv2i64(, i64) @@ -567,3 +648,4 @@ declare @llvm.experimental.vector.extract.nxv4i1.nxv16i1(, i64) declare @llvm.experimental.vector.extract.nxv2i8.nxv32i8( , i64) +declare @llvm.experimental.vector.extract.nxv2i8.nxv14i8( , i64)