@@ -4175,7 +4175,10 @@ int64_t AArch64FrameLowering::assignSVEStackObjectOffsets(
4175
4175
// / Attempts to scavenge a register from \p ScavengeableRegs given the used
4176
4176
// / registers in \p UsedRegs.
4177
4177
static Register tryScavengeRegister (LiveRegUnits const &UsedRegs,
4178
- BitVector const &ScavengeableRegs) {
4178
+ BitVector const &ScavengeableRegs,
4179
+ Register PreferredReg) {
4180
+ if (PreferredReg != AArch64::NoRegister && UsedRegs.available (PreferredReg))
4181
+ return PreferredReg;
4179
4182
for (auto Reg : ScavengeableRegs.set_bits ()) {
4180
4183
if (UsedRegs.available (Reg))
4181
4184
return Reg;
@@ -4212,11 +4215,12 @@ struct ScopedScavengeOrSpill {
4212
4215
Register SpillCandidate, const TargetRegisterClass &RC,
4213
4216
LiveRegUnits const &UsedRegs,
4214
4217
BitVector const &AllocatableRegs,
4215
- std::optional<int > *MaybeSpillFI)
4218
+ std::optional<int > *MaybeSpillFI,
4219
+ Register PreferredReg = AArch64::NoRegister)
4216
4220
: MBB(MBB), MBBI(MBBI), RC(RC), TII(static_cast <const AArch64InstrInfo &>(
4217
4221
*MF.getSubtarget().getInstrInfo())),
4218
4222
TRI (*MF.getSubtarget().getRegisterInfo()) {
4219
- FreeReg = tryScavengeRegister (UsedRegs, AllocatableRegs);
4223
+ FreeReg = tryScavengeRegister (UsedRegs, AllocatableRegs, PreferredReg );
4220
4224
if (FreeReg != AArch64::NoRegister)
4221
4225
return ;
4222
4226
assert (MaybeSpillFI && " Expected emergency spill slot FI information "
@@ -4331,12 +4335,10 @@ static void expandSpillPPRToZPRSlotPseudo(MachineBasicBlock &MBB,
4331
4335
// / spilling if necessary). If the status flags are in use at the point of
4332
4336
// / expansion they are preserved (by moving them to/from a GPR). This may cause
4333
4337
// / an additional spill if no GPR is free at the expansion point.
4334
- static bool expandFillPPRFromZPRSlotPseudo (MachineBasicBlock &MBB,
4335
- MachineInstr &MI,
4336
- const TargetRegisterInfo &TRI,
4337
- LiveRegUnits const &UsedRegs,
4338
- ScavengeableRegs const &SR,
4339
- EmergencyStackSlots &SpillSlots) {
4338
+ static bool expandFillPPRFromZPRSlotPseudo (
4339
+ MachineBasicBlock &MBB, MachineInstr &MI, const TargetRegisterInfo &TRI,
4340
+ LiveRegUnits const &UsedRegs, ScavengeableRegs const &SR,
4341
+ MachineInstr *&LastPTrue, EmergencyStackSlots &SpillSlots) {
4340
4342
MachineFunction &MF = *MBB.getParent ();
4341
4343
auto *TII =
4342
4344
static_cast <const AArch64InstrInfo *>(MF.getSubtarget ().getInstrInfo ());
@@ -4347,7 +4349,9 @@ static bool expandFillPPRFromZPRSlotPseudo(MachineBasicBlock &MBB,
4347
4349
4348
4350
ScopedScavengeOrSpill PredReg (
4349
4351
MF, MBB, MI, AArch64::P0, AArch64::PPR_3bRegClass, UsedRegs, SR.PPR3bRegs ,
4350
- isInPrologueOrEpilogue (MI) ? nullptr : &SpillSlots.PPRSpillFI );
4352
+ isInPrologueOrEpilogue (MI) ? nullptr : &SpillSlots.PPRSpillFI ,
4353
+ /* PreferredReg=*/
4354
+ LastPTrue ? LastPTrue->getOperand (0 ).getReg () : AArch64::NoRegister);
4351
4355
4352
4356
// Elide NZCV spills if we know it is not used.
4353
4357
bool IsNZCVUsed = !UsedRegs.available (AArch64::NZCV);
@@ -4371,9 +4375,17 @@ static bool expandFillPPRFromZPRSlotPseudo(MachineBasicBlock &MBB,
4371
4375
.addImm (AArch64SysReg::NZCV)
4372
4376
.addReg (AArch64::NZCV, RegState::Implicit)
4373
4377
.getInstr ());
4374
- MachineInstrs.push_back (BuildMI (MBB, MI, DL, TII->get (AArch64::PTRUE_B))
4375
- .addReg (*PredReg, RegState::Define)
4376
- .addImm (31 ));
4378
+
4379
+ // Reuse previous ptrue if we know it has not been clobbered.
4380
+ if (LastPTrue) {
4381
+ assert (*PredReg == LastPTrue->getOperand (0 ).getReg ());
4382
+ LastPTrue->moveBefore (&MI);
4383
+ } else {
4384
+ LastPTrue = BuildMI (MBB, MI, DL, TII->get (AArch64::PTRUE_B))
4385
+ .addReg (*PredReg, RegState::Define)
4386
+ .addImm (31 );
4387
+ }
4388
+ MachineInstrs.push_back (LastPTrue);
4377
4389
MachineInstrs.push_back (
4378
4390
BuildMI (MBB, MI, DL, TII->get (AArch64::CMPNE_PPzZI_B))
4379
4391
.addReg (MI.getOperand (0 ).getReg (), RegState::Define)
@@ -4402,19 +4414,24 @@ static bool expandSMEPPRToZPRSpillPseudos(MachineBasicBlock &MBB,
4402
4414
LiveRegUnits UsedRegs (TRI);
4403
4415
UsedRegs.addLiveOuts (MBB);
4404
4416
bool HasPPRSpills = false ;
4417
+ MachineInstr *LastPTrue = nullptr ;
4405
4418
for (MachineInstr &MI : make_early_inc_range (reverse (MBB))) {
4406
4419
UsedRegs.stepBackward (MI);
4407
4420
switch (MI.getOpcode ()) {
4408
4421
case AArch64::FILL_PPR_FROM_ZPR_SLOT_PSEUDO:
4422
+ if (LastPTrue &&
4423
+ MI.definesRegister (LastPTrue->getOperand (0 ).getReg (), &TRI))
4424
+ LastPTrue = nullptr ;
4409
4425
HasPPRSpills |= expandFillPPRFromZPRSlotPseudo (MBB, MI, TRI, UsedRegs, SR,
4410
- SpillSlots);
4426
+ LastPTrue, SpillSlots);
4411
4427
MI.eraseFromParent ();
4412
4428
break ;
4413
4429
case AArch64::SPILL_PPR_TO_ZPR_SLOT_PSEUDO:
4414
4430
expandSpillPPRToZPRSlotPseudo (MBB, MI, TRI, UsedRegs, SR, SpillSlots);
4415
4431
MI.eraseFromParent ();
4416
- break ;
4432
+ [[fallthrough]] ;
4417
4433
default :
4434
+ LastPTrue = nullptr ;
4418
4435
break ;
4419
4436
}
4420
4437
}
0 commit comments