Path: blob/main/contrib/llvm-project/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp
96353 views
//===-- SparcRegisterInfo.cpp - SPARC Register Information ----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the SPARC implementation of the TargetRegisterInfo class.9//10//===----------------------------------------------------------------------===//1112#include "SparcRegisterInfo.h"13#include "Sparc.h"14#include "SparcSubtarget.h"15#include "llvm/ADT/BitVector.h"16#include "llvm/CodeGen/MachineFrameInfo.h"17#include "llvm/CodeGen/MachineFunction.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/TargetInstrInfo.h"20#include "llvm/IR/Type.h"21#include "llvm/Support/CommandLine.h"22#include "llvm/Support/ErrorHandling.h"2324using namespace llvm;2526#define GET_REGINFO_TARGET_DESC27#include "SparcGenRegisterInfo.inc"2829static cl::opt<bool>30ReserveAppRegisters("sparc-reserve-app-registers", cl::Hidden, cl::init(false),31cl::desc("Reserve application registers (%g2-%g4)"));3233SparcRegisterInfo::SparcRegisterInfo() : SparcGenRegisterInfo(SP::O7) {}3435const MCPhysReg*36SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {37return CSR_SaveList;38}3940const uint32_t *41SparcRegisterInfo::getCallPreservedMask(const MachineFunction &MF,42CallingConv::ID CC) const {43return CSR_RegMask;44}4546const uint32_t*47SparcRegisterInfo::getRTCallPreservedMask(CallingConv::ID CC) const {48return RTCSR_RegMask;49}5051BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const {52BitVector Reserved(getNumRegs());53const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();54// FIXME: G1 reserved for now for large imm generation by frame code.55Reserved.set(SP::G1);5657// G1-G4 can be used in applications.58if (ReserveAppRegisters) {59Reserved.set(SP::G2);60Reserved.set(SP::G3);61Reserved.set(SP::G4);62}63// G5 is not reserved in 64 bit mode.64if (!Subtarget.is64Bit())65Reserved.set(SP::G5);6667Reserved.set(SP::O6);68Reserved.set(SP::I6);69Reserved.set(SP::I7);70Reserved.set(SP::G0);71Reserved.set(SP::G6);72Reserved.set(SP::G7);7374// Also reserve the register pair aliases covering the above75// registers, with the same conditions.76Reserved.set(SP::G0_G1);77if (ReserveAppRegisters)78Reserved.set(SP::G2_G3);79if (ReserveAppRegisters || !Subtarget.is64Bit())80Reserved.set(SP::G4_G5);8182Reserved.set(SP::O6_O7);83Reserved.set(SP::I6_I7);84Reserved.set(SP::G6_G7);8586// Unaliased double registers are not available in non-V9 targets.87if (!Subtarget.isV9()) {88for (unsigned n = 0; n != 16; ++n) {89for (MCRegAliasIterator AI(SP::D16 + n, this, true); AI.isValid(); ++AI)90Reserved.set(*AI);91}92}9394// Reserve ASR1-ASR3195for (unsigned n = 0; n < 31; n++)96Reserved.set(SP::ASR1 + n);9798for (TargetRegisterClass::iterator i = SP::IntRegsRegClass.begin();99i != SP::IntRegsRegClass.end(); ++i) {100if (MF.getSubtarget<SparcSubtarget>().isRegisterReserved(*i))101markSuperRegs(Reserved, *i);102}103104assert(checkAllSuperRegsMarked(Reserved));105return Reserved;106}107108bool SparcRegisterInfo::isReservedReg(const MachineFunction &MF,109MCRegister Reg) const {110return getReservedRegs(MF)[Reg];111}112113const TargetRegisterClass*114SparcRegisterInfo::getPointerRegClass(const MachineFunction &MF,115unsigned Kind) const {116const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();117return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;118}119120static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II,121MachineInstr &MI, const DebugLoc &dl,122unsigned FIOperandNum, int Offset, unsigned FramePtr) {123// Replace frame index with a frame pointer reference.124if (Offset >= -4096 && Offset <= 4095) {125// If the offset is small enough to fit in the immediate field, directly126// encode it.127MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);128MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);129return;130}131132const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();133134// FIXME: it would be better to scavenge a register here instead of135// reserving G1 all of the time.136if (Offset >= 0) {137// Emit nonnegaive immediates with sethi + or.138// sethi %hi(Offset), %g1139// add %g1, %fp, %g1140// Insert G1+%lo(offset) into the user.141BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)142.addImm(HI22(Offset));143144145// Emit G1 = G1 + I6146BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)147.addReg(FramePtr);148// Insert: G1+%lo(offset) into the user.149MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);150MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset));151return;152}153154// Emit Negative numbers with sethi + xor155// sethi %hix(Offset), %g1156// xor %g1, %lox(offset), %g1157// add %g1, %fp, %g1158// Insert: G1 + 0 into the user.159BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)160.addImm(HIX22(Offset));161BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1)162.addReg(SP::G1).addImm(LOX10(Offset));163164BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)165.addReg(FramePtr);166// Insert: G1+%lo(offset) into the user.167MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);168MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);169}170171172bool173SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,174int SPAdj, unsigned FIOperandNum,175RegScavenger *RS) const {176assert(SPAdj == 0 && "Unexpected");177178MachineInstr &MI = *II;179DebugLoc dl = MI.getDebugLoc();180int FrameIndex = MI.getOperand(FIOperandNum).getIndex();181MachineFunction &MF = *MI.getParent()->getParent();182const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();183const SparcFrameLowering *TFI = getFrameLowering(MF);184185Register FrameReg;186int Offset;187Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();188189Offset += MI.getOperand(FIOperandNum + 1).getImm();190191if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) {192if (MI.getOpcode() == SP::STQFri) {193const TargetInstrInfo &TII = *Subtarget.getInstrInfo();194Register SrcReg = MI.getOperand(2).getReg();195Register SrcEvenReg = getSubReg(SrcReg, SP::sub_even64);196Register SrcOddReg = getSubReg(SrcReg, SP::sub_odd64);197MachineInstr *StMI =198BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri))199.addReg(FrameReg).addImm(0).addReg(SrcEvenReg);200replaceFI(MF, *StMI, *StMI, dl, 0, Offset, FrameReg);201MI.setDesc(TII.get(SP::STDFri));202MI.getOperand(2).setReg(SrcOddReg);203Offset += 8;204} else if (MI.getOpcode() == SP::LDQFri) {205const TargetInstrInfo &TII = *Subtarget.getInstrInfo();206Register DestReg = MI.getOperand(0).getReg();207Register DestEvenReg = getSubReg(DestReg, SP::sub_even64);208Register DestOddReg = getSubReg(DestReg, SP::sub_odd64);209MachineInstr *LdMI =210BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg)211.addReg(FrameReg).addImm(0);212replaceFI(MF, *LdMI, *LdMI, dl, 1, Offset, FrameReg);213214MI.setDesc(TII.get(SP::LDDFri));215MI.getOperand(0).setReg(DestOddReg);216Offset += 8;217}218}219220replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);221// replaceFI never removes II222return false;223}224225Register SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const {226return SP::I6;227}228229// Sparc has no architectural need for stack realignment support,230// except that LLVM unfortunately currently implements overaligned231// stack objects by depending upon stack realignment support.232// If that ever changes, this can probably be deleted.233bool SparcRegisterInfo::canRealignStack(const MachineFunction &MF) const {234if (!TargetRegisterInfo::canRealignStack(MF))235return false;236237// Sparc always has a fixed frame pointer register, so don't need to238// worry about needing to reserve it. [even if we don't have a frame239// pointer for our frame, it still cannot be used for other things,240// or register window traps will be SADNESS.]241242// If there's a reserved call frame, we can use SP to access locals.243if (getFrameLowering(MF)->hasReservedCallFrame(MF))244return true;245246// Otherwise, we'd need a base pointer, but those aren't implemented247// for SPARC at the moment.248249return false;250}251252253