[AArch64][GlobalISel] Generalize logic for promoting copies

Generalize the 16-bit FPR to 32-bit GPR logic to work for all cases where
destination size is bigger than source size.

Also fixed CheckCopy() always returning true instead of the result of
isValidCopy().

Differential Revision: https://reviews.llvm.org/D77530

Patch by tambre (Raul Tambre)
This commit is contained in:
Jessica Paquette 2020-04-28 14:45:05 -07:00
parent 68b30bc02b
commit 9f31446c99
1 changed files with 37 additions and 47 deletions

View File

@ -736,7 +736,6 @@ getRegClassesForCopy(MachineInstr &I, const TargetInstrInfo &TII,
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) { const RegisterBankInfo &RBI) {
Register DstReg = I.getOperand(0).getReg(); Register DstReg = I.getOperand(0).getReg();
Register SrcReg = I.getOperand(1).getReg(); Register SrcReg = I.getOperand(1).getReg();
const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI); const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
@ -769,13 +768,12 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
(!Register::isPhysicalRegister(I.getOperand(0).getReg()) && (!Register::isPhysicalRegister(I.getOperand(0).getReg()) &&
!Register::isPhysicalRegister(I.getOperand(1).getReg()))) && !Register::isPhysicalRegister(I.getOperand(1).getReg()))) &&
"No phys reg on generic operator!"); "No phys reg on generic operator!");
assert(KnownValid || isValidCopy(I, DstRegBank, MRI, TRI, RBI)); bool ValidCopy = KnownValid || isValidCopy(I, DstRegBank, MRI, TRI, RBI);
(void)KnownValid; assert(ValidCopy && "Invalid copy.");
return true; return ValidCopy;
}; };
// Is this a copy? If so, then we may need to insert a subregister copy, or // Is this a copy? If so, then we may need to insert a subregister copy.
// a SUBREG_TO_REG.
if (I.isCopy()) { if (I.isCopy()) {
// Yes. Check if there's anything to fix up. // Yes. Check if there's anything to fix up.
if (!SrcRC) { if (!SrcRC) {
@ -785,51 +783,43 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
unsigned SrcSize = TRI.getRegSizeInBits(*SrcRC); unsigned SrcSize = TRI.getRegSizeInBits(*SrcRC);
unsigned DstSize = TRI.getRegSizeInBits(*DstRC); unsigned DstSize = TRI.getRegSizeInBits(*DstRC);
unsigned SubReg;
// If the source register is bigger than the destination we need to perform // If the source bank doesn't support a subregister copy small enough,
// a subregister copy. // then we first need to copy to the destination bank.
if (SrcSize > DstSize) { if (getMinSizeForRegBank(SrcRegBank) > DstSize) {
unsigned SubReg = 0; const TargetRegisterClass *DstTempRC =
getMinClassForRegBank(DstRegBank, SrcSize, /* GetAllRegSet */ true);
getSubRegForClass(DstRC, TRI, SubReg);
// If the source bank doesn't support a subregister copy small enough, MachineIRBuilder MIB(I);
// then we first need to copy to the destination bank. auto Copy = MIB.buildCopy({DstTempRC}, {SrcReg});
if (getMinSizeForRegBank(SrcRegBank) > DstSize) { copySubReg(I, MRI, RBI, Copy.getReg(0), DstRC, SubReg);
const TargetRegisterClass *SubregRC = getMinClassForRegBank( } else if (SrcSize > DstSize) {
DstRegBank, SrcSize, /* GetAllRegSet = */ true); // If the source register is bigger than the destination we need to
getSubRegForClass(DstRC, TRI, SubReg); // perform a subregister copy.
const TargetRegisterClass *SubRegRC =
getMinClassForRegBank(SrcRegBank, DstSize, /* GetAllRegSet */ true);
getSubRegForClass(SubRegRC, TRI, SubReg);
copySubReg(I, MRI, RBI, SrcReg, DstRC, SubReg);
} else if (DstSize > SrcSize) {
// If the destination register is bigger than the source we need to do
// a promotion using SUBREG_TO_REG.
const TargetRegisterClass *PromotionRC =
getMinClassForRegBank(SrcRegBank, DstSize, /* GetAllRegSet */ true);
getSubRegForClass(SrcRC, TRI, SubReg);
MachineIRBuilder MIB(I); Register PromoteReg = MRI.createVirtualRegister(PromotionRC);
auto Copy = MIB.buildCopy({SubregRC}, {SrcReg}); BuildMI(*I.getParent(), I, I.getDebugLoc(),
copySubReg(I, MRI, RBI, Copy.getReg(0), DstRC, SubReg); TII.get(AArch64::SUBREG_TO_REG), PromoteReg)
} else { .addImm(0)
const TargetRegisterClass *SubregRC = getMinClassForRegBank( .addUse(SrcReg)
SrcRegBank, DstSize, /* GetAllRegSet = */ true); .addImm(SubReg);
getSubRegForClass(SubregRC, TRI, SubReg); MachineOperand &RegOp = I.getOperand(1);
copySubReg(I, MRI, RBI, SrcReg, DstRC, SubReg); RegOp.setReg(PromoteReg);
}
return CheckCopy(); // Promise that the copy is implicitly validated by the SUBREG_TO_REG.
} KnownValid = true;
// Is this a cross-bank copy?
if (DstRegBank.getID() != SrcRegBank.getID()) {
if (DstRegBank.getID() == AArch64::GPRRegBankID && DstSize == 32 &&
SrcSize == 16) {
// Special case for FPR16 to GPR32.
// FIXME: This can probably be generalized like the above case.
Register PromoteReg =
MRI.createVirtualRegister(&AArch64::FPR32RegClass);
BuildMI(*I.getParent(), I, I.getDebugLoc(),
TII.get(AArch64::SUBREG_TO_REG), PromoteReg)
.addImm(0)
.addUse(SrcReg)
.addImm(AArch64::hsub);
MachineOperand &RegOp = I.getOperand(1);
RegOp.setReg(PromoteReg);
// Promise that the copy is implicitly validated by the SUBREG_TO_REG.
KnownValid = true;
}
} }
// If the destination is a physical register, then there's nothing to // If the destination is a physical register, then there's nothing to