@@ -3062,44 +3062,67 @@ AArch64TargetLowering::EmitGetSMESaveSize(MachineInstr &MI,
30623062 return BB;
30633063}
30643064
3065+ // Helper function to find the instruction that defined a virtual register,
3066+ // stripping and accumulating optional offset.
3067+ // If unable to find such instruction, returns nullptr (Offset is unspecified).
3068+ static MachineInstr *stripAndAccumulateOffset(const MachineRegisterInfo &MRI,
3069+ Register Reg, int64_t &Offset) {
3070+ Offset = 0;
3071+ while (Reg.isVirtual()) {
3072+ MachineInstr *DefMI = MRI.getVRegDef(Reg);
3073+ assert(DefMI && "Virtual register definition not found");
3074+ unsigned Opcode = DefMI->getOpcode();
3075+
3076+ if (Opcode == AArch64::COPY) {
3077+ Reg = DefMI->getOperand(1).getReg();
3078+ continue;
3079+ }
3080+
3081+ // If this is neither a copy, nor inc/dec instruction, we are done.
3082+ if (Opcode != AArch64::ADDXri && Opcode != AArch64::SUBXri)
3083+ return DefMI;
3084+ // Inc/dec with shifted immediates are not handled.
3085+ if (DefMI->getOperand(3).getImm() != 0)
3086+ return DefMI;
3087+
3088+ int64_t Imm = DefMI->getOperand(2).getImm();
3089+ Offset += (Opcode == AArch64::ADDXri) ? Imm : -Imm;
3090+
3091+ Reg = DefMI->getOperand(1).getReg();
3092+ }
3093+ return nullptr;
3094+ }
3095+
3096+ static std::pair<Register, unsigned>
3097+ detectBlendComponents(const MachineRegisterInfo &MRI, Register Reg) {
3098+ int64_t Offset = 0;
3099+ MachineInstr *MaybeBlend = stripAndAccumulateOffset(MRI, Reg, Offset);
3100+ // This should be a plain copy, without adding any offset.
3101+ if (!MaybeBlend || Offset != 0)
3102+ return std::make_pair(Reg, 0);
3103+
3104+ // Detect blend(addr, imm) which is lowered as MOVK addr, #imm, 48.
3105+ if (MaybeBlend->getOpcode() != AArch64::MOVKXi ||
3106+ MaybeBlend->getOperand(3).getImm() != 48)
3107+ return std::make_pair(Reg, 0);
3108+
3109+ return std::make_pair(MaybeBlend->getOperand(1).getReg(),
3110+ MaybeBlend->getOperand(2).getImm());
3111+ }
3112+
30653113MachineBasicBlock *
30663114AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
30673115 MachineBasicBlock *BB) const {
30683116 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
30693117 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
30703118 const DebugLoc &DL = MI.getDebugLoc();
30713119
3072- // Find the unique register definition, skipping copies.
3073- auto GetUniqueDef = [&MRI](Register Reg) {
3074- for (;;) {
3075- MachineInstr *Def = MRI.getUniqueVRegDef(Reg);
3076- if (!Def || Def->getOpcode() != AArch64::COPY)
3077- return Def;
3078-
3079- Reg = Def->getOperand(1).getReg();
3080- }
3081- };
3082- // Find the unique register definition, skipping copies and increments.
3083- auto GetUniqueDefPlusOffset =
3084- [GetUniqueDef](Register Reg, int64_t &Offset) -> MachineInstr * {
3085- for (;;) {
3086- MachineInstr *Def = GetUniqueDef(Reg);
3087- if (!Def || Def->getOpcode() != AArch64::ADDXri)
3088- return Def;
3089-
3090- if (Def->getOperand(3).getImm() != 0)
3091- return nullptr; // shifted immediates are not handled
3092- Reg = Def->getOperand(1).getReg();
3093- Offset += Def->getOperand(2).getImm();
3094- }
3095- };
3096-
30973120 // Try to find a known address-setting instruction, accumulating the offset
30983121 // along the way. If no known pattern is found, keep everything as-is.
30993122
31003123 int64_t AddrOffset = 0;
31013124 MachineInstr *AddrDefInstr =
3102- GetUniqueDefPlusOffset( MI.getOperand(1).getReg(), AddrOffset);
3125+ stripAndAccumulateOffset(MRI, MI.getOperand(1).getReg(), AddrOffset);
31033126 if (!AddrDefInstr)
31043127 return BB;
31053128
@@ -3116,32 +3139,25 @@ AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
31163139 const GlobalValue *GV = AddrOp.getGlobal();
31173140 AddrOffset += AddrOp.getOffset();
31183141
3119- // Detect discriminator blend computation, if any.
3120- Register RegDisc = isPACWithZeroDisc(MI.getOpcode())
3121- ? AArch64::XZR
3122- : MI.getOperand(2).getReg();
3123- unsigned IntDisc = 0;
3124- MachineInstr *MaybeBlendDef =
3125- RegDisc == AArch64::XZR ? nullptr : GetUniqueDef(RegDisc);
3126- if (MaybeBlendDef && MaybeBlendDef->getOpcode() == AArch64::MOVKXi &&
3127- MaybeBlendDef->getOperand(3).getImm() == 48) {
3128- RegDisc = MaybeBlendDef->getOperand(1).getReg();
3129- IntDisc = MaybeBlendDef->getOperand(2).getImm();
3130- }
3142+ // Analyze the discriminator operand.
3143+ Register OriginalDisc = isPACWithZeroDisc(MI.getOpcode())
3144+ ? AArch64::XZR
3145+ : MI.getOperand(2).getReg();
3146+ auto [AddrDisc, IntDisc] = detectBlendComponents(MRI, OriginalDisc);
31313147
31323148 // MOVaddrPAC and LOADgotPAC pseudos are expanded so that they use X16/X17
31333149 // internally, thus their restrictions on the register class of $AddrDisc
3134- // operand are stricter than those of real PAC* instructions.
3135- if (RegDisc != AArch64::XZR) {
3150+ // operand are stricter than those of MOVKXi and PAC* instructions.
3151+ if (AddrDisc != AArch64::XZR) {
31363152 Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64noipRegClass);
3137- BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(RegDisc );
3138- RegDisc = TmpReg;
3153+ BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(AddrDisc );
3154+ AddrDisc = TmpReg;
31393155 }
31403156
31413157 BuildMI(*BB, MI, DL, TII->get(NewOpcode))
31423158 .addGlobalAddress(GV, AddrOffset, TargetFlags)
31433159 .addImm(getKeyForPACOpcode(MI.getOpcode()))
3144- .addReg(RegDisc )
3160+ .addReg(AddrDisc )
31453161 .addImm(IntDisc);
31463162
31473163 BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), MI.getOperand(0).getReg())
0 commit comments