@@ -3353,44 +3353,66 @@ AArch64TargetLowering::EmitGetSMESaveSize(MachineInstr &MI,
3353
3353
return BB;
3354
3354
}
3355
3355
3356
+ // Helper function to find the instruction that defined a virtual register,
3357
+ // stripping and accumulating optional offset.
3358
+ // If unable to find such instruction, returns nullptr (Offset is unspecified).
3359
+ static MachineInstr *stripAndAccumulateOffset(const MachineRegisterInfo &MRI,
3360
+ Register Reg, int64_t &Offset) {
3361
+ Offset = 0;
3362
+ while (Reg.isVirtual()) {
3363
+ MachineInstr *DefMI = MRI.getVRegDef(Reg);
3364
+ assert(DefMI && "Virtual register definition not found");
3365
+ unsigned Opcode = DefMI->getOpcode();
3366
+
3367
+ if (Opcode == AArch64::COPY) {
3368
+ Reg = DefMI->getOperand(1).getReg();
3369
+ continue;
3370
+ }
3371
+
3372
+ // If this is neither a copy, nor inc/dec instruction, we are done.
3373
+ if (Opcode != AArch64::ADDXri && Opcode != AArch64::SUBXri)
3374
+ return DefMI;
3375
+ // Inc/dec with shifted immediates are not handled.
3376
+ if (DefMI->getOperand(3).getImm() != 0)
3377
+ return DefMI;
3378
+
3379
+ int64_t Imm = DefMI->getOperand(2).getImm();
3380
+ Offset += (Opcode == AArch64::ADDXri) ? Imm : -Imm;
3381
+
3382
+ Reg = DefMI->getOperand(1).getReg();
3383
+ }
3384
+ return nullptr;
3385
+ }
3386
+
3387
+ static std::pair<Register, unsigned> detectBlendComponents(const MachineRegisterInfo &MRI, Register Reg) {
3388
+ int64_t Offset = 0;
3389
+ MachineInstr *MaybeBlend = stripAndAccumulateOffset(MRI, Reg, Offset);
3390
+ // This should be a plain copy, without adding any offset.
3391
+ if (!MaybeBlend || Offset != 0)
3392
+ return std::make_pair(Reg, 0);
3393
+
3394
+ // Detect blend(addr, imm) which is lowered as MOVK addr, #imm, 48.
3395
+ if (MaybeBlend->getOpcode() != AArch64::MOVKXi ||
3396
+ MaybeBlend->getOperand(3).getImm() != 48)
3397
+ return std::make_pair(Reg, 0);
3398
+
3399
+ return std::make_pair(MaybeBlend->getOperand(1).getReg(),
3400
+ MaybeBlend->getOperand(2).getImm());
3401
+ }
3402
+
3356
3403
MachineBasicBlock *
3357
3404
AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
3358
3405
MachineBasicBlock *BB) const {
3359
3406
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3360
3407
MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
3361
3408
const DebugLoc &DL = MI.getDebugLoc();
3362
3409
3363
- // Find the unique register definition, skipping copies.
3364
- auto GetUniqueDef = [&MRI](Register Reg) {
3365
- for (;;) {
3366
- MachineInstr *Def = MRI.getUniqueVRegDef(Reg);
3367
- if (!Def || Def->getOpcode() != AArch64::COPY)
3368
- return Def;
3369
-
3370
- Reg = Def->getOperand(1).getReg();
3371
- }
3372
- };
3373
- // Find the unique register definition, skipping copies and increments.
3374
- auto GetUniqueDefPlusOffset =
3375
- [GetUniqueDef](Register Reg, int64_t &Offset) -> MachineInstr * {
3376
- for (;;) {
3377
- MachineInstr *Def = GetUniqueDef(Reg);
3378
- if (!Def || Def->getOpcode() != AArch64::ADDXri)
3379
- return Def;
3380
-
3381
- if (Def->getOperand(3).getImm() != 0)
3382
- return nullptr; // shifted immediates are not handled
3383
- Reg = Def->getOperand(1).getReg();
3384
- Offset += Def->getOperand(2).getImm();
3385
- }
3386
- };
3387
-
3388
3410
// Try to find a known address-setting instruction, accumulating the offset
3389
3411
// along the way. If no known pattern is found, keep everything as-is.
3390
3412
3391
3413
int64_t AddrOffset = 0;
3392
3414
MachineInstr *AddrDefInstr =
3393
- GetUniqueDefPlusOffset( MI.getOperand(1).getReg(), AddrOffset);
3415
+ stripAndAccumulateOffset(MRI, MI.getOperand(1).getReg(), AddrOffset);
3394
3416
if (!AddrDefInstr)
3395
3417
return BB;
3396
3418
@@ -3407,32 +3429,25 @@ AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
3407
3429
const GlobalValue *GV = AddrOp.getGlobal();
3408
3430
AddrOffset += AddrOp.getOffset();
3409
3431
3410
- // Detect discriminator blend computation, if any .
3411
- Register RegDisc = isPACWithZeroDisc(MI.getOpcode())
3432
+ // Analyze the discriminator operand .
3433
+ Register OriginalDisc = isPACWithZeroDisc(MI.getOpcode())
3412
3434
? AArch64::XZR
3413
3435
: MI.getOperand(2).getReg();
3414
- unsigned IntDisc = 0;
3415
- MachineInstr *MaybeBlendDef =
3416
- RegDisc == AArch64::XZR ? nullptr : GetUniqueDef(RegDisc);
3417
- if (MaybeBlendDef && MaybeBlendDef->getOpcode() == AArch64::MOVKXi &&
3418
- MaybeBlendDef->getOperand(3).getImm() == 48) {
3419
- RegDisc = MaybeBlendDef->getOperand(1).getReg();
3420
- IntDisc = MaybeBlendDef->getOperand(2).getImm();
3421
- }
3436
+ auto [AddrDisc, IntDisc] = detectBlendComponents(MRI, OriginalDisc);
3422
3437
3423
3438
// MOVaddrPAC and LOADgotPAC pseudos are expanded so that they use X16/X17
3424
3439
// internally, thus their restrictions on the register class of $AddrDisc
3425
- // operand are stricter than those of real PAC* instructions.
3426
- if (RegDisc != AArch64::XZR) {
3440
+ // operand are stricter than those of MOVKXi and PAC* instructions.
3441
+ if (AddrDisc != AArch64::XZR) {
3427
3442
Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64noipRegClass);
3428
- BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(RegDisc );
3429
- RegDisc = TmpReg;
3443
+ BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(AddrDisc );
3444
+ AddrDisc = TmpReg;
3430
3445
}
3431
3446
3432
3447
BuildMI(*BB, MI, DL, TII->get(NewOpcode))
3433
3448
.addGlobalAddress(GV, AddrOffset, TargetFlags)
3434
3449
.addImm(getKeyForPACOpcode(MI.getOpcode()))
3435
- .addReg(RegDisc )
3450
+ .addReg(AddrDisc )
3436
3451
.addImm(IntDisc);
3437
3452
3438
3453
BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), MI.getOperand(0).getReg())
0 commit comments