[llvm] [AArch64][GlobalISel] Use GPR for illegal fconstants and extend < 32 bit GPR constants to 32 bits (PR #178692)
Mikael Holmen via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 05:01:07 PST 2026
================
@@ -358,17 +362,129 @@ AArch64RegisterBankInfo::getInstrAlternativeMappings(
return RegisterBankInfo::getInstrAlternativeMappings(MI);
}
+static bool preferGPRForFPImm(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);
+
+ unsigned Size = Ty.getSizeInBits();
+ if (Size != 16 && Size != 32 && Size != 64)
+ return false;
+
+ EVT VT = EVT::getFloatingPointVT(Size);
+ const AArch64TargetLowering *TLI = STI.getTargetLowering();
+
+ const APFloat Imm = MI.getOperand(1).getFPImm()->getValueAPF();
+ const APInt ImmBits = Imm.bitcastToAPInt();
+
+ // Check if we can encode this as a movi. Note, we only have one pattern so
+ // far for movis, hence the one check.
+ if (Size == 32) {
+ uint64_t Val = APInt::getSplat(64, ImmBits).getZExtValue();
+ if (AArch64_AM::isAdvSIMDModImmType4(Val))
+ return false;
+ }
+
+ // We want to use GPR when the value cannot be encoded as the immediate value
+ // of a fmov and when it will not result in a constant pool load. As
+ // AArch64TargetLowering::isFPImmLegal is used by the instruction selector
+ // to choose whether to emit a constant pool load, negating this check will
+ // ensure it would not have become a constant pool load.
+ bool OptForSize =
+ shouldOptimizeForSize(&MI.getMF()->getFunction(), nullptr, nullptr);
+ bool IsLegal = TLI->isFPImmLegal(Imm, VT, OptForSize);
+ bool IsFMov = TLI->isFPImmLegalAsFMov(Imm, VT);
+ return !IsFMov && IsLegal;
+}
+
+// Some of the instructions in applyMappingImpl attempt to anyext small values.
+// It may be that these values come from a G_CONSTANT that has been expanded to
+// 32 bits and then truncated. If this is the case, we shouldn't insert an
+// anyext and should instead make use of the G_CONSTANT directly, deleting the
+// trunc if possible.
+static bool foldTruncOfI32Constant(MachineInstr &MI, unsigned OpIdx,
+ MachineRegisterInfo &MRI,
+ const AArch64RegisterBankInfo &RBI) {
+ MachineOperand &Op = MI.getOperand(OpIdx);
+
+ Register ScalarReg = Op.getReg();
+ MachineInstr *TruncMI = MRI.getVRegDef(ScalarReg);
+ if (!TruncMI || TruncMI->getOpcode() != TargetOpcode::G_TRUNC)
+ return false;
+
+ Register TruncSrc = TruncMI->getOperand(1).getReg();
+ MachineInstr *SrcDef = MRI.getVRegDef(TruncSrc);
+ if (!SrcDef || SrcDef->getOpcode() != TargetOpcode::G_CONSTANT)
+ return false;
+
+ LLT TruncSrcTy = MRI.getType(TruncSrc);
+ if (!TruncSrcTy.isScalar() || TruncSrcTy.getSizeInBits() != 32)
+ return false;
+
+ // Avoid truncating and extending a constant, this helps with selection.
+ Op.setReg(TruncSrc);
+ MRI.setRegBank(TruncSrc, RBI.getRegBank(AArch64::GPRRegBankID));
+
+ if (MRI.use_empty(ScalarReg))
+ TruncMI->eraseFromParent();
+
+ return true;
+}
+
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);
----------------
mikaelholmen wrote:
Yep, thanks
https://github.com/llvm/llvm-project/pull/178692
More information about the llvm-commits
mailing list