Skip to content

Commit 80547cd

Browse files
authored
[X86][APX] Fix issues of suppressing APX for relocation (#139285)
1. There is ADD64rm_ND instruction emitted with GOTPCREL relocation. Handled it in "Suppress APX for relocation" pass and transformed it to ADD64rm with register operand in non-rex2 register class. The relocation type R_X86_64_CODE_6_GOTPCRELX will be added later for APX enabled with relocation. 2. The register class for operands in instruction with relocation is updated to non-rex2 one in "Suppress APX for relocation" pass, but it may be updated/recomputed to larger register class (like GR64_NOREX2RegClass to GR64RegClass). Fixed by not updating the register class if it's non-rex2 register class and APX support for relocation is disabled. 3. After "Suppress APX for relocation" pass, the instruction with relocation may be folded with add NDD instruction to a add NDD instruction with relocation. The later will be emitted to instruction with APX relocation type which breaks backward compatibility. Fixed by not folding instruction with GOTPCREL relocation with NDD instruction. 4. If the register in operand 0 of instruction with relocation is used in the PHI instruction, it may be replaced with operand 0 of PHI instruction (maybe EGPR) after PHI elimination and Machine Copy Propagation pass. Fixed by suppressing EGPR in operand 0 of PHI instruction to avoid APX relocation types emitted.
1 parent cede236 commit 80547cd

File tree

7 files changed

+388
-8
lines changed

7 files changed

+388
-8
lines changed

llvm/lib/Target/X86/X86InstrInfo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8122,6 +8122,14 @@ MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
81228122
shouldPreventUndefRegUpdateMemFold(MF, MI)))
81238123
return nullptr;
81248124

8125+
// Do not fold a NDD instruction and a memory instruction with relocation to
8126+
// avoid emit APX relocation when the flag is disabled for backward
8127+
// compatibility.
8128+
uint64_t TSFlags = MI.getDesc().TSFlags;
8129+
if (!X86EnableAPXForRelocation && isMemInstrWithGOTPCREL(LoadMI) &&
8130+
X86II::hasNewDataDest(TSFlags))
8131+
return nullptr;
8132+
81258133
// Determine the alignment of the load.
81268134
Align Alignment;
81278135
unsigned LoadOpc = LoadMI.getOpcode();

llvm/lib/Target/X86/X86InstrInfo.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,40 @@ inline static bool isAddMemInstrWithRelocation(const MachineInstr &MI) {
187187
return false;
188188
}
189189

190+
inline static bool isMemInstrWithGOTPCREL(const MachineInstr &MI) {
191+
unsigned Op = MI.getOpcode();
192+
switch (Op) {
193+
case X86::TEST32mr:
194+
case X86::TEST64mr:
195+
case X86::CMP32rm:
196+
case X86::CMP64rm:
197+
case X86::MOV32rm:
198+
case X86::MOV64rm:
199+
case X86::ADC32rm:
200+
case X86::ADD32rm:
201+
case X86::AND32rm:
202+
case X86::OR32rm:
203+
case X86::SBB32rm:
204+
case X86::SUB32rm:
205+
case X86::XOR32rm:
206+
case X86::ADC64rm:
207+
case X86::ADD64rm:
208+
case X86::AND64rm:
209+
case X86::OR64rm:
210+
case X86::SBB64rm:
211+
case X86::SUB64rm:
212+
case X86::XOR64rm: {
213+
int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
214+
X86II::getOperandBias(MI.getDesc());
215+
const MachineOperand &MO = MI.getOperand(X86::AddrDisp + MemOpNo);
216+
if (MO.getTargetFlags() == X86II::MO_GOTPCREL)
217+
return true;
218+
break;
219+
}
220+
}
221+
return false;
222+
}
223+
190224
class X86InstrInfo final : public X86GenInstrInfo {
191225
X86Subtarget &Subtarget;
192226
const X86RegisterInfo RI;

llvm/lib/Target/X86/X86RegisterInfo.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ static cl::opt<bool>
5050
cl::desc("Disable two address hints for register "
5151
"allocation"));
5252

53+
extern cl::opt<bool> X86EnableAPXForRelocation;
54+
5355
X86RegisterInfo::X86RegisterInfo(const Triple &TT)
5456
: X86GenRegisterInfo((TT.isArch64Bit() ? X86::RIP : X86::EIP),
5557
X86_MC::getDwarfRegFlavour(TT, false),
@@ -121,6 +123,11 @@ X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
121123
if (RC == &X86::GR8_NOREXRegClass)
122124
return RC;
123125

126+
// Keep using non-rex2 register class when APX feature (EGPR/NDD/NF) is not
127+
// enabled for relocation.
128+
if (!X86EnableAPXForRelocation && isNonRex2RegClass(RC))
129+
return RC;
130+
124131
const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
125132

126133
const TargetRegisterClass *Super = RC;
@@ -1258,3 +1265,18 @@ const TargetRegisterClass *X86RegisterInfo::constrainRegClassToNonRex2(
12581265
return &X86::GR64_NOREX2_NOSPRegClass;
12591266
}
12601267
}
1268+
1269+
bool X86RegisterInfo::isNonRex2RegClass(const TargetRegisterClass *RC) const {
1270+
switch (RC->getID()) {
1271+
default:
1272+
return false;
1273+
case X86::GR8_NOREX2RegClassID:
1274+
case X86::GR16_NOREX2RegClassID:
1275+
case X86::GR32_NOREX2RegClassID:
1276+
case X86::GR64_NOREX2RegClassID:
1277+
case X86::GR32_NOREX2_NOSPRegClassID:
1278+
case X86::GR64_NOREX2_NOSPRegClassID:
1279+
case X86::GR64_with_sub_16bit_in_GR16_NOREX2RegClassID:
1280+
return true;
1281+
}
1282+
}

llvm/lib/Target/X86/X86RegisterInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ class X86RegisterInfo final : public X86GenRegisterInfo {
178178

179179
const TargetRegisterClass *
180180
constrainRegClassToNonRex2(const TargetRegisterClass *RC) const;
181+
182+
bool isNonRex2RegClass(const TargetRegisterClass *RC) const;
181183
};
182184

183185
} // End llvm namespace

llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ FunctionPass *llvm::createX86SuppressAPXForRelocationPass() {
6565
return new X86SuppressAPXForRelocationPass();
6666
}
6767

68-
static void suppressEGPRRegClass(MachineFunction &MF, MachineInstr &MI,
68+
static void suppressEGPRRegClass(MachineRegisterInfo *MRI, MachineInstr &MI,
6969
const X86Subtarget &ST, unsigned int OpNum) {
70-
MachineRegisterInfo *MRI = &MF.getRegInfo();
7170
Register Reg = MI.getOperand(OpNum).getReg();
7271
if (!Reg.isVirtual()) {
7372
assert(!X86II::isApxExtendedReg(Reg) && "APX EGPR is used unexpectedly.");
@@ -79,11 +78,30 @@ static void suppressEGPRRegClass(MachineFunction &MF, MachineInstr &MI,
7978
MRI->setRegClass(Reg, NewRC);
8079
}
8180

81+
// Suppress EGPR in operand 0 of uses to avoid APX relocation types emitted. The
82+
// register in operand 0 of instruction with relocation may be replaced with
83+
// operand 0 of uses which may be EGPR. That may lead to emit APX relocation
84+
// types which breaks the backward compatibility with builtin linkers on
85+
// existing OS. For example, the register in operand 0 of instruction with
86+
// relocation is used in PHI instruction, and it may be replaced with operand 0
87+
// of PHI instruction after PHI elimination and Machine Copy Propagation pass.
88+
static void suppressEGPRRegClassInRegAndUses(MachineRegisterInfo *MRI,
89+
MachineInstr &MI,
90+
const X86Subtarget &ST,
91+
unsigned int OpNum) {
92+
suppressEGPRRegClass(MRI, MI, ST, OpNum);
93+
Register Reg = MI.getOperand(OpNum).getReg();
94+
for (MachineInstr &Use : MRI->use_instructions(Reg))
95+
if (Use.getOpcode() == X86::PHI)
96+
suppressEGPRRegClass(MRI, Use, ST, 0);
97+
}
98+
8299
static bool handleInstructionWithEGPR(MachineFunction &MF,
83100
const X86Subtarget &ST) {
84101
if (!ST.hasEGPR())
85102
return false;
86103

104+
MachineRegisterInfo *MRI = &MF.getRegInfo();
87105
auto suppressEGPRInInstrWithReloc = [&](MachineInstr &MI,
88106
ArrayRef<unsigned> OpNoArray) {
89107
int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
@@ -94,7 +112,7 @@ static bool handleInstructionWithEGPR(MachineFunction &MF,
94112
LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n "
95113
<< MI);
96114
for (unsigned OpNo : OpNoArray)
97-
suppressEGPRRegClass(MF, MI, ST, OpNo);
115+
suppressEGPRRegClassInRegAndUses(MRI, MI, ST, OpNo);
98116
LLVM_DEBUG(dbgs() << "to:\n " << MI << "\n");
99117
}
100118
};
@@ -167,7 +185,8 @@ static bool handleNDDOrNFInstructions(MachineFunction &MF,
167185
int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
168186
X86II::getOperandBias(MI.getDesc());
169187
const MachineOperand &MO = MI.getOperand(X86::AddrDisp + MemOpNo);
170-
if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
188+
if (MO.getTargetFlags() == X86II::MO_GOTTPOFF ||
189+
MO.getTargetFlags() == X86II::MO_GOTPCREL) {
171190
LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n "
172191
<< MI);
173192
Register Reg = MRI->createVirtualRegister(&X86::GR64_NOREX2RegClass);
@@ -178,7 +197,7 @@ static bool handleNDDOrNFInstructions(MachineFunction &MF,
178197
MI.getOperand(1).setReg(Reg);
179198
const MCInstrDesc &NewDesc = TII->get(X86::ADD64rm);
180199
MI.setDesc(NewDesc);
181-
suppressEGPRRegClass(MF, MI, ST, 0);
200+
suppressEGPRRegClassInRegAndUses(MRI, MI, ST, 0);
182201
MI.tieOperands(0, 1);
183202
LLVM_DEBUG(dbgs() << "to:\n " << *CopyMIB << "\n");
184203
LLVM_DEBUG(dbgs() << " " << MI << "\n");
@@ -191,7 +210,7 @@ static bool handleNDDOrNFInstructions(MachineFunction &MF,
191210
if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
192211
LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n "
193212
<< MI);
194-
suppressEGPRRegClass(MF, MI, ST, 0);
213+
suppressEGPRRegClassInRegAndUses(MRI, MI, ST, 0);
195214
Register Reg = MRI->createVirtualRegister(&X86::GR64_NOREX2RegClass);
196215
[[maybe_unused]] MachineInstrBuilder CopyMIB =
197216
BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),

0 commit comments

Comments
 (0)