Changeset View
Changeset View
Standalone View
Standalone View
contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 24,988 Lines • ▼ Show 20 Lines | |||||
bool | bool | ||||
X86TargetLowering::isVectorClearMaskLegal(const SmallVectorImpl<int> &Mask, | X86TargetLowering::isVectorClearMaskLegal(const SmallVectorImpl<int> &Mask, | ||||
EVT VT) const { | EVT VT) const { | ||||
// Just delegate to the generic legality, clear masks aren't special. | // Just delegate to the generic legality, clear masks aren't special. | ||||
return isShuffleMaskLegal(Mask, VT); | return isShuffleMaskLegal(Mask, VT); | ||||
} | } | ||||
bool X86TargetLowering::areJTsAllowed(const Function *Fn) const { | |||||
// If the subtarget is using retpolines, we need to not generate jump tables. | |||||
if (Subtarget.useRetpoline()) | |||||
return false; | |||||
// Otherwise, fallback on the generic logic. | |||||
return TargetLowering::areJTsAllowed(Fn); | |||||
} | |||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// X86 Scheduler Hooks | // X86 Scheduler Hooks | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
/// Utility function to emit xbegin specifying the start of an RTM region. | /// Utility function to emit xbegin specifying the start of an RTM region. | ||||
static MachineBasicBlock *emitXBegin(MachineInstr &MI, MachineBasicBlock *MBB, | static MachineBasicBlock *emitXBegin(MachineInstr &MI, MachineBasicBlock *MBB, | ||||
const TargetInstrInfo *TII) { | const TargetInstrInfo *TII) { | ||||
DebugLoc DL = MI.getDebugLoc(); | DebugLoc DL = MI.getDebugLoc(); | ||||
▲ Show 20 Lines • Show All 1,215 Lines • ▼ Show 20 Lines | if (Subtarget.is64Bit()) { | ||||
addDirectMem(MIB, X86::EAX); | addDirectMem(MIB, X86::EAX); | ||||
MIB.addReg(X86::EAX, RegState::ImplicitDefine).addRegMask(RegMask); | MIB.addReg(X86::EAX, RegState::ImplicitDefine).addRegMask(RegMask); | ||||
} | } | ||||
MI.eraseFromParent(); // The pseudo instruction is gone now. | MI.eraseFromParent(); // The pseudo instruction is gone now. | ||||
return BB; | return BB; | ||||
} | } | ||||
static unsigned getOpcodeForRetpoline(unsigned RPOpc) { | |||||
switch (RPOpc) { | |||||
case X86::RETPOLINE_CALL32: | |||||
return X86::CALLpcrel32; | |||||
case X86::RETPOLINE_CALL64: | |||||
return X86::CALL64pcrel32; | |||||
case X86::RETPOLINE_TCRETURN32: | |||||
return X86::TCRETURNdi; | |||||
case X86::RETPOLINE_TCRETURN64: | |||||
return X86::TCRETURNdi64; | |||||
} | |||||
llvm_unreachable("not retpoline opcode"); | |||||
} | |||||
static const char *getRetpolineSymbol(const X86Subtarget &Subtarget, | |||||
unsigned Reg) { | |||||
if (Subtarget.useRetpolineExternalThunk()) { | |||||
// When using an external thunk for retpolines, we pick names that match the | |||||
// names GCC happens to use as well. This helps simplify the implementation | |||||
// of the thunks for kernels where they have no easy ability to create | |||||
// aliases and are doing non-trivial configuration of the thunk's body. For | |||||
// example, the Linux kernel will do boot-time hot patching of the thunk | |||||
// bodies and cannot easily export aliases of these to loaded modules. | |||||
// | |||||
// Note that at any point in the future, we may need to change the semantics | |||||
// of how we implement retpolines and at that time will likely change the | |||||
// name of the called thunk. Essentially, there is no hard guarantee that | |||||
// LLVM will generate calls to specific thunks, we merely make a best-effort | |||||
// attempt to help out kernels and other systems where duplicating the | |||||
// thunks is costly. | |||||
switch (Reg) { | |||||
case X86::EAX: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__x86_indirect_thunk_eax"; | |||||
case X86::ECX: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__x86_indirect_thunk_ecx"; | |||||
case X86::EDX: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__x86_indirect_thunk_edx"; | |||||
case X86::EDI: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__x86_indirect_thunk_edi"; | |||||
case X86::R11: | |||||
assert(Subtarget.is64Bit() && "Should not be using a 64-bit thunk!"); | |||||
return "__x86_indirect_thunk_r11"; | |||||
} | |||||
llvm_unreachable("unexpected reg for retpoline"); | |||||
} | |||||
// When targeting an internal COMDAT thunk use an LLVM-specific name. | |||||
switch (Reg) { | |||||
case X86::EAX: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__llvm_retpoline_eax"; | |||||
case X86::ECX: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__llvm_retpoline_ecx"; | |||||
case X86::EDX: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__llvm_retpoline_edx"; | |||||
case X86::EDI: | |||||
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!"); | |||||
return "__llvm_retpoline_edi"; | |||||
case X86::R11: | |||||
assert(Subtarget.is64Bit() && "Should not be using a 64-bit thunk!"); | |||||
return "__llvm_retpoline_r11"; | |||||
} | |||||
llvm_unreachable("unexpected reg for retpoline"); | |||||
} | |||||
MachineBasicBlock * | MachineBasicBlock * | ||||
X86TargetLowering::EmitLoweredRetpoline(MachineInstr &MI, | |||||
MachineBasicBlock *BB) const { | |||||
// Copy the virtual register into the R11 physical register and | |||||
// call the retpoline thunk. | |||||
DebugLoc DL = MI.getDebugLoc(); | |||||
const X86InstrInfo *TII = Subtarget.getInstrInfo(); | |||||
unsigned CalleeVReg = MI.getOperand(0).getReg(); | |||||
unsigned Opc = getOpcodeForRetpoline(MI.getOpcode()); | |||||
// Find an available scratch register to hold the callee. On 64-bit, we can | |||||
// just use R11, but we scan for uses anyway to ensure we don't generate | |||||
// incorrect code. On 32-bit, we use one of EAX, ECX, or EDX that isn't | |||||
// already a register use operand to the call to hold the callee. If none | |||||
// are available, use EDI instead. EDI is chosen because EBX is the PIC base | |||||
// register and ESI is the base pointer to realigned stack frames with VLAs. | |||||
SmallVector<unsigned, 3> AvailableRegs; | |||||
if (Subtarget.is64Bit()) | |||||
AvailableRegs.push_back(X86::R11); | |||||
else | |||||
AvailableRegs.append({X86::EAX, X86::ECX, X86::EDX, X86::EDI}); | |||||
// Zero out any registers that are already used. | |||||
for (const auto &MO : MI.operands()) { | |||||
if (MO.isReg() && MO.isUse()) | |||||
for (unsigned &Reg : AvailableRegs) | |||||
if (Reg == MO.getReg()) | |||||
Reg = 0; | |||||
} | |||||
// Choose the first remaining non-zero available register. | |||||
unsigned AvailableReg = 0; | |||||
for (unsigned MaybeReg : AvailableRegs) { | |||||
if (MaybeReg) { | |||||
AvailableReg = MaybeReg; | |||||
break; | |||||
} | |||||
} | |||||
if (!AvailableReg) | |||||
report_fatal_error("calling convention incompatible with retpoline, no " | |||||
"available registers"); | |||||
const char *Symbol = getRetpolineSymbol(Subtarget, AvailableReg); | |||||
BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), AvailableReg) | |||||
.addReg(CalleeVReg); | |||||
MI.getOperand(0).ChangeToES(Symbol); | |||||
MI.setDesc(TII->get(Opc)); | |||||
MachineInstrBuilder(*BB->getParent(), &MI) | |||||
.addReg(AvailableReg, RegState::Implicit | RegState::Kill); | |||||
return BB; | |||||
} | |||||
MachineBasicBlock * | |||||
X86TargetLowering::emitEHSjLjSetJmp(MachineInstr &MI, | X86TargetLowering::emitEHSjLjSetJmp(MachineInstr &MI, | ||||
MachineBasicBlock *MBB) const { | MachineBasicBlock *MBB) const { | ||||
DebugLoc DL = MI.getDebugLoc(); | DebugLoc DL = MI.getDebugLoc(); | ||||
MachineFunction *MF = MBB->getParent(); | MachineFunction *MF = MBB->getParent(); | ||||
const TargetInstrInfo *TII = Subtarget.getInstrInfo(); | const TargetInstrInfo *TII = Subtarget.getInstrInfo(); | ||||
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); | const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); | ||||
MachineRegisterInfo &MRI = MF->getRegInfo(); | MachineRegisterInfo &MRI = MF->getRegInfo(); | ||||
▲ Show 20 Lines • Show All 447 Lines • ▼ Show 20 Lines | X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, | ||||
case X86::TCRETURNri64: | case X86::TCRETURNri64: | ||||
case X86::TCRETURNmi64: | case X86::TCRETURNmi64: | ||||
return BB; | return BB; | ||||
case X86::TLS_addr32: | case X86::TLS_addr32: | ||||
case X86::TLS_addr64: | case X86::TLS_addr64: | ||||
case X86::TLS_base_addr32: | case X86::TLS_base_addr32: | ||||
case X86::TLS_base_addr64: | case X86::TLS_base_addr64: | ||||
return EmitLoweredTLSAddr(MI, BB); | return EmitLoweredTLSAddr(MI, BB); | ||||
case X86::RETPOLINE_CALL32: | |||||
case X86::RETPOLINE_CALL64: | |||||
case X86::RETPOLINE_TCRETURN32: | |||||
case X86::RETPOLINE_TCRETURN64: | |||||
return EmitLoweredRetpoline(MI, BB); | |||||
case X86::CATCHRET: | case X86::CATCHRET: | ||||
return EmitLoweredCatchRet(MI, BB); | return EmitLoweredCatchRet(MI, BB); | ||||
case X86::CATCHPAD: | case X86::CATCHPAD: | ||||
return EmitLoweredCatchPad(MI, BB); | return EmitLoweredCatchPad(MI, BB); | ||||
case X86::SEG_ALLOCA_32: | case X86::SEG_ALLOCA_32: | ||||
case X86::SEG_ALLOCA_64: | case X86::SEG_ALLOCA_64: | ||||
return EmitLoweredSegAlloca(MI, BB); | return EmitLoweredSegAlloca(MI, BB); | ||||
case X86::TLSCall_32: | case X86::TLSCall_32: | ||||
▲ Show 20 Lines • Show All 10,090 Lines • Show Last 20 Lines |