@@ -3353,44 +3353,67 @@ 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>
3388
+ detectBlendComponents(const MachineRegisterInfo &MRI, Register Reg) {
3389
+ int64_t Offset = 0;
3390
+ MachineInstr *MaybeBlend = stripAndAccumulateOffset(MRI, Reg, Offset);
3391
+ // This should be a plain copy, without adding any offset.
3392
+ if (!MaybeBlend || Offset != 0)
3393
+ return std::make_pair(Reg, 0);
3394
+
3395
+ // Detect blend(addr, imm) which is lowered as MOVK addr, #imm, 48.
3396
+ if (MaybeBlend->getOpcode() != AArch64::MOVKXi ||
3397
+ MaybeBlend->getOperand(3).getImm() != 48)
3398
+ return std::make_pair(Reg, 0);
3399
+
3400
+ return std::make_pair(MaybeBlend->getOperand(1).getReg(),
3401
+ MaybeBlend->getOperand(2).getImm());
3402
+ }
3403
+
3356
3404
MachineBasicBlock *
3357
3405
AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
3358
3406
MachineBasicBlock *BB) const {
3359
3407
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3360
3408
MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
3361
3409
const DebugLoc &DL = MI.getDebugLoc();
3362
3410
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
3411
// Try to find a known address-setting instruction, accumulating the offset
3389
3412
// along the way. If no known pattern is found, keep everything as-is.
3390
3413
3391
3414
int64_t AddrOffset = 0;
3392
3415
MachineInstr *AddrDefInstr =
3393
- GetUniqueDefPlusOffset( MI.getOperand(1).getReg(), AddrOffset);
3416
+ stripAndAccumulateOffset(MRI, MI.getOperand(1).getReg(), AddrOffset);
3394
3417
if (!AddrDefInstr)
3395
3418
return BB;
3396
3419
@@ -3407,32 +3430,25 @@ AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
3407
3430
const GlobalValue *GV = AddrOp.getGlobal();
3408
3431
AddrOffset += AddrOp.getOffset();
3409
3432
3410
- // Detect discriminator blend computation, if any.
3411
- Register RegDisc = isPACWithZeroDisc(MI.getOpcode())
3412
- ? AArch64::XZR
3413
- : 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
- }
3433
+ // Analyze the discriminator operand.
3434
+ Register OriginalDisc = isPACWithZeroDisc(MI.getOpcode())
3435
+ ? AArch64::XZR
3436
+ : MI.getOperand(2).getReg();
3437
+ auto [AddrDisc, IntDisc] = detectBlendComponents(MRI, OriginalDisc);
3422
3438
3423
3439
// MOVaddrPAC and LOADgotPAC pseudos are expanded so that they use X16/X17
3424
3440
// 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) {
3441
+ // operand are stricter than those of MOVKXi and PAC* instructions.
3442
+ if (AddrDisc != AArch64::XZR) {
3427
3443
Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64noipRegClass);
3428
- BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(RegDisc );
3429
- RegDisc = TmpReg;
3444
+ BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(AddrDisc );
3445
+ AddrDisc = TmpReg;
3430
3446
}
3431
3447
3432
3448
BuildMI(*BB, MI, DL, TII->get(NewOpcode))
3433
3449
.addGlobalAddress(GV, AddrOffset, TargetFlags)
3434
3450
.addImm(getKeyForPACOpcode(MI.getOpcode()))
3435
- .addReg(RegDisc )
3451
+ .addReg(AddrDisc )
3436
3452
.addImm(IntDisc);
3437
3453
3438
3454
BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), MI.getOperand(0).getReg())
0 commit comments