229 lines · cpp
1//===-- SparcRegisterInfo.cpp - SPARC Register Information ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the SPARC implementation of the TargetRegisterInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "SparcRegisterInfo.h"14#include "Sparc.h"15#include "SparcSubtarget.h"16#include "llvm/ADT/BitVector.h"17#include "llvm/CodeGen/MachineFrameInfo.h"18#include "llvm/CodeGen/MachineFunction.h"19#include "llvm/CodeGen/MachineInstrBuilder.h"20#include "llvm/CodeGen/TargetInstrInfo.h"21#include "llvm/IR/Type.h"22#include "llvm/Support/CommandLine.h"23#include "llvm/Support/ErrorHandling.h"24 25using namespace llvm;26 27#define GET_REGINFO_TARGET_DESC28#include "SparcGenRegisterInfo.inc"29 30static cl::opt<bool>31ReserveAppRegisters("sparc-reserve-app-registers", cl::Hidden, cl::init(false),32 cl::desc("Reserve application registers (%g2-%g4)"));33 34SparcRegisterInfo::SparcRegisterInfo(const SparcSubtarget &STI)35 : SparcGenRegisterInfo(SP::O7), Is64Bit(STI.is64Bit()) {}36 37const MCPhysReg*38SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {39 return CSR_SaveList;40}41 42const uint32_t *43SparcRegisterInfo::getCallPreservedMask(const MachineFunction &MF,44 CallingConv::ID CC) const {45 return CSR_RegMask;46}47 48const uint32_t*49SparcRegisterInfo::getRTCallPreservedMask(CallingConv::ID CC) const {50 return RTCSR_RegMask;51}52 53BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const {54 BitVector Reserved(getNumRegs());55 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();56 // FIXME: G1 reserved for now for large imm generation by frame code.57 Reserved.set(SP::G1);58 59 // G1-G4 can be used in applications.60 if (ReserveAppRegisters) {61 Reserved.set(SP::G2);62 Reserved.set(SP::G3);63 Reserved.set(SP::G4);64 }65 // G5 is not reserved in 64 bit mode.66 if (!Subtarget.is64Bit())67 Reserved.set(SP::G5);68 69 Reserved.set(SP::O6);70 Reserved.set(SP::I6);71 Reserved.set(SP::I7);72 Reserved.set(SP::G0);73 Reserved.set(SP::G6);74 Reserved.set(SP::G7);75 76 // Also reserve the register pair aliases covering the above77 // registers, with the same conditions.78 Reserved.set(SP::G0_G1);79 if (ReserveAppRegisters)80 Reserved.set(SP::G2_G3);81 if (ReserveAppRegisters || !Subtarget.is64Bit())82 Reserved.set(SP::G4_G5);83 84 Reserved.set(SP::O6_O7);85 Reserved.set(SP::I6_I7);86 Reserved.set(SP::G6_G7);87 88 // Unaliased double registers are not available in non-V9 targets.89 if (!Subtarget.isV9()) {90 for (unsigned n = 0; n != 16; ++n) {91 for (MCRegAliasIterator AI(SP::D16 + n, this, true); AI.isValid(); ++AI)92 Reserved.set(*AI);93 }94 }95 96 // Reserve ASR1-ASR3197 for (unsigned n = 0; n < 31; n++)98 Reserved.set(SP::ASR1 + n);99 100 for (TargetRegisterClass::iterator i = SP::IntRegsRegClass.begin();101 i != SP::IntRegsRegClass.end(); ++i) {102 if (MF.getSubtarget<SparcSubtarget>().isRegisterReserved(*i))103 markSuperRegs(Reserved, *i);104 }105 106 assert(checkAllSuperRegsMarked(Reserved));107 return Reserved;108}109 110bool SparcRegisterInfo::isReservedReg(const MachineFunction &MF,111 MCRegister Reg) const {112 return getReservedRegs(MF)[Reg];113}114 115const TargetRegisterClass *116SparcRegisterInfo::getPointerRegClass(unsigned Kind) const {117 assert(Kind == 0 && "this should only be used for default cases");118 return Is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;119}120 121static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II,122 MachineInstr &MI, const DebugLoc &dl,123 unsigned FIOperandNum, int Offset, unsigned FramePtr) {124 // Replace frame index with a frame pointer reference.125 if (Offset >= -4096 && Offset <= 4095) {126 // If the offset is small enough to fit in the immediate field, directly127 // encode it.128 MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);129 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);130 return;131 }132 133 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();134 135 // FIXME: it would be better to scavenge a register here instead of136 // reserving G1 all of the time.137 if (Offset >= 0) {138 // Emit nonnegaive immediates with sethi + or.139 // sethi %hi(Offset), %g1140 // add %g1, %fp, %g1141 // Insert G1+%lo(offset) into the user.142 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)143 .addImm(HI22(Offset));144 145 146 // Emit G1 = G1 + I6147 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)148 .addReg(FramePtr);149 // Insert: G1+%lo(offset) into the user.150 MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);151 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset));152 return;153 }154 155 // Emit Negative numbers with sethi + xor156 // sethi %hix(Offset), %g1157 // xor %g1, %lox(offset), %g1158 // add %g1, %fp, %g1159 // Insert: G1 + 0 into the user.160 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)161 .addImm(HIX22(Offset));162 BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1)163 .addReg(SP::G1).addImm(LOX10(Offset));164 165 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)166 .addReg(FramePtr);167 // Insert: G1+%lo(offset) into the user.168 MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);169 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);170}171 172 173bool174SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,175 int SPAdj, unsigned FIOperandNum,176 RegScavenger *RS) const {177 assert(SPAdj == 0 && "Unexpected");178 179 MachineInstr &MI = *II;180 DebugLoc dl = MI.getDebugLoc();181 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();182 MachineFunction &MF = *MI.getParent()->getParent();183 const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();184 const SparcFrameLowering *TFI = getFrameLowering(MF);185 186 Register FrameReg;187 int Offset;188 Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();189 190 Offset += MI.getOperand(FIOperandNum + 1).getImm();191 192 if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) {193 if (MI.getOpcode() == SP::STQFri) {194 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();195 Register SrcReg = MI.getOperand(2).getReg();196 Register SrcEvenReg = getSubReg(SrcReg, SP::sub_even64);197 Register SrcOddReg = getSubReg(SrcReg, SP::sub_odd64);198 MachineInstr *StMI =199 BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri))200 .addReg(FrameReg).addImm(0).addReg(SrcEvenReg);201 replaceFI(MF, *StMI, *StMI, dl, 0, Offset, FrameReg);202 MI.setDesc(TII.get(SP::STDFri));203 MI.getOperand(2).setReg(SrcOddReg);204 Offset += 8;205 } else if (MI.getOpcode() == SP::LDQFri) {206 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();207 Register DestReg = MI.getOperand(0).getReg();208 Register DestEvenReg = getSubReg(DestReg, SP::sub_even64);209 Register DestOddReg = getSubReg(DestReg, SP::sub_odd64);210 MachineInstr *LdMI =211 BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg)212 .addReg(FrameReg).addImm(0);213 replaceFI(MF, *LdMI, *LdMI, dl, 1, Offset, FrameReg);214 215 MI.setDesc(TII.get(SP::LDDFri));216 MI.getOperand(0).setReg(DestOddReg);217 Offset += 8;218 }219 }220 221 replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);222 // replaceFI never removes II223 return false;224}225 226Register SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const {227 return SP::I6;228}229