1249259Sdim//===- AArch64RegisterInfo.cpp - AArch64 Register Information -------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file contains the AArch64 implementation of the TargetRegisterInfo 11249259Sdim// class. 12249259Sdim// 13249259Sdim//===----------------------------------------------------------------------===// 14249259Sdim 15249259Sdim 16249259Sdim#include "AArch64RegisterInfo.h" 17249259Sdim#include "AArch64FrameLowering.h" 18249259Sdim#include "AArch64MachineFunctionInfo.h" 19249259Sdim#include "AArch64TargetMachine.h" 20249259Sdim#include "MCTargetDesc/AArch64MCTargetDesc.h" 21249259Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 22249259Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 23249259Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 24249259Sdim#include "llvm/CodeGen/RegisterScavenging.h" 25249259Sdim#include "llvm/ADT/BitVector.h" 26249259Sdim 27249259Sdim#define GET_REGINFO_TARGET_DESC 28249259Sdim#include "AArch64GenRegisterInfo.inc" 29249259Sdim 30249259Sdimusing namespace llvm; 31249259Sdim 32263508SdimAArch64RegisterInfo::AArch64RegisterInfo() 33263508Sdim : AArch64GenRegisterInfo(AArch64::X30) { 34249259Sdim} 35249259Sdim 36249259Sdimconst uint16_t * 37249259SdimAArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 38249259Sdim return CSR_PCS_SaveList; 39249259Sdim} 40249259Sdim 41249259Sdimconst uint32_t* 42249259SdimAArch64RegisterInfo::getCallPreservedMask(CallingConv::ID) const { 43249259Sdim return CSR_PCS_RegMask; 44249259Sdim} 45249259Sdim 46249259Sdimconst uint32_t *AArch64RegisterInfo::getTLSDescCallPreservedMask() const { 47249259Sdim return TLSDesc_RegMask; 48249259Sdim} 49249259Sdim 50249259Sdimconst TargetRegisterClass * 51249259SdimAArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { 52249259Sdim if (RC == &AArch64::FlagClassRegClass) 53249259Sdim return &AArch64::GPR64RegClass; 54249259Sdim 55249259Sdim return RC; 56249259Sdim} 57249259Sdim 58249259Sdim 59249259Sdim 60249259SdimBitVector 61249259SdimAArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { 62249259Sdim BitVector Reserved(getNumRegs()); 63249259Sdim const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 64249259Sdim 65249259Sdim Reserved.set(AArch64::XSP); 66249259Sdim Reserved.set(AArch64::WSP); 67249259Sdim 68249259Sdim Reserved.set(AArch64::XZR); 69249259Sdim Reserved.set(AArch64::WZR); 70249259Sdim 71249259Sdim if (TFI->hasFP(MF)) { 72249259Sdim Reserved.set(AArch64::X29); 73249259Sdim Reserved.set(AArch64::W29); 74249259Sdim } 75249259Sdim 76249259Sdim return Reserved; 77249259Sdim} 78249259Sdim 79249259Sdimvoid 80249259SdimAArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI, 81249259Sdim int SPAdj, 82249259Sdim unsigned FIOperandNum, 83249259Sdim RegScavenger *RS) const { 84249259Sdim assert(SPAdj == 0 && "Cannot deal with nonzero SPAdj yet"); 85249259Sdim MachineInstr &MI = *MBBI; 86249259Sdim MachineBasicBlock &MBB = *MI.getParent(); 87249259Sdim MachineFunction &MF = *MBB.getParent(); 88249259Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 89249259Sdim const AArch64FrameLowering *TFI = 90249259Sdim static_cast<const AArch64FrameLowering *>(MF.getTarget().getFrameLowering()); 91249259Sdim 92249259Sdim // In order to work out the base and offset for addressing, the FrameLowering 93249259Sdim // code needs to know (sometimes) whether the instruction is storing/loading a 94249259Sdim // callee-saved register, or whether it's a more generic 95249259Sdim // operation. Fortunately the frame indices are used *only* for that purpose 96249259Sdim // and are contiguous, so we can check here. 97249259Sdim const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 98249259Sdim int MinCSFI = 0; 99249259Sdim int MaxCSFI = -1; 100249259Sdim 101249259Sdim if (CSI.size()) { 102249259Sdim MinCSFI = CSI[0].getFrameIdx(); 103249259Sdim MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); 104249259Sdim } 105249259Sdim 106249259Sdim int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 107249259Sdim bool IsCalleeSaveOp = FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI; 108249259Sdim 109249259Sdim unsigned FrameReg; 110249259Sdim int64_t Offset; 111249259Sdim Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj, 112249259Sdim IsCalleeSaveOp); 113249259Sdim 114249259Sdim Offset += MI.getOperand(FIOperandNum + 1).getImm(); 115249259Sdim 116249259Sdim // DBG_VALUE instructions have no real restrictions so they can be handled 117249259Sdim // easily. 118249259Sdim if (MI.isDebugValue()) { 119249259Sdim MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/ false); 120249259Sdim MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 121249259Sdim return; 122249259Sdim } 123249259Sdim 124263508Sdim const AArch64InstrInfo &TII = 125263508Sdim *static_cast<const AArch64InstrInfo*>(MF.getTarget().getInstrInfo()); 126249259Sdim int MinOffset, MaxOffset, OffsetScale; 127249259Sdim if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s) { 128249259Sdim MinOffset = 0; 129249259Sdim MaxOffset = 0xfff; 130249259Sdim OffsetScale = 1; 131249259Sdim } else { 132249259Sdim // Load/store of a stack object 133249259Sdim TII.getAddressConstraints(MI, OffsetScale, MinOffset, MaxOffset); 134249259Sdim } 135249259Sdim 136249259Sdim // The frame lowering has told us a base and offset it thinks we should use to 137249259Sdim // access this variable, but it's still up to us to make sure the values are 138249259Sdim // legal for the instruction in question. 139249259Sdim if (Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) { 140249259Sdim unsigned BaseReg = 141249259Sdim MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass); 142249259Sdim emitRegUpdate(MBB, MBBI, MBBI->getDebugLoc(), TII, 143249259Sdim BaseReg, FrameReg, BaseReg, Offset); 144249259Sdim FrameReg = BaseReg; 145249259Sdim Offset = 0; 146249259Sdim } 147249259Sdim 148249259Sdim // Negative offsets are expected if we address from FP, but for 149249259Sdim // now this checks nothing has gone horribly wrong. 150249259Sdim assert(Offset >= 0 && "Unexpected negative offset from SP"); 151249259Sdim 152249259Sdim MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, true); 153249259Sdim MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale); 154249259Sdim} 155249259Sdim 156249259Sdimunsigned 157249259SdimAArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const { 158249259Sdim const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 159249259Sdim 160249259Sdim if (TFI->hasFP(MF)) 161249259Sdim return AArch64::X29; 162249259Sdim else 163249259Sdim return AArch64::XSP; 164249259Sdim} 165249259Sdim 166249259Sdimbool 167249259SdimAArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const { 168249259Sdim const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 169249259Sdim const AArch64FrameLowering *AFI 170249259Sdim = static_cast<const AArch64FrameLowering*>(TFI); 171249259Sdim return AFI->useFPForAddressing(MF); 172249259Sdim} 173