ARM64RegisterInfo.cpp [plain text]
#include "ARM64RegisterInfo.h"
#include "ARM64FrameLowering.h"
#include "ARM64InstrInfo.h"
#include "ARM64Subtarget.h"
#include "MCTargetDesc/ARM64AddressingModes.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetOptions.h"
#define GET_REGINFO_TARGET_DESC
#include "ARM64GenRegisterInfo.inc"
using namespace llvm;
ARM64RegisterInfo::ARM64RegisterInfo(const ARM64InstrInfo *tii,
const ARM64Subtarget *sti)
: ARM64GenRegisterInfo(ARM64::LR), TII(tii), STI(sti) {
}
const uint16_t *ARM64RegisterInfo::
getCalleeSavedRegs(const MachineFunction*) const {
return CSR_ARM64_AAPCS_SaveList;
}
const uint32_t *ARM64RegisterInfo::getCallPreservedMask(CallingConv::ID) const {
return CSR_ARM64_AAPCS_RegMask;
}
const uint32_t *ARM64RegisterInfo::getTLSCallPreservedMask() const {
if (STI->isTargetDarwin())
return CSR_ARM64_TLS_Darwin_RegMask;
assert(STI->isTargetELF() && "only expect Darwin or ELF TLS");
return CSR_ARM64_TLS_ELF_RegMask;
}
const uint32_t*
ARM64RegisterInfo::getThisReturnPreservedMask(CallingConv::ID) const {
return CSR_ARM64_AAPCS_ThisReturn_RegMask;
}
BitVector ARM64RegisterInfo::
getReservedRegs(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
BitVector Reserved(getNumRegs());
Reserved.set(ARM64::SP);
Reserved.set(ARM64::XZR);
Reserved.set(ARM64::WSP);
Reserved.set(ARM64::WZR);
if (TFI->hasFP(MF) || STI->isTargetDarwin()) {
Reserved.set(ARM64::FP);
Reserved.set(ARM64::W29);
}
if (STI->isTargetDarwin()) {
Reserved.set(ARM64::X18); Reserved.set(ARM64::W18);
}
if (hasBasePointer(MF)) {
Reserved.set(ARM64::X19);
Reserved.set(ARM64::W19);
}
return Reserved;
}
bool ARM64RegisterInfo::isReservedReg(const MachineFunction &MF,
unsigned Reg) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
switch (Reg) {
default: break;
case ARM64::SP:
case ARM64::XZR:
case ARM64::WSP:
case ARM64::WZR:
return true;
case ARM64::X18:
case ARM64::W18:
return STI->isTargetDarwin();
case ARM64::FP:
case ARM64::W29:
return TFI->hasFP(MF) || STI->isTargetDarwin();
case ARM64::W19:
case ARM64::X19:
return hasBasePointer(MF);
}
return false;
}
const TargetRegisterClass *
ARM64RegisterInfo::getPointerRegClass(const MachineFunction &MF,
unsigned Kind) const {
return &ARM64::GPR64RegClass;
}
const TargetRegisterClass *
ARM64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
if (RC == &ARM64::CCRRegClass)
return NULL; return RC;
}
unsigned ARM64RegisterInfo::getBaseRegister() const {
return ARM64::X19;
}
bool ARM64RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
if (MFI->hasVarSizedObjects()) {
if (MFI->getLocalFrameSize() < 256)
return false;
return true;
}
return false;
}
unsigned ARM64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
return TFI->hasFP(MF) ? ARM64::FP : ARM64::SP;
}
bool ARM64RegisterInfo::
requiresRegisterScavenging(const MachineFunction &MF) const {
return true;
}
bool ARM64RegisterInfo::
requiresVirtualBaseRegisters(const MachineFunction &MF) const {
return true;
}
bool ARM64RegisterInfo::
useFPForScavengingIndex(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return MFI->hasVarSizedObjects() && !hasBasePointer(MF);
}
bool ARM64RegisterInfo::
requiresFrameIndexScavenging(const MachineFunction &MF) const {
return true;
}
bool ARM64RegisterInfo::cannotEliminateFrame(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
if (MFI->hasCalls() ||
(MF.getTarget().Options.DisableFramePointerElim(MF) &&
MFI->adjustsStack()))
return true;
return MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken();
}
bool ARM64RegisterInfo::
needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const {
for (unsigned i = 0; !MI->getOperand(i).isFI(); ++i)
assert(i < MI->getNumOperands() &&"Instr doesn't have FrameIndex operand!");
if (!MI->mayLoad() && !MI->mayStore())
return false;
MachineFunction &MF = *MI->getParent()->getParent();
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
MachineFrameInfo *MFI = MF.getFrameInfo();
int64_t FPOffset = Offset - 16 * 20;
Offset += MFI->getLocalFrameSize();
Offset += 128;
if (TFI->hasFP(MF) && isFrameOffsetLegal(MI, FPOffset))
return false;
if (isFrameOffsetLegal(MI, Offset))
return false;
return true;
}
bool ARM64RegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
int64_t Offset) const {
assert(Offset <= INT_MAX && "Offset too big to fit in int.");
assert(MI && "Unable to get the legal offset for nil instruction.");
int SaveOffset = Offset;
return isARM64FrameOffsetLegal(*MI, SaveOffset) & ARM64FrameOffsetIsLegal;
}
void ARM64RegisterInfo::
materializeFrameBaseRegister(MachineBasicBlock *MBB,
unsigned BaseReg, int FrameIdx,
int64_t Offset) const {
MachineBasicBlock::iterator Ins = MBB->begin();
DebugLoc DL; if (Ins != MBB->end())
DL = Ins->getDebugLoc();
const MCInstrDesc &MCID = TII->get(ARM64::ADDXri);
MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
const MachineFunction &MF = *MBB->getParent();
MRI.constrainRegClass(BaseReg, TII->getRegClass(MCID, 0, this, MF));
unsigned Shifter = ARM64_AM::getShifterImm(ARM64_AM::LSL, 0);
BuildMI(*MBB, Ins, DL, MCID, BaseReg).addFrameIndex(FrameIdx).addImm(Offset)
.addImm(Shifter);
}
void
ARM64RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
unsigned BaseReg, int64_t Offset) const {
MachineInstr &MI = *I;
int Off = Offset; unsigned i = 0;
while (!MI.getOperand(i).isFI()) {
++i;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
bool Done = rewriteARM64FrameIndex(MI, i, BaseReg, Off, TII);
assert (Done && "Unable to resolve frame index!");
(void)Done;
}
void ARM64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
const ARM64FrameLowering *TFI =
static_cast<const ARM64FrameLowering*>(MF.getTarget().getFrameLowering());
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
unsigned FrameReg;
int Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg);
if (MI.isDebugValue()) {
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false );
MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
return;
}
if (rewriteARM64FrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
return;
assert((!RS || !RS->isScavengingFrameIndex(FrameIndex)) &&
"Emergency spill slot is out of reach");
unsigned ScratchReg =
MF.getRegInfo().createVirtualRegister(&ARM64::GPR64RegClass);
emitFrameOffset(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg,
Offset, TII);
MI.getOperand(FIOperandNum).ChangeToRegister(ScratchReg, false, false, true);
}
namespace llvm {
unsigned getWRegFromXReg(unsigned Reg) {
switch (Reg) {
case ARM64::X0: return ARM64::W0;
case ARM64::X1: return ARM64::W1;
case ARM64::X2: return ARM64::W2;
case ARM64::X3: return ARM64::W3;
case ARM64::X4: return ARM64::W4;
case ARM64::X5: return ARM64::W5;
case ARM64::X6: return ARM64::W6;
case ARM64::X7: return ARM64::W7;
case ARM64::X8: return ARM64::W8;
case ARM64::X9: return ARM64::W9;
case ARM64::X10: return ARM64::W10;
case ARM64::X11: return ARM64::W11;
case ARM64::X12: return ARM64::W12;
case ARM64::X13: return ARM64::W13;
case ARM64::X14: return ARM64::W14;
case ARM64::X15: return ARM64::W15;
case ARM64::X16: return ARM64::W16;
case ARM64::X17: return ARM64::W17;
case ARM64::X18: return ARM64::W18;
case ARM64::X19: return ARM64::W19;
case ARM64::X20: return ARM64::W20;
case ARM64::X21: return ARM64::W21;
case ARM64::X22: return ARM64::W22;
case ARM64::X23: return ARM64::W23;
case ARM64::X24: return ARM64::W24;
case ARM64::X25: return ARM64::W25;
case ARM64::X26: return ARM64::W26;
case ARM64::X27: return ARM64::W27;
case ARM64::X28: return ARM64::W28;
case ARM64::FP: return ARM64::W29;
case ARM64::LR: return ARM64::W30;
case ARM64::SP: return ARM64::WSP;
case ARM64::XZR: return ARM64::WZR;
}
return Reg;
}
unsigned getXRegFromWReg(unsigned Reg) {
switch (Reg) {
case ARM64::W0: return ARM64::X0;
case ARM64::W1: return ARM64::X1;
case ARM64::W2: return ARM64::X2;
case ARM64::W3: return ARM64::X3;
case ARM64::W4: return ARM64::X4;
case ARM64::W5: return ARM64::X5;
case ARM64::W6: return ARM64::X6;
case ARM64::W7: return ARM64::X7;
case ARM64::W8: return ARM64::X8;
case ARM64::W9: return ARM64::X9;
case ARM64::W10: return ARM64::X10;
case ARM64::W11: return ARM64::X11;
case ARM64::W12: return ARM64::X12;
case ARM64::W13: return ARM64::X13;
case ARM64::W14: return ARM64::X14;
case ARM64::W15: return ARM64::X15;
case ARM64::W16: return ARM64::X16;
case ARM64::W17: return ARM64::X17;
case ARM64::W18: return ARM64::X18;
case ARM64::W19: return ARM64::X19;
case ARM64::W20: return ARM64::X20;
case ARM64::W21: return ARM64::X21;
case ARM64::W22: return ARM64::X22;
case ARM64::W23: return ARM64::X23;
case ARM64::W24: return ARM64::X24;
case ARM64::W25: return ARM64::X25;
case ARM64::W26: return ARM64::X26;
case ARM64::W27: return ARM64::X27;
case ARM64::W28: return ARM64::X28;
case ARM64::W29: return ARM64::FP;
case ARM64::W30: return ARM64::LR;
case ARM64::WSP: return ARM64::SP;
case ARM64::WZR: return ARM64::XZR;
}
return Reg;
}
unsigned getBRegFromDReg(unsigned Reg) {
switch (Reg) {
case ARM64::D0: return ARM64::B0;
case ARM64::D1: return ARM64::B1;
case ARM64::D2: return ARM64::B2;
case ARM64::D3: return ARM64::B3;
case ARM64::D4: return ARM64::B4;
case ARM64::D5: return ARM64::B5;
case ARM64::D6: return ARM64::B6;
case ARM64::D7: return ARM64::B7;
case ARM64::D8: return ARM64::B8;
case ARM64::D9: return ARM64::B9;
case ARM64::D10: return ARM64::B10;
case ARM64::D11: return ARM64::B11;
case ARM64::D12: return ARM64::B12;
case ARM64::D13: return ARM64::B13;
case ARM64::D14: return ARM64::B14;
case ARM64::D15: return ARM64::B15;
case ARM64::D16: return ARM64::B16;
case ARM64::D17: return ARM64::B17;
case ARM64::D18: return ARM64::B18;
case ARM64::D19: return ARM64::B19;
case ARM64::D20: return ARM64::B20;
case ARM64::D21: return ARM64::B21;
case ARM64::D22: return ARM64::B22;
case ARM64::D23: return ARM64::B23;
case ARM64::D24: return ARM64::B24;
case ARM64::D25: return ARM64::B25;
case ARM64::D26: return ARM64::B26;
case ARM64::D27: return ARM64::B27;
case ARM64::D28: return ARM64::B28;
case ARM64::D29: return ARM64::B29;
case ARM64::D30: return ARM64::B30;
case ARM64::D31: return ARM64::B31;
}
return Reg;
}
unsigned getDRegFromBReg(unsigned Reg) {
switch (Reg) {
case ARM64::B0: return ARM64::D0;
case ARM64::B1: return ARM64::D1;
case ARM64::B2: return ARM64::D2;
case ARM64::B3: return ARM64::D3;
case ARM64::B4: return ARM64::D4;
case ARM64::B5: return ARM64::D5;
case ARM64::B6: return ARM64::D6;
case ARM64::B7: return ARM64::D7;
case ARM64::B8: return ARM64::D8;
case ARM64::B9: return ARM64::D9;
case ARM64::B10: return ARM64::D10;
case ARM64::B11: return ARM64::D11;
case ARM64::B12: return ARM64::D12;
case ARM64::B13: return ARM64::D13;
case ARM64::B14: return ARM64::D14;
case ARM64::B15: return ARM64::D15;
case ARM64::B16: return ARM64::D16;
case ARM64::B17: return ARM64::D17;
case ARM64::B18: return ARM64::D18;
case ARM64::B19: return ARM64::D19;
case ARM64::B20: return ARM64::D20;
case ARM64::B21: return ARM64::D21;
case ARM64::B22: return ARM64::D22;
case ARM64::B23: return ARM64::D23;
case ARM64::B24: return ARM64::D24;
case ARM64::B25: return ARM64::D25;
case ARM64::B26: return ARM64::D26;
case ARM64::B27: return ARM64::D27;
case ARM64::B28: return ARM64::D28;
case ARM64::B29: return ARM64::D29;
case ARM64::B30: return ARM64::D30;
case ARM64::B31: return ARM64::D31;
}
return Reg;
}
unsigned ARM64RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
switch (RC->getID()) {
default:
return 0;
case ARM64::GPR32RegClassID:
case ARM64::GPR32spRegClassID:
case ARM64::GPR32allRegClassID:
case ARM64::GPR64spRegClassID:
case ARM64::GPR64allRegClassID:
case ARM64::GPR64RegClassID:
case ARM64::GPR32commonRegClassID:
case ARM64::GPR64commonRegClassID:
return 32 - 1 - (TFI->hasFP(MF) || STI->isTargetDarwin()) - STI->isTargetDarwin() - hasBasePointer(MF); case ARM64::FPR8RegClassID:
case ARM64::FPR16RegClassID:
case ARM64::FPR32RegClassID:
case ARM64::FPR64RegClassID:
case ARM64::FPR128RegClassID:
return 32;
case ARM64::DDRegClassID:
case ARM64::DDDRegClassID:
case ARM64::DDDDRegClassID:
case ARM64::QQRegClassID:
case ARM64::QQQRegClassID:
case ARM64::QQQQRegClassID:
return 32;
case ARM64::FPR128_loRegClassID:
return 16;
}
}
}