mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-31 12:30:06 +00:00
This pass is needed to break false dependencies. Without it, unlucky register assignment can result in wild (5x) swings in performance. This pass was trying to handle AVX but not getting it right. AVX doesn't have partial register defs, it has unused register reads in which the high bits of a source operand are copied into the unused bits of the dest. Fixing this requires conservative liveness analysis. This is awkard because the pass already has its own pseudo-liveness. However, proper liveness is expensive, and we would like to use a generic utility to compute it. The fix only invokes liveness on-demand. It is rare to detect a case that needs undef-read dependence breaking, but when it happens, it can be needed many times within a very large block. I think the existing heuristic which uses a register window of 16 is too conservative for loop-carried false dependencies. If the loop is a reduction. The out-of-order engine may be able to execute several loop iterations in parallel. However, I'll leave this tuning exercise for next time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192635 91177308-0d34-0410-b5e6-96231b3b80d8
700 lines
25 KiB
C++
700 lines
25 KiB
C++
//===-- X86RegisterInfo.cpp - X86 Register Information --------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the X86 implementation of the TargetRegisterInfo class.
|
|
// This file is responsible for the frame pointer elimination optimization
|
|
// on X86.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "X86RegisterInfo.h"
|
|
#include "X86.h"
|
|
#include "X86InstrBuilder.h"
|
|
#include "X86MachineFunctionInfo.h"
|
|
#include "X86Subtarget.h"
|
|
#include "X86TargetMachine.h"
|
|
#include "llvm/ADT/BitVector.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/ValueTypes.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Target/TargetFrameLowering.h"
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
#define GET_REGINFO_TARGET_DESC
|
|
#include "X86GenRegisterInfo.inc"
|
|
|
|
using namespace llvm;
|
|
|
|
cl::opt<bool>
|
|
ForceStackAlign("force-align-stack",
|
|
cl::desc("Force align the stack to the minimum alignment"
|
|
" needed for the function."),
|
|
cl::init(false), cl::Hidden);
|
|
|
|
static cl::opt<bool>
|
|
EnableBasePointer("x86-use-base-pointer", cl::Hidden, cl::init(true),
|
|
cl::desc("Enable use of a base pointer for complex stack frames"));
|
|
|
|
X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm)
|
|
: X86GenRegisterInfo((tm.getSubtarget<X86Subtarget>().is64Bit()
|
|
? X86::RIP : X86::EIP),
|
|
X86_MC::getDwarfRegFlavour(tm.getTargetTriple(), false),
|
|
X86_MC::getDwarfRegFlavour(tm.getTargetTriple(), true),
|
|
(tm.getSubtarget<X86Subtarget>().is64Bit()
|
|
? X86::RIP : X86::EIP)),
|
|
TM(tm) {
|
|
X86_MC::InitLLVM2SEHRegisterMapping(this);
|
|
|
|
// Cache some information.
|
|
const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
|
|
Is64Bit = Subtarget->is64Bit();
|
|
IsWin64 = Subtarget->isTargetWin64();
|
|
|
|
if (Is64Bit) {
|
|
SlotSize = 8;
|
|
StackPtr = X86::RSP;
|
|
FramePtr = X86::RBP;
|
|
} else {
|
|
SlotSize = 4;
|
|
StackPtr = X86::ESP;
|
|
FramePtr = X86::EBP;
|
|
}
|
|
// Use a callee-saved register as the base pointer. These registers must
|
|
// not conflict with any ABI requirements. For example, in 32-bit mode PIC
|
|
// requires GOT in the EBX register before function calls via PLT GOT pointer.
|
|
BasePtr = Is64Bit ? X86::RBX : X86::ESI;
|
|
}
|
|
|
|
/// getCompactUnwindRegNum - This function maps the register to the number for
|
|
/// compact unwind encoding. Return -1 if the register isn't valid.
|
|
int X86RegisterInfo::getCompactUnwindRegNum(unsigned RegNum, bool isEH) const {
|
|
switch (getLLVMRegNum(RegNum, isEH)) {
|
|
case X86::EBX: case X86::RBX: return 1;
|
|
case X86::ECX: case X86::R12: return 2;
|
|
case X86::EDX: case X86::R13: return 3;
|
|
case X86::EDI: case X86::R14: return 4;
|
|
case X86::ESI: case X86::R15: return 5;
|
|
case X86::EBP: case X86::RBP: return 6;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool
|
|
X86RegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
|
|
// ExeDepsFixer and PostRAScheduler require liveness.
|
|
return true;
|
|
}
|
|
|
|
int
|
|
X86RegisterInfo::getSEHRegNum(unsigned i) const {
|
|
return getEncodingValue(i);
|
|
}
|
|
|
|
const TargetRegisterClass *
|
|
X86RegisterInfo::getSubClassWithSubReg(const TargetRegisterClass *RC,
|
|
unsigned Idx) const {
|
|
// The sub_8bit sub-register index is more constrained in 32-bit mode.
|
|
// It behaves just like the sub_8bit_hi index.
|
|
if (!Is64Bit && Idx == X86::sub_8bit)
|
|
Idx = X86::sub_8bit_hi;
|
|
|
|
// Forward to TableGen's default version.
|
|
return X86GenRegisterInfo::getSubClassWithSubReg(RC, Idx);
|
|
}
|
|
|
|
const TargetRegisterClass *
|
|
X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
|
|
const TargetRegisterClass *B,
|
|
unsigned SubIdx) const {
|
|
// The sub_8bit sub-register index is more constrained in 32-bit mode.
|
|
if (!Is64Bit && SubIdx == X86::sub_8bit) {
|
|
A = X86GenRegisterInfo::getSubClassWithSubReg(A, X86::sub_8bit_hi);
|
|
if (!A)
|
|
return 0;
|
|
}
|
|
return X86GenRegisterInfo::getMatchingSuperRegClass(A, B, SubIdx);
|
|
}
|
|
|
|
const TargetRegisterClass*
|
|
X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) const{
|
|
// Don't allow super-classes of GR8_NOREX. This class is only used after
|
|
// extrating sub_8bit_hi sub-registers. The H sub-registers cannot be copied
|
|
// to the full GR8 register class in 64-bit mode, so we cannot allow the
|
|
// reigster class inflation.
|
|
//
|
|
// The GR8_NOREX class is always used in a way that won't be constrained to a
|
|
// sub-class, so sub-classes like GR8_ABCD_L are allowed to expand to the
|
|
// full GR8 class.
|
|
if (RC == &X86::GR8_NOREXRegClass)
|
|
return RC;
|
|
|
|
const TargetRegisterClass *Super = RC;
|
|
TargetRegisterClass::sc_iterator I = RC->getSuperClasses();
|
|
do {
|
|
switch (Super->getID()) {
|
|
case X86::GR8RegClassID:
|
|
case X86::GR16RegClassID:
|
|
case X86::GR32RegClassID:
|
|
case X86::GR64RegClassID:
|
|
case X86::FR32RegClassID:
|
|
case X86::FR64RegClassID:
|
|
case X86::RFP32RegClassID:
|
|
case X86::RFP64RegClassID:
|
|
case X86::RFP80RegClassID:
|
|
case X86::VR128RegClassID:
|
|
case X86::VR256RegClassID:
|
|
// Don't return a super-class that would shrink the spill size.
|
|
// That can happen with the vector and float classes.
|
|
if (Super->getSize() == RC->getSize())
|
|
return Super;
|
|
}
|
|
Super = *I++;
|
|
} while (Super);
|
|
return RC;
|
|
}
|
|
|
|
const TargetRegisterClass *
|
|
X86RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind)
|
|
const {
|
|
const X86Subtarget &Subtarget = TM.getSubtarget<X86Subtarget>();
|
|
switch (Kind) {
|
|
default: llvm_unreachable("Unexpected Kind in getPointerRegClass!");
|
|
case 0: // Normal GPRs.
|
|
if (Subtarget.isTarget64BitLP64())
|
|
return &X86::GR64RegClass;
|
|
return &X86::GR32RegClass;
|
|
case 1: // Normal GPRs except the stack pointer (for encoding reasons).
|
|
if (Subtarget.isTarget64BitLP64())
|
|
return &X86::GR64_NOSPRegClass;
|
|
return &X86::GR32_NOSPRegClass;
|
|
case 2: // Available for tailcall (not callee-saved GPRs).
|
|
if (Subtarget.isTargetWin64())
|
|
return &X86::GR64_TCW64RegClass;
|
|
else if (Subtarget.is64Bit())
|
|
return &X86::GR64_TCRegClass;
|
|
|
|
const Function *F = MF.getFunction();
|
|
bool hasHipeCC = (F ? F->getCallingConv() == CallingConv::HiPE : false);
|
|
if (hasHipeCC)
|
|
return &X86::GR32RegClass;
|
|
return &X86::GR32_TCRegClass;
|
|
}
|
|
}
|
|
|
|
const TargetRegisterClass *
|
|
X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
|
|
if (RC == &X86::CCRRegClass) {
|
|
if (Is64Bit)
|
|
return &X86::GR64RegClass;
|
|
else
|
|
return &X86::GR32RegClass;
|
|
}
|
|
return RC;
|
|
}
|
|
|
|
unsigned
|
|
X86RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
|
|
MachineFunction &MF) const {
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
|
|
unsigned FPDiff = TFI->hasFP(MF) ? 1 : 0;
|
|
switch (RC->getID()) {
|
|
default:
|
|
return 0;
|
|
case X86::GR32RegClassID:
|
|
return 4 - FPDiff;
|
|
case X86::GR64RegClassID:
|
|
return 12 - FPDiff;
|
|
case X86::VR128RegClassID:
|
|
return TM.getSubtarget<X86Subtarget>().is64Bit() ? 10 : 4;
|
|
case X86::VR64RegClassID:
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
const uint16_t *
|
|
X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|
switch (MF->getFunction()->getCallingConv()) {
|
|
case CallingConv::GHC:
|
|
case CallingConv::HiPE:
|
|
return CSR_NoRegs_SaveList;
|
|
|
|
case CallingConv::Intel_OCL_BI: {
|
|
bool HasAVX = TM.getSubtarget<X86Subtarget>().hasAVX();
|
|
bool HasAVX512 = TM.getSubtarget<X86Subtarget>().hasAVX512();
|
|
if (HasAVX512 && IsWin64)
|
|
return CSR_Win64_Intel_OCL_BI_AVX512_SaveList;
|
|
if (HasAVX512 && Is64Bit)
|
|
return CSR_64_Intel_OCL_BI_AVX512_SaveList;
|
|
if (HasAVX && IsWin64)
|
|
return CSR_Win64_Intel_OCL_BI_AVX_SaveList;
|
|
if (HasAVX && Is64Bit)
|
|
return CSR_64_Intel_OCL_BI_AVX_SaveList;
|
|
if (!HasAVX && !IsWin64 && Is64Bit)
|
|
return CSR_64_Intel_OCL_BI_SaveList;
|
|
break;
|
|
}
|
|
|
|
case CallingConv::Cold:
|
|
if (Is64Bit)
|
|
return CSR_MostRegs_64_SaveList;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
bool CallsEHReturn = MF->getMMI().callsEHReturn();
|
|
if (Is64Bit) {
|
|
if (IsWin64)
|
|
return CSR_Win64_SaveList;
|
|
if (CallsEHReturn)
|
|
return CSR_64EHRet_SaveList;
|
|
return CSR_64_SaveList;
|
|
}
|
|
if (CallsEHReturn)
|
|
return CSR_32EHRet_SaveList;
|
|
return CSR_32_SaveList;
|
|
}
|
|
|
|
const uint32_t*
|
|
X86RegisterInfo::getCallPreservedMask(CallingConv::ID CC) const {
|
|
bool HasAVX = TM.getSubtarget<X86Subtarget>().hasAVX();
|
|
bool HasAVX512 = TM.getSubtarget<X86Subtarget>().hasAVX512();
|
|
|
|
if (CC == CallingConv::Intel_OCL_BI) {
|
|
if (IsWin64 && HasAVX512)
|
|
return CSR_Win64_Intel_OCL_BI_AVX512_RegMask;
|
|
if (Is64Bit && HasAVX512)
|
|
return CSR_64_Intel_OCL_BI_AVX512_RegMask;
|
|
if (IsWin64 && HasAVX)
|
|
return CSR_Win64_Intel_OCL_BI_AVX_RegMask;
|
|
if (Is64Bit && HasAVX)
|
|
return CSR_64_Intel_OCL_BI_AVX_RegMask;
|
|
if (!HasAVX && !IsWin64 && Is64Bit)
|
|
return CSR_64_Intel_OCL_BI_RegMask;
|
|
}
|
|
if (CC == CallingConv::GHC || CC == CallingConv::HiPE)
|
|
return CSR_NoRegs_RegMask;
|
|
if (!Is64Bit)
|
|
return CSR_32_RegMask;
|
|
if (CC == CallingConv::Cold)
|
|
return CSR_MostRegs_64_RegMask;
|
|
if (IsWin64)
|
|
return CSR_Win64_RegMask;
|
|
return CSR_64_RegMask;
|
|
}
|
|
|
|
const uint32_t*
|
|
X86RegisterInfo::getNoPreservedMask() const {
|
|
return CSR_NoRegs_RegMask;
|
|
}
|
|
|
|
BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|
BitVector Reserved(getNumRegs());
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
|
|
// Set the stack-pointer register and its aliases as reserved.
|
|
for (MCSubRegIterator I(X86::RSP, this, /*IncludeSelf=*/true); I.isValid();
|
|
++I)
|
|
Reserved.set(*I);
|
|
|
|
// Set the instruction pointer register and its aliases as reserved.
|
|
for (MCSubRegIterator I(X86::RIP, this, /*IncludeSelf=*/true); I.isValid();
|
|
++I)
|
|
Reserved.set(*I);
|
|
|
|
// Set the frame-pointer register and its aliases as reserved if needed.
|
|
if (TFI->hasFP(MF)) {
|
|
for (MCSubRegIterator I(X86::RBP, this, /*IncludeSelf=*/true); I.isValid();
|
|
++I)
|
|
Reserved.set(*I);
|
|
}
|
|
|
|
// Set the base-pointer register and its aliases as reserved if needed.
|
|
if (hasBasePointer(MF)) {
|
|
CallingConv::ID CC = MF.getFunction()->getCallingConv();
|
|
const uint32_t* RegMask = getCallPreservedMask(CC);
|
|
if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
|
|
report_fatal_error(
|
|
"Stack realignment in presence of dynamic allocas is not supported with"
|
|
"this calling convention.");
|
|
|
|
for (MCSubRegIterator I(getBaseRegister(), this, /*IncludeSelf=*/true);
|
|
I.isValid(); ++I)
|
|
Reserved.set(*I);
|
|
}
|
|
|
|
// Mark the segment registers as reserved.
|
|
Reserved.set(X86::CS);
|
|
Reserved.set(X86::SS);
|
|
Reserved.set(X86::DS);
|
|
Reserved.set(X86::ES);
|
|
Reserved.set(X86::FS);
|
|
Reserved.set(X86::GS);
|
|
|
|
// Mark the floating point stack registers as reserved.
|
|
for (unsigned n = 0; n != 8; ++n)
|
|
Reserved.set(X86::ST0 + n);
|
|
|
|
// Reserve the registers that only exist in 64-bit mode.
|
|
if (!Is64Bit) {
|
|
// These 8-bit registers are part of the x86-64 extension even though their
|
|
// super-registers are old 32-bits.
|
|
Reserved.set(X86::SIL);
|
|
Reserved.set(X86::DIL);
|
|
Reserved.set(X86::BPL);
|
|
Reserved.set(X86::SPL);
|
|
|
|
for (unsigned n = 0; n != 8; ++n) {
|
|
// R8, R9, ...
|
|
for (MCRegAliasIterator AI(X86::R8 + n, this, true); AI.isValid(); ++AI)
|
|
Reserved.set(*AI);
|
|
|
|
// XMM8, XMM9, ...
|
|
for (MCRegAliasIterator AI(X86::XMM8 + n, this, true); AI.isValid(); ++AI)
|
|
Reserved.set(*AI);
|
|
}
|
|
}
|
|
if (!Is64Bit || !TM.getSubtarget<X86Subtarget>().hasAVX512()) {
|
|
for (unsigned n = 16; n != 32; ++n) {
|
|
for (MCRegAliasIterator AI(X86::XMM0 + n, this, true); AI.isValid(); ++AI)
|
|
Reserved.set(*AI);
|
|
}
|
|
}
|
|
|
|
return Reserved;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Stack Frame Processing methods
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool X86RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
|
|
if (!EnableBasePointer)
|
|
return false;
|
|
|
|
// When we need stack realignment and there are dynamic allocas, we can't
|
|
// reference off of the stack pointer, so we reserve a base pointer.
|
|
//
|
|
// This is also true if the function contain MS-style inline assembly. We
|
|
// do this because if any stack changes occur in the inline assembly, e.g.,
|
|
// "pusha", then any C local variable or C argument references in the
|
|
// inline assembly will be wrong because the SP is not properly tracked.
|
|
if ((needsStackRealignment(MF) && MFI->hasVarSizedObjects()) ||
|
|
MF.hasMSInlineAsm())
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
|
if (MF.getFunction()->hasFnAttribute("no-realign-stack"))
|
|
return false;
|
|
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
const MachineRegisterInfo *MRI = &MF.getRegInfo();
|
|
|
|
// Stack realignment requires a frame pointer. If we already started
|
|
// register allocation with frame pointer elimination, it is too late now.
|
|
if (!MRI->canReserveReg(FramePtr))
|
|
return false;
|
|
|
|
// If a base pointer is necessary. Check that it isn't too late to reserve
|
|
// it.
|
|
if (MFI->hasVarSizedObjects())
|
|
return MRI->canReserveReg(BasePtr);
|
|
return true;
|
|
}
|
|
|
|
bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
const Function *F = MF.getFunction();
|
|
unsigned StackAlign = TM.getFrameLowering()->getStackAlignment();
|
|
bool requiresRealignment =
|
|
((MFI->getMaxAlignment() > StackAlign) ||
|
|
F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
|
|
Attribute::StackAlignment));
|
|
|
|
// If we've requested that we force align the stack do so now.
|
|
if (ForceStackAlign)
|
|
return canRealignStack(MF);
|
|
|
|
return requiresRealignment && canRealignStack(MF);
|
|
}
|
|
|
|
bool X86RegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
|
|
unsigned Reg, int &FrameIdx) const {
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
|
|
if (Reg == FramePtr && TFI->hasFP(MF)) {
|
|
FrameIdx = MF.getFrameInfo()->getObjectIndexBegin();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|
int SPAdj, unsigned FIOperandNum,
|
|
RegScavenger *RS) const {
|
|
assert(SPAdj == 0 && "Unexpected");
|
|
|
|
MachineInstr &MI = *II;
|
|
MachineFunction &MF = *MI.getParent()->getParent();
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
|
|
unsigned BasePtr;
|
|
|
|
unsigned Opc = MI.getOpcode();
|
|
bool AfterFPPop = Opc == X86::TAILJMPm64 || Opc == X86::TAILJMPm;
|
|
if (hasBasePointer(MF))
|
|
BasePtr = (FrameIndex < 0 ? FramePtr : getBaseRegister());
|
|
else if (needsStackRealignment(MF))
|
|
BasePtr = (FrameIndex < 0 ? FramePtr : StackPtr);
|
|
else if (AfterFPPop)
|
|
BasePtr = StackPtr;
|
|
else
|
|
BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr);
|
|
|
|
// This must be part of a four operand memory reference. Replace the
|
|
// FrameIndex with base register with EBP. Add an offset to the offset.
|
|
MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
|
|
|
|
// Now add the frame object offset to the offset from EBP.
|
|
int FIOffset;
|
|
if (AfterFPPop) {
|
|
// Tail call jmp happens after FP is popped.
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
FIOffset = MFI->getObjectOffset(FrameIndex) - TFI->getOffsetOfLocalArea();
|
|
} else
|
|
FIOffset = TFI->getFrameIndexOffset(MF, FrameIndex);
|
|
|
|
if (MI.getOperand(FIOperandNum+3).isImm()) {
|
|
// Offset is a 32-bit integer.
|
|
int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm());
|
|
int Offset = FIOffset + Imm;
|
|
assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) &&
|
|
"Requesting 64-bit offset in 32-bit immediate!");
|
|
MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset);
|
|
} else {
|
|
// Offset is symbolic. This is extremely rare.
|
|
uint64_t Offset = FIOffset +
|
|
(uint64_t)MI.getOperand(FIOperandNum+3).getOffset();
|
|
MI.getOperand(FIOperandNum + 3).setOffset(Offset);
|
|
}
|
|
}
|
|
|
|
unsigned X86RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
|
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
|
return TFI->hasFP(MF) ? FramePtr : StackPtr;
|
|
}
|
|
|
|
namespace llvm {
|
|
unsigned getX86SubSuperRegister(unsigned Reg, MVT::SimpleValueType VT,
|
|
bool High) {
|
|
switch (VT) {
|
|
default: llvm_unreachable("Unexpected VT");
|
|
case MVT::i8:
|
|
if (High) {
|
|
switch (Reg) {
|
|
default: return getX86SubSuperRegister(Reg, MVT::i64);
|
|
case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
|
|
return X86::SI;
|
|
case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
|
|
return X86::DI;
|
|
case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
|
|
return X86::BP;
|
|
case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
|
|
return X86::SP;
|
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
|
|
return X86::AH;
|
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
|
|
return X86::DH;
|
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
|
|
return X86::CH;
|
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
|
|
return X86::BH;
|
|
}
|
|
} else {
|
|
switch (Reg) {
|
|
default: llvm_unreachable("Unexpected register");
|
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
|
|
return X86::AL;
|
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
|
|
return X86::DL;
|
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
|
|
return X86::CL;
|
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
|
|
return X86::BL;
|
|
case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
|
|
return X86::SIL;
|
|
case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
|
|
return X86::DIL;
|
|
case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
|
|
return X86::BPL;
|
|
case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
|
|
return X86::SPL;
|
|
case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
|
|
return X86::R8B;
|
|
case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
|
|
return X86::R9B;
|
|
case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
|
|
return X86::R10B;
|
|
case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
|
|
return X86::R11B;
|
|
case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
|
|
return X86::R12B;
|
|
case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
|
|
return X86::R13B;
|
|
case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
|
|
return X86::R14B;
|
|
case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
|
|
return X86::R15B;
|
|
}
|
|
}
|
|
case MVT::i16:
|
|
switch (Reg) {
|
|
default: llvm_unreachable("Unexpected register");
|
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
|
|
return X86::AX;
|
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
|
|
return X86::DX;
|
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
|
|
return X86::CX;
|
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
|
|
return X86::BX;
|
|
case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
|
|
return X86::SI;
|
|
case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
|
|
return X86::DI;
|
|
case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
|
|
return X86::BP;
|
|
case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
|
|
return X86::SP;
|
|
case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
|
|
return X86::R8W;
|
|
case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
|
|
return X86::R9W;
|
|
case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
|
|
return X86::R10W;
|
|
case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
|
|
return X86::R11W;
|
|
case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
|
|
return X86::R12W;
|
|
case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
|
|
return X86::R13W;
|
|
case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
|
|
return X86::R14W;
|
|
case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
|
|
return X86::R15W;
|
|
}
|
|
case MVT::i32:
|
|
switch (Reg) {
|
|
default: llvm_unreachable("Unexpected register");
|
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
|
|
return X86::EAX;
|
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
|
|
return X86::EDX;
|
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
|
|
return X86::ECX;
|
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
|
|
return X86::EBX;
|
|
case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
|
|
return X86::ESI;
|
|
case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
|
|
return X86::EDI;
|
|
case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
|
|
return X86::EBP;
|
|
case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
|
|
return X86::ESP;
|
|
case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
|
|
return X86::R8D;
|
|
case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
|
|
return X86::R9D;
|
|
case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
|
|
return X86::R10D;
|
|
case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
|
|
return X86::R11D;
|
|
case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
|
|
return X86::R12D;
|
|
case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
|
|
return X86::R13D;
|
|
case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
|
|
return X86::R14D;
|
|
case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
|
|
return X86::R15D;
|
|
}
|
|
case MVT::i64:
|
|
switch (Reg) {
|
|
default: llvm_unreachable("Unexpected register");
|
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
|
|
return X86::RAX;
|
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
|
|
return X86::RDX;
|
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
|
|
return X86::RCX;
|
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
|
|
return X86::RBX;
|
|
case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
|
|
return X86::RSI;
|
|
case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
|
|
return X86::RDI;
|
|
case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
|
|
return X86::RBP;
|
|
case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
|
|
return X86::RSP;
|
|
case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
|
|
return X86::R8;
|
|
case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
|
|
return X86::R9;
|
|
case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
|
|
return X86::R10;
|
|
case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
|
|
return X86::R11;
|
|
case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
|
|
return X86::R12;
|
|
case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
|
|
return X86::R13;
|
|
case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
|
|
return X86::R14;
|
|
case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
|
|
return X86::R15;
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned get512BitSuperRegister(unsigned Reg) {
|
|
if (Reg >= X86::XMM0 && Reg <= X86::XMM31)
|
|
return X86::ZMM0 + (Reg - X86::XMM0);
|
|
if (Reg >= X86::YMM0 && Reg <= X86::YMM31)
|
|
return X86::ZMM0 + (Reg - X86::YMM0);
|
|
if (Reg >= X86::ZMM0 && Reg <= X86::ZMM31)
|
|
return Reg;
|
|
llvm_unreachable("Unexpected SIMD register");
|
|
}
|
|
|
|
}
|