[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