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/IR/Function.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* MF) const {
assert(MF && "Invalid MachineFunction pointer.");
if (MF->getFunction()->getCallingConv() == CallingConv::AnyReg)
return CSR_ARM64_AllRegs_SaveList;
else
return CSR_ARM64_AAPCS_SaveList;
}
const uint32_t *
ARM64RegisterInfo::getCallPreservedMask(CallingConv::ID CC) const {
if (CC == CallingConv::AnyReg)
return CSR_ARM64_AllRegs_RegMask;
else
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;
if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP ||
MI.getOpcode() == TargetOpcode::PATCHPOINT) {
Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg,
true);
Offset += MI.getOperand(FIOperandNum + 1).getImm();
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false );
MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
return;
}
Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg);
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 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;
}
}
}