Skip to content

Commit e2affa3

Browse files
[LLVM][CodeGen][SVE] Improve custom lowering for EXTRACT_SUBVECTOR.
We can extract any legal fixed length vector from a scalable vector by using VECTOR_SPLICE.
1 parent b277bf5 commit e2affa3

File tree

4 files changed

+77
-202
lines changed

4 files changed

+77
-202
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13856,45 +13856,52 @@ AArch64TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
1385613856

1385713857
SDValue AArch64TargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op,
1385813858
SelectionDAG &DAG) const {
13859-
assert(Op.getValueType().isFixedLengthVector() &&
13859+
EVT VT = Op.getValueType();
13860+
assert(VT.isFixedLengthVector() &&
1386013861
"Only cases that extract a fixed length vector are supported!");
13861-
1386213862
EVT InVT = Op.getOperand(0).getValueType();
13863-
unsigned Idx = Op.getConstantOperandVal(1);
13864-
unsigned Size = Op.getValueSizeInBits();
1386513863

1386613864
// If we don't have legal types yet, do nothing
13867-
if (!DAG.getTargetLoweringInfo().isTypeLegal(InVT))
13865+
if (!isTypeLegal(InVT))
1386813866
return SDValue();
1386913867

13870-
if (InVT.isScalableVector()) {
13871-
// This will be matched by custom code during ISelDAGToDAG.
13872-
if (Idx == 0 && isPackedVectorType(InVT, DAG))
13868+
if (InVT.is128BitVector()) {
13869+
assert(VT.is64BitVector() && "Extracting unexpected vector type!");
13870+
unsigned Idx = Op.getConstantOperandVal(1);
13871+
13872+
// This will get lowered to an appropriate EXTRACT_SUBREG in ISel.
13873+
if (Idx == 0)
1387313874
return Op;
1387413875

13875-
return SDValue();
13876+
// If this is extracting the upper 64-bits of a 128-bit vector, we match
13877+
// that directly.
13878+
if (Idx * InVT.getScalarSizeInBits() == 64 && Subtarget->isNeonAvailable())
13879+
return Op;
1387613880
}
1387713881

13878-
// This will get lowered to an appropriate EXTRACT_SUBREG in ISel.
13879-
if (Idx == 0 && InVT.getSizeInBits() <= 128)
13880-
return Op;
13881-
13882-
// If this is extracting the upper 64-bits of a 128-bit vector, we match
13883-
// that directly.
13884-
if (Size == 64 && Idx * InVT.getScalarSizeInBits() == 64 &&
13885-
InVT.getSizeInBits() == 128 && Subtarget->isNeonAvailable())
13886-
return Op;
13887-
13888-
if (useSVEForFixedLengthVectorVT(InVT, !Subtarget->isNeonAvailable())) {
13882+
if (InVT.isScalableVector() ||
13883+
useSVEForFixedLengthVectorVT(InVT, !Subtarget->isNeonAvailable())) {
1388913884
SDLoc DL(Op);
13885+
SDValue Vec = Op.getOperand(0);
13886+
SDValue Idx = Op.getOperand(1);
1389013887

13891-
EVT ContainerVT = getContainerForFixedLengthVector(DAG, InVT);
13892-
SDValue NewInVec =
13893-
convertToScalableVector(DAG, ContainerVT, Op.getOperand(0));
13888+
EVT PackedVT = getPackedSVEVectorVT(InVT.getVectorElementType());
13889+
if (PackedVT != InVT) {
13890+
// Pack input into the bottom part of an SVE register and try again.
13891+
SDValue Container = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, PackedVT,
13892+
DAG.getUNDEF(PackedVT), Vec,
13893+
DAG.getVectorIdxConstant(0, DL));
13894+
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Container, Idx);
13895+
}
13896+
13897+
// This will get matched by custom code during ISelDAGToDAG.
13898+
if (isNullConstant(Idx))
13899+
return Op;
1389413900

13895-
SDValue Splice = DAG.getNode(ISD::VECTOR_SPLICE, DL, ContainerVT, NewInVec,
13896-
NewInVec, DAG.getConstant(Idx, DL, MVT::i64));
13897-
return convertFromScalableVector(DAG, Op.getValueType(), Splice);
13901+
assert(InVT.isScalableVector() && "Unexpected vector type!");
13902+
// Move requested subvector to the start of the vector and try again.
13903+
SDValue Splice = DAG.getNode(ISD::VECTOR_SPLICE, DL, InVT, Vec, Vec, Idx);
13904+
return convertFromScalableVector(DAG, VT, Splice);
1389813905
}
1389913906

1390013907
return SDValue();

llvm/test/CodeGen/AArch64/sve-extract-fixed-from-scalable-vector.ll

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,8 @@ define <4 x float> @extract_v4f32_nxv16f32_12(<vscale x 16 x float> %arg) {
143143
define <2 x float> @extract_v2f32_nxv16f32_2(<vscale x 16 x float> %arg) {
144144
; CHECK-LABEL: extract_v2f32_nxv16f32_2:
145145
; CHECK: // %bb.0:
146-
; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill
147-
; CHECK-NEXT: addvl sp, sp, #-1
148-
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
149-
; CHECK-NEXT: .cfi_offset w29, -16
150-
; CHECK-NEXT: ptrue p0.s
151-
; CHECK-NEXT: st1w { z0.s }, p0, [sp]
152-
; CHECK-NEXT: ldr d0, [sp, #8]
153-
; CHECK-NEXT: addvl sp, sp, #1
154-
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
146+
; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8
147+
; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
155148
; CHECK-NEXT: ret
156149
%ext = call <2 x float> @llvm.vector.extract.v2f32.nxv16f32(<vscale x 16 x float> %arg, i64 2)
157150
ret <2 x float> %ext
@@ -274,15 +267,8 @@ define <4 x i3> @extract_v4i3_nxv32i3_16(<vscale x 32 x i3> %arg) {
274267
define <2 x i32> @extract_v2i32_nxv16i32_2(<vscale x 16 x i32> %arg) {
275268
; CHECK-LABEL: extract_v2i32_nxv16i32_2:
276269
; CHECK: // %bb.0:
277-
; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill
278-
; CHECK-NEXT: addvl sp, sp, #-1
279-
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
280-
; CHECK-NEXT: .cfi_offset w29, -16
281-
; CHECK-NEXT: ptrue p0.s
282-
; CHECK-NEXT: st1w { z0.s }, p0, [sp]
283-
; CHECK-NEXT: ldr d0, [sp, #8]
284-
; CHECK-NEXT: addvl sp, sp, #1
285-
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
270+
; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8
271+
; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
286272
; CHECK-NEXT: ret
287273
%ext = call <2 x i32> @llvm.vector.extract.v2i32.nxv16i32(<vscale x 16 x i32> %arg, i64 2)
288274
ret <2 x i32> %ext
@@ -314,16 +300,9 @@ define <4 x half> @extract_v4f16_nxv2f16_0(<vscale x 2 x half> %arg) {
314300
; CHECK-NEXT: addvl sp, sp, #-1
315301
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
316302
; CHECK-NEXT: .cfi_offset w29, -16
317-
; CHECK-NEXT: cntd x8
318303
; CHECK-NEXT: ptrue p0.d
319-
; CHECK-NEXT: addpl x9, sp, #6
320-
; CHECK-NEXT: subs x8, x8, #4
321-
; CHECK-NEXT: csel x8, xzr, x8, lo
322-
; CHECK-NEXT: st1h { z0.d }, p0, [sp, #3, mul vl]
323-
; CHECK-NEXT: cmp x8, #0
324-
; CHECK-NEXT: csel x8, x8, xzr, lo
325-
; CHECK-NEXT: lsl x8, x8, #1
326-
; CHECK-NEXT: ldr d0, [x9, x8]
304+
; CHECK-NEXT: st1h { z0.d }, p0, [sp]
305+
; CHECK-NEXT: ldr d0, [sp]
327306
; CHECK-NEXT: addvl sp, sp, #1
328307
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
329308
; CHECK-NEXT: ret
@@ -338,17 +317,12 @@ define <4 x half> @extract_v4f16_nxv2f16_4(<vscale x 2 x half> %arg) {
338317
; CHECK-NEXT: addvl sp, sp, #-1
339318
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
340319
; CHECK-NEXT: .cfi_offset w29, -16
341-
; CHECK-NEXT: cntd x8
342-
; CHECK-NEXT: mov w9, #4 // =0x4
343320
; CHECK-NEXT: ptrue p0.d
344-
; CHECK-NEXT: subs x8, x8, #4
345-
; CHECK-NEXT: csel x8, xzr, x8, lo
346-
; CHECK-NEXT: st1h { z0.d }, p0, [sp, #3, mul vl]
347-
; CHECK-NEXT: cmp x8, #4
348-
; CHECK-NEXT: csel x8, x8, x9, lo
349-
; CHECK-NEXT: addpl x9, sp, #6
350-
; CHECK-NEXT: lsl x8, x8, #1
351-
; CHECK-NEXT: ldr d0, [x9, x8]
321+
; CHECK-NEXT: ptrue p1.h
322+
; CHECK-NEXT: st1h { z0.d }, p0, [sp]
323+
; CHECK-NEXT: ld1h { z0.h }, p1/z, [sp]
324+
; CHECK-NEXT: ext z0.b, z0.b, z0.b, #8
325+
; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
352326
; CHECK-NEXT: addvl sp, sp, #1
353327
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
354328
; CHECK-NEXT: ret

0 commit comments

Comments
 (0)