[llvm] 08936cd - [AArch64][GlobalISel] Add legalisation to G_EXRACT_SUBVECTOR (#207956)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 6 00:23:59 PDT 2026
Author: Joshua Rodriguez
Date: 2026-08-06T08:23:54+01:00
New Revision: 08936cd2a0ca69b4cc6326aea11960e1352e9d91
URL: https://github.com/llvm/llvm-project/commit/08936cd2a0ca69b4cc6326aea11960e1352e9d91
DIFF: https://github.com/llvm/llvm-project/commit/08936cd2a0ca69b4cc6326aea11960e1352e9d91.diff
LOG: [AArch64][GlobalISel] Add legalisation to G_EXRACT_SUBVECTOR (#207956)
Prevent legalisation of this opcode falling back to SDAG.
In situations where a G_EXTRACT_SUBVECTOR is being performed on two
vectors which aren't double/half the size of each other, represent the
extract as build_vector(extract_vector_element, extract_vector_element,
...).
Added:
llvm/test/CodeGen/AArch64/GlobalISel/extract-subvector.ll
Modified:
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
llvm/test/CodeGen/AArch64/GlobalISel/insert-subvector.ll
llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll
llvm/test/CodeGen/AArch64/extract-vector-elt.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 16a87a8d28833..c550db75619f9 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4932,13 +4932,13 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
auto InsertionPointImm = MI.getOperand(3).getImm();
LLT VectorTy = MRI.getType(Vector);
- LLT SubvectorTy = MRI.getType(Subvector);
+ LLT DstTy = MRI.getType(Subvector);
// If so, -> concat(subvector, extract(half of vector))
// (Operands can be either way round depending on insertion point
- if (VectorTy.getSizeInBits() == SubvectorTy.getSizeInBits() * 2) {
+ if (VectorTy.getSizeInBits() == DstTy.getSizeInBits() * 2) {
bool InsertInLowHalf = InsertionPointImm == 0;
auto Extract = MIRBuilder.buildExtractSubvector(
- SubvectorTy, Vector,
+ DstTy, Vector,
(uint64_t)(InsertInLowHalf ? VectorTy.getNumElements() / 2 : 0));
auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
@@ -4960,7 +4960,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
for (int i = 0; i < VectorTy.getNumElements(); i++) {
// If this index is within bounds, put subvector's index into mask
if (i >= InsertionPointImm &&
- i < InsertionPointImm + SubvectorTy.getNumElements())
+ i < InsertionPointImm + DstTy.getNumElements())
Mask.push_back(VectorTy.getNumElements() + i - InsertionPointImm);
else
Mask.push_back(i);
@@ -4973,6 +4973,34 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
return Legalized;
}
}
+ case G_EXTRACT_SUBVECTOR: {
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
+ uint64_t ExtractionPointImm = MI.getOperand(2).getImm();
+
+ LLT SrcTy = MRI.getType(SrcReg);
+ LLT DstTy = MRI.getType(DstReg);
+
+ if (SrcTy.isScalable() || DstTy.isScalable())
+ return UnableToLegalize;
+
+ if (SrcTy.getScalarType() != DstTy.getScalarType())
+ return UnableToLegalize;
+
+ // extract_subvector = build_vector(extract_element, extract_element, ...)
+ SmallVector<Register> ExtractedElements;
+ for (uint64_t i = 0; i < DstTy.getNumElements(); i++) {
+ ExtractedElements.push_back(
+ MIRBuilder
+ .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
+ ExtractionPointImm + i)
+ .getReg(0));
+ }
+
+ MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
+ MI.eraseFromParent();
+ return Legalized;
+ }
case G_STACKSAVE:
return lowerStackSave(MI);
case G_STACKRESTORE:
@@ -5840,6 +5868,34 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
if (TypeIdx != 1) // TODO: This probably does work as expected already.
return UnableToLegalize;
return fewerElementsVectorMerge(MI, TypeIdx, NarrowTy);
+ case G_EXTRACT_SUBVECTOR: {
+ Register DstReg = MI.getOperand(0).getReg();
+ LLT DstTy = MRI.getType(DstReg);
+ Register SrcReg = MI.getOperand(1).getReg();
+ uint64_t InsertionPointImm = MI.getOperand(2).getImm();
+
+ // If Dst > NarrowTy bits, then cannot legalize
+ if (DstTy.getSizeInBits() > NarrowTy.getSizeInBits())
+ return UnableToLegalize;
+
+ // If DstTy's size is not a multiple of NarrowTy's, then cannot legalize
+ if (!DstTy.getElementCount().isKnownMultipleOf(NarrowTy.getElementCount()))
+ return UnableToLegalize;
+
+ auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
+ uint64_t RequiredSubvectorIndex =
+ InsertionPointImm / NarrowTy.getNumElements();
+ // If Dst and Narrow are both same size, convert to a copy
+ if (DstTy.getNumElements() == NarrowTy.getNumElements())
+ MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
+ else
+ MIRBuilder.buildExtractSubvector(
+ DstReg, Unmerge.getReg(RequiredSubvectorIndex),
+ InsertionPointImm % NarrowTy.getNumElements());
+
+ MI.eraseFromParent();
+ return Legalized;
+ }
case G_EXTRACT_VECTOR_ELT:
case G_INSERT_VECTOR_ELT:
return fewerElementsVectorExtractInsertVectorElt(MI, TypeIdx, NarrowTy);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 5def62f4707e6..2263712120de8 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1352,6 +1352,13 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
getActionDefinitionsBuilder(G_EXTRACT_SUBVECTOR)
.legalFor({{v8s8, v16s8}, {v4s16, v8s16}, {v2s32, v4s32}})
.widenScalarOrEltToNextPow2(0)
+ .clampMaxNumElements(0, s8, 16)
+ .clampMaxNumElements(0, s16, 8)
+ .clampMaxNumElements(0, s32, 4)
+ .clampNumElements(1, v8s8, v16s8)
+ .clampNumElements(1, v4s16, v8s16)
+ .clampNumElements(1, v2s32, v4s32)
+ .lower()
.immIdx(0); // Inform verifier imm idx 0 is handled.
// TODO: {nxv16s8, s8}, {nxv8s16, s16}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/extract-subvector.ll b/llvm/test/CodeGen/AArch64/GlobalISel/extract-subvector.ll
new file mode 100644
index 0000000000000..637b3b41a0dd5
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/extract-subvector.ll
@@ -0,0 +1,391 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+
+; RUN: llc -mtriple=aarch64 %s -o - | FileCheck --check-prefixes=CHECK,CHECK-SD %s
+; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 %s -o - 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-GI %s
+
+define <4 x i32> @extract_v4i32_v8i32_low(<8 x i32> %a) {
+; CHECK-LABEL: extract_v4i32_v8i32_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+ %vector = call <4 x i32> @llvm.vector.extract.subvector.v4i32.v8i32(<8 x i32> %a, i64 0)
+ ret <4 x i32> %vector
+}
+
+define <4 x i32> @extract_v4i32_v8i32_high(<8 x i32> %a) {
+; CHECK-LABEL: extract_v4i32_v8i32_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov v0.16b, v1.16b
+; CHECK-NEXT: ret
+entry:
+ %vector = call <4 x i32> @llvm.vector.extract.subvector.v4i32.v8i32(<8 x i32> %a, i64 4)
+ ret <4 x i32> %vector
+}
+
+define <4 x i32> @extract_v4i32_v4i32(<4 x i32> %a) {
+; CHECK-SD-LABEL: extract_v4i32_v4i32:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: extract_v4i32_v4i32:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov s1, v0.s[0]
+; CHECK-GI-NEXT: mov v1.s[1], v0.s[1]
+; CHECK-GI-NEXT: mov v1.s[2], v0.s[2]
+; CHECK-GI-NEXT: mov v1.s[3], v0.s[3]
+; CHECK-GI-NEXT: mov v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
+entry:
+ %vector = call <4 x i32> @llvm.vector.extract.subvector.v4i32.v4i32(<4 x i32> %a, i64 0)
+ ret <4 x i32> %vector
+}
+
+define <2 x i32> @extract_v2i32_v8i32_low(<8 x i32> %a) {
+; CHECK-LABEL: extract_v2i32_v8i32_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <2 x i32> @llvm.vector.extract.subvector.v2i32.v8i32(<8 x i32> %a, i64 0)
+ ret <2 x i32> %vector
+}
+
+define <2 x i32> @extract_v2i32_v8i32_mid(<8 x i32> %a) {
+; CHECK-LABEL: extract_v2i32_v8i32_mid:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov v0.16b, v1.16b
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <2 x i32> @llvm.vector.extract.subvector.v2i32.v8i32(<8 x i32> %a, i64 4)
+ ret <2 x i32> %vector
+}
+
+define <2 x i32> @extract_v2i32_v8i32_high(<8 x i32> %a) {
+; CHECK-LABEL: extract_v2i32_v8i32_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v1.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <2 x i32> @llvm.vector.extract.subvector.v2i32.v8i32(<8 x i32> %a, i64 6)
+ ret <2 x i32> %vector
+}
+
+define <2 x i32> @extract_v2i32_v4i32_low(<4 x i32> %a) {
+; CHECK-LABEL: extract_v2i32_v4i32_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <2 x i32> @llvm.vector.extract.subvector.v2i32.v4i32(<4 x i32> %a, i64 0)
+ ret <2 x i32> %vector
+}
+
+define <2 x i32> @extract_v2i32_v4i32_high(<4 x i32> %a) {
+; CHECK-LABEL: extract_v2i32_v4i32_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v0.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <2 x i32> @llvm.vector.extract.subvector.v2i32.v4i32(<4 x i32> %a, i64 2)
+ ret <2 x i32> %vector
+}
+
+define <2 x i32> @extract_v2i32_v2i32(<2 x i32> %a) {
+; CHECK-SD-LABEL: extract_v2i32_v2i32:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: extract_v2i32_v2i32:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT: mov v1.s[0], v0.s[0]
+; CHECK-GI-NEXT: mov v1.s[1], v0.s[1]
+; CHECK-GI-NEXT: fmov d0, d1
+; CHECK-GI-NEXT: ret
+entry:
+ %vector = call <2 x i32> @llvm.vector.extract.subvector.v2i32.v2i32(<2 x i32> %a, i64 0)
+ ret <2 x i32> %vector
+}
+
+define <8 x i16> @extract_v8i16_v16i16_low(<16 x i16> %a) {
+; CHECK-LABEL: extract_v8i16_v16i16_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+ %vector = call <8 x i16> @llvm.vector.extract.subvector.v8i16.v16i16(<16 x i16> %a, i64 0)
+ ret <8 x i16> %vector
+}
+
+define <8 x i16> @extract_v8i16_v16i16_high(<16 x i16> %a) {
+; CHECK-LABEL: extract_v8i16_v16i16_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov v0.16b, v1.16b
+; CHECK-NEXT: ret
+entry:
+ %vector = call <8 x i16> @llvm.vector.extract.subvector.v8i16.v16i16(<16 x i16> %a, i64 8)
+ ret <8 x i16> %vector
+}
+
+define <8 x i16> @extract_v8i16_v8i16(<8 x i16> %a) {
+; CHECK-SD-LABEL: extract_v8i16_v8i16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: extract_v8i16_v8i16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov h1, v0.h[0]
+; CHECK-GI-NEXT: mov v1.h[1], v0.h[1]
+; CHECK-GI-NEXT: mov v1.h[2], v0.h[2]
+; CHECK-GI-NEXT: mov v1.h[3], v0.h[3]
+; CHECK-GI-NEXT: mov v1.h[4], v0.h[4]
+; CHECK-GI-NEXT: mov v1.h[5], v0.h[5]
+; CHECK-GI-NEXT: mov v1.h[6], v0.h[6]
+; CHECK-GI-NEXT: mov v1.h[7], v0.h[7]
+; CHECK-GI-NEXT: mov v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
+entry:
+ %vector = call <8 x i16> @llvm.vector.extract.subvector.v8i16.v8i16(<8 x i16> %a, i64 0)
+ ret <8 x i16> %vector
+}
+
+define <4 x i16> @extract_v4i16_v16i16_low(<16 x i16> %a) {
+; CHECK-LABEL: extract_v4i16_v16i16_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <4 x i16> @llvm.vector.extract.subvector.v4i16.v16i16(<16 x i16> %a, i64 0)
+ ret <4 x i16> %vector
+}
+
+define <4 x i16> @extract_v4i16_v16i16_mid(<16 x i16> %a) {
+; CHECK-LABEL: extract_v4i16_v16i16_mid:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v1.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <4 x i16> @llvm.vector.extract.subvector.v4i16.v16i16(<16 x i16> %a, i64 12)
+ ret <4 x i16> %vector
+}
+
+define <4 x i16> @extract_v4i16_v16i16_high(<16 x i16> %a) {
+; CHECK-LABEL: extract_v4i16_v16i16_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v1.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <4 x i16> @llvm.vector.extract.subvector.v4i16.v16i16(<16 x i16> %a, i64 12)
+ ret <4 x i16> %vector
+}
+
+define <4 x i16> @extract_v4i16_v8i16_low(<8 x i16> %a) {
+; CHECK-LABEL: extract_v4i16_v8i16_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <4 x i16> @llvm.vector.extract.subvector.v4i16.v8i16(<8 x i16> %a, i64 0)
+ ret <4 x i16> %vector
+}
+
+define <4 x i16> @extract_v4i16_v8i16_high(<8 x i16> %a) {
+; CHECK-LABEL: extract_v4i16_v8i16_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v0.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <4 x i16> @llvm.vector.extract.subvector.v4i16.v8i16(<8 x i16> %a, i64 4)
+ ret <4 x i16> %vector
+}
+
+define <4 x i16> @extract_v4i16_v4i16(<4 x i16> %a) {
+; CHECK-SD-LABEL: extract_v4i16_v4i16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: extract_v4i16_v4i16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT: mov v1.h[0], v0.h[0]
+; CHECK-GI-NEXT: mov v1.h[1], v0.h[1]
+; CHECK-GI-NEXT: mov v1.h[2], v0.h[2]
+; CHECK-GI-NEXT: mov v1.h[3], v0.h[3]
+; CHECK-GI-NEXT: fmov d0, d1
+; CHECK-GI-NEXT: ret
+entry:
+ %vector = call <4 x i16> @llvm.vector.extract.subvector.v4i16.v4i16(<4 x i16> %a, i64 0)
+ ret <4 x i16> %vector
+}
+
+define <16 x i8> @extract_v16i8_v32i8_low(<32 x i8> %a) {
+; CHECK-LABEL: extract_v16i8_v32i8_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+ %vector = call <16 x i8> @llvm.vector.extract.subvector.v16i8.v32i8(<32 x i8> %a, i64 0)
+ ret <16 x i8> %vector
+}
+
+define <16 x i8> @extract_v16i8_v32i8_high(<32 x i8> %a) {
+; CHECK-LABEL: extract_v16i8_v32i8_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov v0.16b, v1.16b
+; CHECK-NEXT: ret
+entry:
+ %vector = call <16 x i8> @llvm.vector.extract.subvector.v16i8.v32i8(<32 x i8> %a, i64 16)
+ ret <16 x i8> %vector
+}
+
+define <16 x i8> @extract_v16i8_v16i8(<16 x i8> %a) {
+; CHECK-SD-LABEL: extract_v16i8_v16i8:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: extract_v16i8_v16i8:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov b1, v0.b[0]
+; CHECK-GI-NEXT: mov v1.b[1], v0.b[1]
+; CHECK-GI-NEXT: mov v1.b[2], v0.b[2]
+; CHECK-GI-NEXT: mov v1.b[3], v0.b[3]
+; CHECK-GI-NEXT: mov v1.b[4], v0.b[4]
+; CHECK-GI-NEXT: mov v1.b[5], v0.b[5]
+; CHECK-GI-NEXT: mov v1.b[6], v0.b[6]
+; CHECK-GI-NEXT: mov v1.b[7], v0.b[7]
+; CHECK-GI-NEXT: mov v1.b[8], v0.b[8]
+; CHECK-GI-NEXT: mov v1.b[9], v0.b[9]
+; CHECK-GI-NEXT: mov v1.b[10], v0.b[10]
+; CHECK-GI-NEXT: mov v1.b[11], v0.b[11]
+; CHECK-GI-NEXT: mov v1.b[12], v0.b[12]
+; CHECK-GI-NEXT: mov v1.b[13], v0.b[13]
+; CHECK-GI-NEXT: mov v1.b[14], v0.b[14]
+; CHECK-GI-NEXT: mov v1.b[15], v0.b[15]
+; CHECK-GI-NEXT: mov v0.16b, v1.16b
+; CHECK-GI-NEXT: ret
+entry:
+ %vector = call <16 x i8> @llvm.vector.extract.subvector.v16i8.v16i8(<16 x i8> %a, i64 0)
+ ret <16 x i8> %vector
+}
+
+define <8 x i8> @extract_v8i8_v32i8_low(<32 x i8> %a) {
+; CHECK-LABEL: extract_v8i8_v32i8_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <8 x i8> @llvm.vector.extract.subvector.v8i8.v32i8(<32 x i8> %a, i64 0)
+ ret <8 x i8> %vector
+}
+
+define <8 x i8> @extract_v8i8_v32i8_mid(<32 x i8> %a) {
+; CHECK-LABEL: extract_v8i8_v32i8_mid:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v0.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <8 x i8> @llvm.vector.extract.subvector.v8i8.v32i8(<32 x i8> %a, i64 8)
+ ret <8 x i8> %vector
+}
+
+define <8 x i8> @extract_v8i8_v32i8_high(<32 x i8> %a) {
+; CHECK-LABEL: extract_v8i8_v32i8_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v1.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <8 x i8> @llvm.vector.extract.subvector.v8i8.v32i8(<32 x i8> %a, i64 24)
+ ret <8 x i8> %vector
+}
+
+define <8 x i8> @extract_v8i8_v16i8_low(<16 x i8> %a) {
+; CHECK-LABEL: extract_v8i8_v16i8_low:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <8 x i8> @llvm.vector.extract.subvector.v8i8.v16i8(<16 x i8> %a, i64 0)
+ ret <8 x i8> %vector
+}
+
+define <8 x i8> @extract_v8i8_v16i8_high(<16 x i8> %a) {
+; CHECK-LABEL: extract_v8i8_v16i8_high:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v0.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <8 x i8> @llvm.vector.extract.subvector.v8i8.v16i8(<16 x i8> %a, i64 8)
+ ret <8 x i8> %vector
+}
+
+define <8 x i8> @extract_v8i8_v8i8(<8 x i8> %a) {
+; CHECK-SD-LABEL: extract_v8i8_v8i8:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: extract_v8i8_v8i8:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT: mov v1.b[0], v0.b[0]
+; CHECK-GI-NEXT: mov v1.b[1], v0.b[1]
+; CHECK-GI-NEXT: mov v1.b[2], v0.b[2]
+; CHECK-GI-NEXT: mov v1.b[3], v0.b[3]
+; CHECK-GI-NEXT: mov v1.b[4], v0.b[4]
+; CHECK-GI-NEXT: mov v1.b[5], v0.b[5]
+; CHECK-GI-NEXT: mov v1.b[6], v0.b[6]
+; CHECK-GI-NEXT: mov v1.b[7], v0.b[7]
+; CHECK-GI-NEXT: fmov d0, d1
+; CHECK-GI-NEXT: ret
+entry:
+ %vector = call <8 x i8> @llvm.vector.extract.subvector.v8i8.v8i8(<8 x i8> %a, i64 0)
+ ret <8 x i8> %vector
+}
+
+define <2 x i10> @extract_v2i10_v4i10_low(<4 x i10> %a) {
+; CHECK-LABEL: extract_v2i10_v4i10_low:
+; CHECK: // %bb.0:
+; CHECK-NEXT: zip1 v0.4h, v0.4h, v0.4h
+; CHECK-NEXT: ret
+ %vector = call <2 x i10> @llvm.vector.extract.subvector.v2i10.v4i10(<4 x i10> %a, i64 0)
+ ret <2 x i10> %vector
+}
+
+define <2 x i10> @extract_v2i10_v4i10_high(<4 x i10> %a) {
+; CHECK-LABEL: extract_v2i10_v4i10_high:
+; CHECK: // %bb.0:
+; CHECK-NEXT: zip2 v0.4h, v0.4h, v0.4h
+; CHECK-NEXT: ret
+ %vector = call <2 x i10> @llvm.vector.extract.subvector.v2i10.v4i10(<4 x i10> %a, i64 2)
+ ret <2 x i10> %vector
+}
+
+define <2 x i32> @extract_v2i32_v10i32_2(<10 x i32> %a) {
+; CHECK-LABEL: extract_v2i32_v10i32_2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov s0, w2
+; CHECK-NEXT: mov v0.s[1], w3
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %vector = call <2 x i32> @llvm.vector.extract.subvector.v2i32.v10i32(<10 x i32> %a, i64 2)
+ ret <2 x i32> %vector
+}
+
+define <1 x i64> @extract_v1i64_v2i64_1(<2 x i64> %a) {
+; CHECK-LABEL: extract_v1i64_v2i64_1:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v0.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <1 x i64> @llvm.vector.extract.subvector.v1i64.v2i64(<2 x i64> %a, i64 1)
+ ret <1 x i64> %vector
+}
+
+define <1 x i64> @extract_v1i64_v4i64_4(<4 x i64> %a) {
+; CHECK-LABEL: extract_v1i64_v4i64_4:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov d0, v1.d[1]
+; CHECK-NEXT: ret
+entry:
+ %vector = call <1 x i64> @llvm.vector.extract.subvector.v1i64.v4i64(<4 x i64> %a, i64 3)
+ ret <1 x i64> %vector
+}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/insert-subvector.ll b/llvm/test/CodeGen/AArch64/GlobalISel/insert-subvector.ll
index a6a42fb6887e2..d2f9723a6e756 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/insert-subvector.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/insert-subvector.ll
@@ -2,9 +2,6 @@
; RUN: llc -mtriple=aarch64 %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-SD %s
; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 %s -o - 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-GI %s
-; CHECK-GI: warning: Instruction selection used fallback path for insert_v8i32_v4i32_high
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for insert_v8i32_v4i32_low
-
define <4 x i32> @insert_v4i32_v2i32_high(<4 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: insert_v4i32_v2i32_high:
; CHECK: // %bb.0: // %entry
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 26c0aaa3bb3c9..4a88a30d56e01 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -727,8 +727,8 @@
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_EXTRACT_SUBVECTOR (opcode {{[0-9]+}}): 2 type indices, 1 imm index
-# DEBUG-NEXT: .. the first uncovered type index: 2, OK
-# DEBUG-NEXT: .. the first uncovered imm index: 1, OK
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_INSERT_VECTOR_ELT (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll
index bb043ecb5ecb3..acbe0c4097daa 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll
@@ -6,10 +6,6 @@
; RUN: llc < %s -mtriple=aarch64 --global-isel --global-isel-abort=2 --mattr=+complxnum,+neon,+fullfp16,+sve -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
; RUN: llc < %s -mtriple=aarch64 --global-isel --global-isel-abort=2 --mattr=+complxnum,+neon,+fullfp16,+sve2 -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-; CHECK-GI: warning: Instruction selection used fallback path for complex_add_v16f16
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for complex_add_v32f16
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for complex_add_v16f16_with_intrinsic
-
; Expected to not transform
define <2 x half> @complex_add_v2f16(<2 x half> %a, <2 x half> %b) {
; CHECK-SD-LABEL: complex_add_v2f16:
@@ -82,11 +78,17 @@ entry:
; Expected to transform
define <16 x half> @complex_add_v16f16(<16 x half> %a, <16 x half> %b) {
-; CHECK-LABEL: complex_add_v16f16:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcadd v1.8h, v3.8h, v1.8h, #90
-; CHECK-NEXT: fcadd v0.8h, v2.8h, v0.8h, #90
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: complex_add_v16f16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcadd v1.8h, v3.8h, v1.8h, #90
+; CHECK-SD-NEXT: fcadd v0.8h, v2.8h, v0.8h, #90
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: complex_add_v16f16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcadd v0.8h, v2.8h, v0.8h, #90
+; CHECK-GI-NEXT: fcadd v1.8h, v3.8h, v1.8h, #90
+; CHECK-GI-NEXT: ret
entry:
%a.real = shufflevector <16 x half> %a, <16 x half> zeroinitializer, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
%a.imag = shufflevector <16 x half> %a, <16 x half> zeroinitializer, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
@@ -158,11 +160,17 @@ entry:
; Expected to transform
define <16 x half> @complex_add_v16f16_with_intrinsic(<16 x half> %a, <16 x half> %b) {
-; CHECK-LABEL: complex_add_v16f16_with_intrinsic:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcadd v1.8h, v3.8h, v1.8h, #90
-; CHECK-NEXT: fcadd v0.8h, v2.8h, v0.8h, #90
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: complex_add_v16f16_with_intrinsic:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcadd v1.8h, v3.8h, v1.8h, #90
+; CHECK-SD-NEXT: fcadd v0.8h, v2.8h, v0.8h, #90
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: complex_add_v16f16_with_intrinsic:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcadd v0.8h, v2.8h, v0.8h, #90
+; CHECK-GI-NEXT: fcadd v1.8h, v3.8h, v1.8h, #90
+; CHECK-GI-NEXT: ret
entry:
%a.deinterleaved = tail call { <8 x half>, <8 x half> } @llvm.vector.deinterleave2.v16f16(<16 x half> %a)
%a.real = extractvalue { <8 x half>, <8 x half> } %a.deinterleaved, 0
diff --git a/llvm/test/CodeGen/AArch64/extract-vector-elt.ll b/llvm/test/CodeGen/AArch64/extract-vector-elt.ll
index bd312737cade8..3ab413b50e17d 100644
--- a/llvm/test/CodeGen/AArch64/extract-vector-elt.ll
+++ b/llvm/test/CodeGen/AArch64/extract-vector-elt.ll
@@ -2,9 +2,6 @@
; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-; CHECK-GI: warning: Instruction selection used fallback path for extract_v4i32_vector_extract
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for extract_v4i32_vector_extract_const
-
define i64 @extract_v2i64_undef_index(<2 x i64> %a, i32 %c) {
; CHECK-SD-LABEL: extract_v2i64_undef_index:
; CHECK-SD: // %bb.0: // %entry
@@ -816,17 +813,33 @@ entry:
}
define i32 @extract_v4i32_vector_extract(<4 x i32> %a, <2 x i32> %b, i32 %c) {
-; CHECK-LABEL: extract_v4i32_vector_extract:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sub sp, sp, #16
-; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: mov x8, sp
-; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
-; CHECK-NEXT: str q0, [sp]
-; CHECK-NEXT: bfi x8, x0, #2, #2
-; CHECK-NEXT: ldr w0, [x8]
-; CHECK-NEXT: add sp, sp, #16
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: extract_v4i32_vector_extract:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: sub sp, sp, #16
+; CHECK-SD-NEXT: .cfi_def_cfa_offset 16
+; CHECK-SD-NEXT: mov x8, sp
+; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-SD-NEXT: str q0, [sp]
+; CHECK-SD-NEXT: bfi x8, x0, #2, #2
+; CHECK-SD-NEXT: ldr w0, [x8]
+; CHECK-SD-NEXT: add sp, sp, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: extract_v4i32_vector_extract:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: sub sp, sp, #16
+; CHECK-GI-NEXT: .cfi_def_cfa_offset 16
+; CHECK-GI-NEXT: mov s1, v0.s[0]
+; CHECK-GI-NEXT: mov w9, w0
+; CHECK-GI-NEXT: mov x8, sp
+; CHECK-GI-NEXT: and x9, x9, #0x3
+; CHECK-GI-NEXT: mov v1.s[1], v0.s[1]
+; CHECK-GI-NEXT: mov v1.s[2], v0.s[2]
+; CHECK-GI-NEXT: mov v1.s[3], v0.s[3]
+; CHECK-GI-NEXT: str q1, [sp]
+; CHECK-GI-NEXT: ldr w0, [x8, x9, lsl #2]
+; CHECK-GI-NEXT: add sp, sp, #16
+; CHECK-GI-NEXT: ret
entry:
%vector = call <4 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %a, i64 0)
%d = extractelement <4 x i32> %vector, i32 %c
More information about the llvm-commits
mailing list