@@ -3062,44 +3062,67 @@ AArch64TargetLowering::EmitGetSMESaveSize(MachineInstr &MI,
3062
3062
return BB;
3063
3063
}
3064
3064
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
+
3065
3113
MachineBasicBlock *
3066
3114
AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
3067
3115
MachineBasicBlock *BB) const {
3068
3116
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3069
3117
MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
3070
3118
const DebugLoc &DL = MI.getDebugLoc();
3071
3119
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
-
3097
3120
// Try to find a known address-setting instruction, accumulating the offset
3098
3121
// along the way. If no known pattern is found, keep everything as-is.
3099
3122
3100
3123
int64_t AddrOffset = 0;
3101
3124
MachineInstr *AddrDefInstr =
3102
- GetUniqueDefPlusOffset( MI.getOperand(1).getReg(), AddrOffset);
3125
+ stripAndAccumulateOffset(MRI, MI.getOperand(1).getReg(), AddrOffset);
3103
3126
if (!AddrDefInstr)
3104
3127
return BB;
3105
3128
@@ -3116,32 +3139,25 @@ AArch64TargetLowering::tryRewritingPAC(MachineInstr &MI,
3116
3139
const GlobalValue *GV = AddrOp.getGlobal();
3117
3140
AddrOffset += AddrOp.getOffset();
3118
3141
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);
3131
3147
3132
3148
// MOVaddrPAC and LOADgotPAC pseudos are expanded so that they use X16/X17
3133
3149
// 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) {
3136
3152
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;
3139
3155
}
3140
3156
3141
3157
BuildMI(*BB, MI, DL, TII->get(NewOpcode))
3142
3158
.addGlobalAddress(GV, AddrOffset, TargetFlags)
3143
3159
.addImm(getKeyForPACOpcode(MI.getOpcode()))
3144
- .addReg(RegDisc )
3160
+ .addReg(AddrDisc )
3145
3161
.addImm(IntDisc);
3146
3162
3147
3163
BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), MI.getOperand(0).getReg())
0 commit comments