[llvm] [AArch64][GlobalISel] Select vector element extract into GPR (PR #210030)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 03:59:43 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel
Author: Cullen Rhodes (c-rhodes)
<details>
<summary>Changes</summary>
Prototyping a new minimal type-based approach to RegBankSelect (#<!-- -->199040) for compile-time purposes exposed various gaps in instruction selection when not using the existing RegBankSelect pass. These manifested as new fallbacks when compiling the IR dataset from [1].
This patch teaches instruction selection to handle extracts of scalar i8/i16/i32 into GPR directly. This will prevent new fallbacks being introduced when a new type-based RBS pass is added.
The test cases are extracted from [1].
Assisted-by: codex
[1] https://davemgreen.github.io/gisel.html
---
Full diff: https://github.com/llvm/llvm-project/pull/210030.diff
2 Files Affected:
- (modified) llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp (+29-7)
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/select-extract-vector-elt.mir (+92)
``````````diff
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 7fa788ec86cc2..0c2f3f97ec07d 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -4016,7 +4016,6 @@ bool AArch64InstructionSelector::selectExtractElt(
const LLT NarrowTy = MRI.getType(DstReg);
const Register SrcReg = I.getOperand(1).getReg();
const LLT WideTy = MRI.getType(SrcReg);
- (void)WideTy;
assert(WideTy.getSizeInBits() >= NarrowTy.getSizeInBits() &&
"source register size too small!");
assert(!NarrowTy.isVector() && "cannot extract vector into vector!");
@@ -4025,19 +4024,42 @@ bool AArch64InstructionSelector::selectExtractElt(
MachineOperand &LaneIdxOp = I.getOperand(2);
assert(LaneIdxOp.isReg() && "Lane index operand was not a register?");
- if (RBI.getRegBank(DstReg, MRI, TRI)->getID() != AArch64::FPRRegBankID) {
- LLVM_DEBUG(dbgs() << "Cannot extract into GPR.\n");
- return false;
- }
-
// Find the index to extract from.
auto VRegAndVal = getIConstantVRegValWithLookThrough(LaneIdxOp.getReg(), MRI);
if (!VRegAndVal)
return false;
unsigned LaneIdx = VRegAndVal->Value.getSExtValue();
-
const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
+ if (DstRB.getID() == AArch64::GPRRegBankID) {
+ unsigned Opcode;
+ switch (WideTy.getScalarSizeInBits()) {
+ case 8:
+ Opcode = AArch64::UMOVvi8;
+ break;
+ case 16:
+ Opcode = AArch64::UMOVvi16;
+ break;
+ case 32:
+ Opcode = AArch64::UMOVvi32;
+ break;
+ default:
+ return false;
+ }
+
+ if (WideTy.getSizeInBits() != 128) {
+ MachineInstr *ScalarToVector = emitScalarToVector(
+ WideTy.getSizeInBits(), &AArch64::FPR128RegClass, SrcReg, MIB);
+ assert(ScalarToVector && "Didn't expect emitScalarToVector to fail!");
+ I.getOperand(1).setReg(ScalarToVector->getOperand(0).getReg());
+ }
+
+ I.setDesc(TII.get(Opcode));
+ I.getOperand(2).ChangeToImmediate(LaneIdx);
+ constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+ return true;
+ }
+
MachineInstr *Extract = emitExtractVectorElt(DstReg, DstRB, NarrowTy, SrcReg,
LaneIdx, MIB);
if (!Extract)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-extract-vector-elt.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-extract-vector-elt.mir
index 0f716ae7ab6e8..62c1bb707f819 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/select-extract-vector-elt.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-extract-vector-elt.mir
@@ -32,6 +32,36 @@ body: |
$s0 = COPY %1(i32)
RET_ReallyLR implicit $s0
+...
+---
+name: v2s32_gpr
+alignment: 4
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: fpr }
+ - { id: 1, class: gpr }
+ - { id: 2, class: gpr }
+body: |
+ bb.0:
+ liveins: $d0
+
+ ; CHECK-LABEL: name: v2s32_gpr
+ ; CHECK: liveins: $d0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $d0
+ ; CHECK-NEXT: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], [[COPY]], %subreg.dsub
+ ; CHECK-NEXT: [[UMOVvi32_:%[0-9]+]]:gpr32 = UMOVvi32 [[INSERT_SUBREG]], 0
+ ; CHECK-NEXT: $w0 = COPY [[UMOVvi32_]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:fpr(<2 x i32>) = COPY $d0
+ %2:gpr(i64) = G_CONSTANT i64 0
+ %1:gpr(i32) = G_EXTRACT_VECTOR_ELT %0(<2 x i32>), %2(i64)
+ $w0 = COPY %1(i32)
+ RET_ReallyLR implicit $w0
+
...
---
name: v2s32_fpr_idx0
@@ -300,3 +330,65 @@ body: |
RET_ReallyLR implicit $d0
...
+---
+name: shuffle_extract_i8
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0
+
+ ; CHECK-LABEL: name: shuffle_extract_i8
+ ; CHECK: liveins: $d0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $d0
+ ; CHECK-NEXT: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], [[COPY]], %subreg.dsub
+ ; CHECK-NEXT: [[UMOVvi8_:%[0-9]+]]:gpr32 = UMOVvi8 [[INSERT_SUBREG]], 4
+ ; CHECK-NEXT: [[DEF1:%[0-9]+]]:fpr128 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[INSERT_SUBREG1:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF1]], [[COPY]], %subreg.dsub
+ ; CHECK-NEXT: [[INSvi8gpr:%[0-9]+]]:fpr128 = INSvi8gpr [[INSERT_SUBREG1]], 1, [[UMOVvi8_]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY [[INSvi8gpr]].dsub
+ ; CHECK-NEXT: $d0 = COPY [[COPY1]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $d0
+ %0:fpr(<8 x i8>) = COPY $d0
+ %1:gpr(i64) = G_CONSTANT i64 4
+ %2:gpr(i8) = G_EXTRACT_VECTOR_ELT %0(<8 x i8>), %1(i64)
+ %3:gpr(i64) = G_CONSTANT i64 1
+ %4:fpr(<8 x i8>) = G_INSERT_VECTOR_ELT %0, %2(i8), %3(i64)
+ $d0 = COPY %4(<8 x i8>)
+ RET_ReallyLR implicit $d0
+
+...
+---
+name: shuffle_extract_i16
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0
+
+ ; CHECK-LABEL: name: shuffle_extract_i16
+ ; CHECK: liveins: $d0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $d0
+ ; CHECK-NEXT: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], [[COPY]], %subreg.dsub
+ ; CHECK-NEXT: [[UMOVvi16_:%[0-9]+]]:gpr32 = UMOVvi16 [[INSERT_SUBREG]], 1
+ ; CHECK-NEXT: [[DEF1:%[0-9]+]]:fpr128 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[INSERT_SUBREG1:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF1]], [[COPY]], %subreg.dsub
+ ; CHECK-NEXT: [[INSvi16gpr:%[0-9]+]]:fpr128 = INSvi16gpr [[INSERT_SUBREG1]], 0, [[UMOVvi16_]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY [[INSvi16gpr]].dsub
+ ; CHECK-NEXT: $d0 = COPY [[COPY1]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $d0
+ %0:fpr(<4 x i16>) = COPY $d0
+ %1:gpr(i64) = G_CONSTANT i64 1
+ %2:gpr(i16) = G_EXTRACT_VECTOR_ELT %0(<4 x i16>), %1(i64)
+ %3:gpr(i64) = G_CONSTANT i64 0
+ %4:fpr(<4 x i16>) = G_INSERT_VECTOR_ELT %0, %2(i16), %3(i64)
+ $d0 = COPY %4(<4 x i16>)
+ RET_ReallyLR implicit $d0
+
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/210030
More information about the llvm-commits
mailing list