[llvm] [AArch64][GlobalISel] Use GPR for illegal fconstants and extend < 32 bit GPR constants to 32 bits (PR #178692)

David Green via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 16 15:02:47 PST 2026


================
@@ -358,12 +359,77 @@ AArch64RegisterBankInfo::getInstrAlternativeMappings(
   return RegisterBankInfo::getInstrAlternativeMappings(MI);
 }
 
+static bool isLegalFPImm(const MachineInstr &MI, const MachineRegisterInfo &MRI,
+                         const AArch64Subtarget &STI) {
+  assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
+  Register Dst = MI.getOperand(0).getReg();
+  LLT Ty = MRI.getType(Dst);
+  if (!Ty.isScalar())
+    return false;
+
+  unsigned Bits = Ty.getSizeInBits();
+  if (Bits != 16 && Bits != 32 && Bits != 64)
+    return false;
+
+  EVT VT = EVT::getFloatingPointVT(Bits);
+  bool OptForSize = MI.getMF()->getFunction().hasOptSize() ||
+                    MI.getMF()->getFunction().hasMinSize();
+  const AArch64TargetLowering *TLI = STI.getTargetLowering();
+  return TLI->isFPImmLegal(MI.getOperand(1).getFPImm()->getValueAPF(), VT,
+                           OptForSize);
+}
+
 void AArch64RegisterBankInfo::applyMappingImpl(
     MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
   MachineInstr &MI = OpdMapper.getMI();
   MachineRegisterInfo &MRI = OpdMapper.getMRI();
 
   switch (MI.getOpcode()) {
+  case TargetOpcode::G_CONSTANT: {
+    Register Dst = MI.getOperand(0).getReg();
+    LLT DstTy = MRI.getType(Dst);
+    assert(MRI.getRegBank(Dst) == &AArch64::GPRRegBank && DstTy.isScalar() &&
+           DstTy.getSizeInBits() < 32 &&
+           "Expected a scalar smaller than 32 bits on a GPR.");
+    Builder.setInsertPt(*MI.getParent(), std::next(MI.getIterator()));
+    Register ExtReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
+    Builder.buildTrunc(Dst, ExtReg);
+
+    auto Val = MI.getOperand(1).getCImm()->getValue().zext(32);
+    LLVMContext &Ctx = Builder.getMF().getFunction().getContext();
+    MI.getOperand(1).setCImm(ConstantInt::get(Ctx, Val));
+    MI.getOperand(0).setReg(ExtReg);
+    MRI.setRegBank(ExtReg, AArch64::GPRRegBank);
+
+    for (MachineInstr &UseMI :
+         make_early_inc_range(MRI.use_nodbg_instructions(Dst))) {
+      if (UseMI.getOpcode() != AArch64::G_DUP)
+        continue;
+      for (MachineOperand &Op : UseMI.operands()) {
+        if (Op.isReg() && Op.getReg() == Dst)
+          Op.setReg(ExtReg);
+      }
+    }
----------------
davemgreen wrote:

Is this still necessary? It looks like it might do the wrong thing with ExtReg.

https://github.com/llvm/llvm-project/pull/178692


More information about the llvm-commits mailing list