Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/lib/Target/X86/X86InstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8122,6 +8122,14 @@ MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
shouldPreventUndefRegUpdateMemFold(MF, MI)))
return nullptr;

// Do not fold a NDD instruction and a memory instruction with relocation to
// avoid emit APX relocation when the flag is disabled for backward
// compatibility.
uint64_t TSFlags = MI.getDesc().TSFlags;
if (!X86EnableAPXForRelocation && isMemInstrWithGOTPCREL(LoadMI) &&
X86II::hasNewDataDest(TSFlags))
return nullptr;

// Determine the alignment of the load.
Align Alignment;
unsigned LoadOpc = LoadMI.getOpcode();
Expand Down
34 changes: 34 additions & 0 deletions llvm/lib/Target/X86/X86InstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,40 @@ inline static bool isAddMemInstrWithRelocation(const MachineInstr &MI) {
return false;
}

inline static bool isMemInstrWithGOTPCREL(const MachineInstr &MI) {
unsigned Op = MI.getOpcode();
switch (Op) {
case X86::TEST32mr:
case X86::TEST64mr:
case X86::CMP32rm:
case X86::CMP64rm:
case X86::MOV32rm:
case X86::MOV64rm:
case X86::ADC32rm:
case X86::ADD32rm:
case X86::AND32rm:
case X86::OR32rm:
case X86::SBB32rm:
case X86::SUB32rm:
case X86::XOR32rm:
case X86::ADC64rm:
case X86::ADD64rm:
case X86::AND64rm:
case X86::OR64rm:
case X86::SBB64rm:
case X86::SUB64rm:
case X86::XOR64rm: {
int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
X86II::getOperandBias(MI.getDesc());
const MachineOperand &MO = MI.getOperand(X86::AddrDisp + MemOpNo);
if (MO.getTargetFlags() == X86II::MO_GOTPCREL)
return true;
break;
}
}
return false;
}

class X86InstrInfo final : public X86GenInstrInfo {
X86Subtarget &Subtarget;
const X86RegisterInfo RI;
Expand Down
22 changes: 22 additions & 0 deletions llvm/lib/Target/X86/X86RegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ static cl::opt<bool>
cl::desc("Disable two address hints for register "
"allocation"));

extern cl::opt<bool> X86EnableAPXForRelocation;

X86RegisterInfo::X86RegisterInfo(const Triple &TT)
: X86GenRegisterInfo((TT.isArch64Bit() ? X86::RIP : X86::EIP),
X86_MC::getDwarfRegFlavour(TT, false),
Expand Down Expand Up @@ -121,6 +123,11 @@ X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
if (RC == &X86::GR8_NOREXRegClass)
return RC;

// Keep using non-rex2 register class when APX feature (EGPR/NDD/NF) is not
// enabled for relocation.
if (!X86EnableAPXForRelocation && isNonRex2RegClass(RC))
return RC;

const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();

const TargetRegisterClass *Super = RC;
Expand Down Expand Up @@ -1258,3 +1265,18 @@ const TargetRegisterClass *X86RegisterInfo::constrainRegClassToNonRex2(
return &X86::GR64_NOREX2_NOSPRegClass;
}
}

bool X86RegisterInfo::isNonRex2RegClass(const TargetRegisterClass *RC) const {
switch (RC->getID()) {
default:
return false;
case X86::GR8_NOREX2RegClassID:
case X86::GR16_NOREX2RegClassID:
case X86::GR32_NOREX2RegClassID:
case X86::GR64_NOREX2RegClassID:
case X86::GR32_NOREX2_NOSPRegClassID:
case X86::GR64_NOREX2_NOSPRegClassID:
case X86::GR64_with_sub_16bit_in_GR16_NOREX2RegClassID:
return true;
}
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/X86/X86RegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ class X86RegisterInfo final : public X86GenRegisterInfo {

const TargetRegisterClass *
constrainRegClassToNonRex2(const TargetRegisterClass *RC) const;

bool isNonRex2RegClass(const TargetRegisterClass *RC) const;
};

} // End llvm namespace
Expand Down
31 changes: 25 additions & 6 deletions llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@ FunctionPass *llvm::createX86SuppressAPXForRelocationPass() {
return new X86SuppressAPXForRelocationPass();
}

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

// Suppress EGPR in operand 0 of PHI instruction to avoid APX relocation types
// emitted. 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. That
// may lead to emit APX relocation types which may break the backward
// compatibility with builtin linkers on existing OS.
static void suppressEGPRRegClassInRegUses(MachineRegisterInfo *MRI,
const X86Subtarget &ST,
Register Reg) {
for (MachineInstr &Use : MRI->use_instructions(Reg))
if (Use.getOpcode() == X86::PHI)
suppressEGPRRegClass(MRI, Use, ST, 0);
}

static bool handleInstructionWithEGPR(MachineFunction &MF,
const X86Subtarget &ST) {
if (!ST.hasEGPR())
return false;

MachineRegisterInfo *MRI = &MF.getRegInfo();
auto suppressEGPRInInstrWithReloc = [&](MachineInstr &MI,
ArrayRef<unsigned> OpNoArray) {
int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
Expand All @@ -94,7 +108,7 @@ static bool handleInstructionWithEGPR(MachineFunction &MF,
LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n "
<< MI);
for (unsigned OpNo : OpNoArray)
suppressEGPRRegClass(MF, MI, ST, OpNo);
suppressEGPRRegClass(MRI, MI, ST, OpNo);
LLVM_DEBUG(dbgs() << "to:\n " << MI << "\n");
}
};
Expand All @@ -117,6 +131,7 @@ static bool handleInstructionWithEGPR(MachineFunction &MF,
case X86::MOV32rm:
case X86::MOV64rm: {
suppressEGPRInInstrWithReloc(MI, {0});
suppressEGPRRegClassInRegUses(MRI, ST, MI.getOperand(0).getReg());
break;
}
case X86::ADC32rm:
Expand All @@ -134,6 +149,7 @@ static bool handleInstructionWithEGPR(MachineFunction &MF,
case X86::SUB64rm:
case X86::XOR64rm: {
suppressEGPRInInstrWithReloc(MI, {0, 1});
suppressEGPRRegClassInRegUses(MRI, ST, MI.getOperand(0).getReg());
break;
}
}
Expand Down Expand Up @@ -167,7 +183,8 @@ static bool handleNDDOrNFInstructions(MachineFunction &MF,
int MemOpNo = X86II::getMemoryOperandNo(MI.getDesc().TSFlags) +
X86II::getOperandBias(MI.getDesc());
const MachineOperand &MO = MI.getOperand(X86::AddrDisp + MemOpNo);
if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
if (MO.getTargetFlags() == X86II::MO_GOTTPOFF ||
MO.getTargetFlags() == X86II::MO_GOTPCREL) {
LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n "
<< MI);
Register Reg = MRI->createVirtualRegister(&X86::GR64_NOREX2RegClass);
Expand All @@ -178,7 +195,8 @@ static bool handleNDDOrNFInstructions(MachineFunction &MF,
MI.getOperand(1).setReg(Reg);
const MCInstrDesc &NewDesc = TII->get(X86::ADD64rm);
MI.setDesc(NewDesc);
suppressEGPRRegClass(MF, MI, ST, 0);
suppressEGPRRegClass(MRI, MI, ST, 0);
suppressEGPRRegClassInRegUses(MRI, ST, MI.getOperand(0).getReg());
MI.tieOperands(0, 1);
LLVM_DEBUG(dbgs() << "to:\n " << *CopyMIB << "\n");
LLVM_DEBUG(dbgs() << " " << MI << "\n");
Expand All @@ -191,7 +209,8 @@ static bool handleNDDOrNFInstructions(MachineFunction &MF,
if (MO.getTargetFlags() == X86II::MO_GOTTPOFF) {
LLVM_DEBUG(dbgs() << "Transform instruction with relocation type:\n "
<< MI);
suppressEGPRRegClass(MF, MI, ST, 0);
suppressEGPRRegClass(MRI, MI, ST, 0);
suppressEGPRRegClassInRegUses(MRI, ST, MI.getOperand(0).getReg());
Register Reg = MRI->createVirtualRegister(&X86::GR64_NOREX2RegClass);
[[maybe_unused]] MachineInstrBuilder CopyMIB =
BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
Expand Down
Loading