[llvm] bb577f6 - [AArch64][GlobalISel] Select i16/f16 cross-bank bitcasts (#220612)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 7 04:08:53 PDT 2026
Author: Cullen Rhodes
Date: 2026-09-07T12:08:47+01:00
New Revision: bb577f620571ce3bb97f2e717b53500574a9cf27
URL: https://github.com/llvm/llvm-project/commit/bb577f620571ce3bb97f2e717b53500574a9cf27
DIFF: https://github.com/llvm/llvm-project/commit/bb577f620571ce3bb97f2e717b53500574a9cf27.diff
LOG: [AArch64][GlobalISel] Select i16/f16 cross-bank bitcasts (#220612)
Test bitcast_to_half in
llvm/test/CodeGen/AArch64/GlobalISel/arm64-atomic.ll crashes with
H0 = COPY W8
unimplemented reg-to-reg copy
UNREACHABLE executed at
/home/culrho01/llvm-project/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp:6363!
when type-based RegBankSelect (#199040) is enabled. Normal RBS keeps
both operands on GPR and moves to FPR afterward. This extends
instruction select to support bitcasts where src/dst reg bank doens't
match.
Assisted-by: codex
Added:
Modified:
llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir
llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 0b018dc7b22a8..2a0118237c390 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -963,6 +963,48 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
return false;
}
+ if (I.getOpcode() == TargetOpcode::G_BITCAST &&
+ RBI.getSizeInBits(DstReg, MRI, TRI) == TypeSize::getFixed(16)) {
+ if (DstRegBank.getID() == AArch64::FPRRegBankID &&
+ SrcRegBank.getID() == AArch64::GPRRegBankID) {
+ if (!SrcReg.isPhysical() &&
+ !RBI.constrainGenericRegister(SrcReg, AArch64::GPR32RegClass, MRI))
+ return false;
+ if (!DstReg.isPhysical() &&
+ !RBI.constrainGenericRegister(DstReg, AArch64::FPR16RegClass, MRI))
+ return false;
+
+ Register FPR32 = MRI.createVirtualRegister(&AArch64::FPR32RegClass);
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::FMOVWSr))
+ .addDef(FPR32)
+ .addUse(SrcReg);
+ I.setDesc(TII.get(TargetOpcode::COPY));
+ I.getOperand(1).setReg(FPR32);
+ I.getOperand(1).setSubReg(AArch64::hsub);
+ return true;
+ }
+
+ if (DstRegBank.getID() == AArch64::GPRRegBankID &&
+ SrcRegBank.getID() == AArch64::FPRRegBankID) {
+ if (!SrcReg.isPhysical() &&
+ !RBI.constrainGenericRegister(SrcReg, AArch64::FPR16RegClass, MRI))
+ return false;
+ if (!DstReg.isPhysical() &&
+ !RBI.constrainGenericRegister(DstReg, AArch64::GPR32RegClass, MRI))
+ return false;
+
+ Register FPR32 = MRI.createVirtualRegister(&AArch64::FPR32RegClass);
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(TargetOpcode::SUBREG_TO_REG))
+ .addDef(FPR32)
+ .addUse(SrcReg)
+ .addImm(AArch64::hsub);
+ I.setDesc(TII.get(AArch64::FMOVSWr));
+ I.getOperand(1).setReg(FPR32);
+ return true;
+ }
+ }
+
// Is this a copy? If so, then we may need to insert a subregister copy.
if (I.isCopy()) {
// Yes. Check if there's anything to fix up.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir b/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir
index 5aa77f1e1295f..53f61d6abe47d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir
@@ -33,7 +33,8 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[PHI:%[0-9]+]]:gpr32 = PHI [[CSELWr]], %bb.1, %7, %bb.2
; CHECK-NEXT: [[FCVTHSr:%[0-9]+]]:fpr16 = nofpexcept FCVTHSr [[COPY]], implicit $fpcr
- ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32all = COPY [[FCVTHSr]]
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:fpr32 = SUBREG_TO_REG [[FCVTHSr]], %subreg.hsub
+ ; CHECK-NEXT: [[FMOVSWr:%[0-9]+]]:gpr32 = FMOVSWr [[SUBREG_TO_REG]]
; CHECK-NEXT: STRHHui [[PHI]], [[DEF1]], 0 :: (store (i16) into `ptr undef`)
; CHECK-NEXT: B %bb.2
bb.0:
@@ -92,7 +93,8 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[PHI:%[0-9]+]]:fpr16 = PHI %7, %bb.2, [[CSELWr]], %bb.1
; CHECK-NEXT: [[FCVTHSr:%[0-9]+]]:fpr16 = nofpexcept FCVTHSr [[COPY]], implicit $fpcr
- ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32all = COPY [[FCVTHSr]]
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:fpr32 = SUBREG_TO_REG [[FCVTHSr]], %subreg.hsub
+ ; CHECK-NEXT: [[FMOVSWr:%[0-9]+]]:gpr32 = FMOVSWr [[SUBREG_TO_REG]]
; CHECK-NEXT: STRHui [[PHI]], [[DEF1]], 0 :: (store (i16) into `ptr undef`)
; CHECK-NEXT: B %bb.2
bb.0:
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir
index 8ffea5447afde..c3db65889ce1f 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir
@@ -14,6 +14,8 @@
define void @bitcast_s64_fpr_gpr() { ret void }
define void @bitcast_s64_v2f32_fpr() { ret void }
define void @bitcast_s64_v8i8_fpr() { ret void }
+ define void @bitcast_i16_gpr_to_f16_fpr() { ret void }
+ define void @bitcast_f16_fpr_to_i16_gpr() { ret void }
...
---
@@ -257,3 +259,45 @@ body: |
%1(<8 x i8>) = G_BITCAST %0
$x0 = COPY %1(<8 x i8>)
...
+
+---
+name: bitcast_i16_gpr_to_f16_fpr
+legalized: true
+regBankSelected: true
+
+registers:
+ - { id: 0, class: gpr }
+ - { id: 1, class: fpr }
+
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: bitcast_i16_gpr_to_f16_fpr
+ ; CHECK: [[DEF:%[0-9]+]]:gpr32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[FMOVWSr:%[0-9]+]]:fpr32 = FMOVWSr [[DEF]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr16 = COPY [[FMOVWSr]].hsub
+ ; CHECK-NEXT: RET_ReallyLR implicit [[COPY1]]
+ %0(i16) = G_IMPLICIT_DEF
+ %1(f16) = G_BITCAST %0
+ RET_ReallyLR implicit %1
+...
+
+---
+name: bitcast_f16_fpr_to_i16_gpr
+legalized: true
+regBankSelected: true
+
+registers:
+ - { id: 0, class: fpr }
+ - { id: 1, class: gpr }
+
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: bitcast_f16_fpr_to_i16_gpr
+ ; CHECK: [[DEF:%[0-9]+]]:fpr16 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:fpr32 = SUBREG_TO_REG [[DEF]], %subreg.hsub
+ ; CHECK-NEXT: [[FMOVSWr:%[0-9]+]]:gpr32 = FMOVSWr [[SUBREG_TO_REG]]
+ ; CHECK-NEXT: RET_ReallyLR implicit [[FMOVSWr]]
+ %0(f16) = G_IMPLICIT_DEF
+ %1(i16) = G_BITCAST %0
+ RET_ReallyLR implicit %1
+...
More information about the llvm-commits
mailing list