1251607Sdim//===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===// 2251607Sdim// 3251607Sdim// The LLVM Compiler Infrastructure 4251607Sdim// 5251607Sdim// This file is distributed under the University of Illinois Open Source 6251607Sdim// License. See LICENSE.TXT for details. 7251607Sdim// 8251607Sdim//===----------------------------------------------------------------------===// 9251607Sdim 10251607Sdim#include "SystemZRegisterInfo.h" 11251607Sdim#include "SystemZTargetMachine.h" 12251607Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 13251607Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 14251607Sdim 15251607Sdim#define GET_REGINFO_TARGET_DESC 16251607Sdim#include "SystemZGenRegisterInfo.inc" 17251607Sdim 18251607Sdimusing namespace llvm; 19251607Sdim 20251607SdimSystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm, 21251607Sdim const SystemZInstrInfo &tii) 22251607Sdim : SystemZGenRegisterInfo(SystemZ::R14D), TM(tm), TII(tii) {} 23251607Sdim 24251607Sdimconst uint16_t* 25251607SdimSystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 26251607Sdim static const uint16_t CalleeSavedRegs[] = { 27251607Sdim SystemZ::R6D, SystemZ::R7D, SystemZ::R8D, SystemZ::R9D, 28251607Sdim SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D, 29251607Sdim SystemZ::R14D, SystemZ::R15D, 30251607Sdim SystemZ::F8D, SystemZ::F9D, SystemZ::F10D, SystemZ::F11D, 31251607Sdim SystemZ::F12D, SystemZ::F13D, SystemZ::F14D, SystemZ::F15D, 32251607Sdim 0 33251607Sdim }; 34251607Sdim 35251607Sdim return CalleeSavedRegs; 36251607Sdim} 37251607Sdim 38251607SdimBitVector 39251607SdimSystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 40251607Sdim BitVector Reserved(getNumRegs()); 41251607Sdim const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 42251607Sdim 43251607Sdim if (TFI->hasFP(MF)) { 44251607Sdim // R11D is the frame pointer. Reserve all aliases. 45251607Sdim Reserved.set(SystemZ::R11D); 46251607Sdim Reserved.set(SystemZ::R11W); 47251607Sdim Reserved.set(SystemZ::R10Q); 48251607Sdim } 49251607Sdim 50251607Sdim // R15D is the stack pointer. Reserve all aliases. 51251607Sdim Reserved.set(SystemZ::R15D); 52251607Sdim Reserved.set(SystemZ::R15W); 53251607Sdim Reserved.set(SystemZ::R14Q); 54251607Sdim return Reserved; 55251607Sdim} 56251607Sdim 57251607Sdimbool 58251607SdimSystemZRegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, 59251607Sdim MachineBasicBlock::iterator SaveMBBI, 60251607Sdim MachineBasicBlock::iterator &UseMBBI, 61251607Sdim const TargetRegisterClass *RC, 62251607Sdim unsigned Reg) const { 63251607Sdim MachineFunction &MF = *MBB.getParent(); 64251607Sdim const SystemZFrameLowering *TFI = 65251607Sdim static_cast<const SystemZFrameLowering *>(TM.getFrameLowering()); 66251607Sdim unsigned Base = getFrameRegister(MF); 67251607Sdim uint64_t Offset = TFI->getEmergencySpillSlotOffset(MF); 68251607Sdim DebugLoc DL; 69251607Sdim 70251607Sdim unsigned LoadOpcode, StoreOpcode; 71251607Sdim TII.getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode); 72251607Sdim 73251607Sdim // The offset must always be in range of a 12-bit unsigned displacement. 74251607Sdim BuildMI(MBB, SaveMBBI, DL, TII.get(StoreOpcode)) 75251607Sdim .addReg(Reg, RegState::Kill).addReg(Base).addImm(Offset).addReg(0); 76251607Sdim BuildMI(MBB, UseMBBI, DL, TII.get(LoadOpcode), Reg) 77251607Sdim .addReg(Base).addImm(Offset).addReg(0); 78251607Sdim return true; 79251607Sdim} 80251607Sdim 81251607Sdimvoid 82251607SdimSystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, 83251607Sdim int SPAdj, unsigned FIOperandNum, 84251607Sdim RegScavenger *RS) const { 85251607Sdim assert(SPAdj == 0 && "Outgoing arguments should be part of the frame"); 86251607Sdim 87251607Sdim MachineBasicBlock &MBB = *MI->getParent(); 88251607Sdim MachineFunction &MF = *MBB.getParent(); 89251607Sdim const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 90251607Sdim DebugLoc DL = MI->getDebugLoc(); 91251607Sdim 92251607Sdim // Decompose the frame index into a base and offset. 93251607Sdim int FrameIndex = MI->getOperand(FIOperandNum).getIndex(); 94251607Sdim unsigned BasePtr = getFrameRegister(MF); 95251607Sdim int64_t Offset = (TFI->getFrameIndexOffset(MF, FrameIndex) + 96251607Sdim MI->getOperand(FIOperandNum + 1).getImm()); 97251607Sdim 98251607Sdim // Special handling of dbg_value instructions. 99251607Sdim if (MI->isDebugValue()) { 100251607Sdim MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false); 101251607Sdim MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 102251607Sdim return; 103251607Sdim } 104251607Sdim 105251607Sdim // See if the offset is in range, or if an equivalent instruction that 106251607Sdim // accepts the offset exists. 107251607Sdim unsigned Opcode = MI->getOpcode(); 108251607Sdim unsigned OpcodeForOffset = TII.getOpcodeForOffset(Opcode, Offset); 109251607Sdim if (OpcodeForOffset) 110251607Sdim MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 111251607Sdim else { 112251607Sdim // Create an anchor point that is in range. Start at 0xffff so that 113251607Sdim // can use LLILH to load the immediate. 114251607Sdim int64_t OldOffset = Offset; 115251607Sdim int64_t Mask = 0xffff; 116251607Sdim do { 117251607Sdim Offset = OldOffset & Mask; 118251607Sdim OpcodeForOffset = TII.getOpcodeForOffset(Opcode, Offset); 119251607Sdim Mask >>= 1; 120251607Sdim assert(Mask && "One offset must be OK"); 121251607Sdim } while (!OpcodeForOffset); 122251607Sdim 123251607Sdim unsigned ScratchReg = 124251607Sdim MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass); 125251607Sdim int64_t HighOffset = OldOffset - Offset; 126251607Sdim 127251607Sdim if (MI->getDesc().TSFlags & SystemZII::HasIndex 128251607Sdim && MI->getOperand(FIOperandNum + 2).getReg() == 0) { 129251607Sdim // Load the offset into the scratch register and use it as an index. 130251607Sdim // The scratch register then dies here. 131251607Sdim TII.loadImmediate(MBB, MI, ScratchReg, HighOffset); 132251607Sdim MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); 133251607Sdim MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg, 134251607Sdim false, false, true); 135251607Sdim } else { 136251607Sdim // Load the anchor address into a scratch register. 137251607Sdim unsigned LAOpcode = TII.getOpcodeForOffset(SystemZ::LA, HighOffset); 138251607Sdim if (LAOpcode) 139251607Sdim BuildMI(MBB, MI, DL, TII.get(LAOpcode),ScratchReg) 140251607Sdim .addReg(BasePtr).addImm(HighOffset).addReg(0); 141251607Sdim else { 142251607Sdim // Load the high offset into the scratch register and use it as 143251607Sdim // an index. 144251607Sdim TII.loadImmediate(MBB, MI, ScratchReg, HighOffset); 145251607Sdim BuildMI(MBB, MI, DL, TII.get(SystemZ::AGR),ScratchReg) 146251607Sdim .addReg(ScratchReg, RegState::Kill).addReg(BasePtr); 147251607Sdim } 148251607Sdim 149251607Sdim // Use the scratch register as the base. It then dies here. 150251607Sdim MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg, 151251607Sdim false, false, true); 152251607Sdim } 153251607Sdim } 154251607Sdim MI->setDesc(TII.get(OpcodeForOffset)); 155251607Sdim MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 156251607Sdim} 157251607Sdim 158251607Sdimunsigned 159251607SdimSystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 160251607Sdim const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 161251607Sdim return TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D; 162251607Sdim} 163