292 lines · cpp
1//===-- CSKYRegisterInfo.h - CSKY Register Information Impl ---*- C++ -*---===//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 CSKY implementation of the TargetRegisterInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "CSKYRegisterInfo.h"14#include "CSKY.h"15#include "CSKYSubtarget.h"16#include "llvm/CodeGen/MachineFrameInfo.h"17#include "llvm/CodeGen/MachineFunction.h"18#include "llvm/CodeGen/RegisterScavenging.h"19#include "llvm/MC/MCContext.h"20 21#define GET_REGINFO_TARGET_DESC22#include "CSKYGenRegisterInfo.inc"23 24using namespace llvm;25 26CSKYRegisterInfo::CSKYRegisterInfo()27 : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {}28 29const uint32_t *30CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF,31 CallingConv::ID Id) const {32 const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();33 if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())34 return CSR_GPR_FPR64_RegMask;35 if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())36 return CSR_GPR_FPR32_RegMask;37 return CSR_I32_RegMask;38}39 40Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const {41 const TargetFrameLowering *TFI = getFrameLowering(MF);42 return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14;43}44 45BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const {46 const CSKYFrameLowering *TFI = getFrameLowering(MF);47 const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();48 BitVector Reserved(getNumRegs());49 50 // Reserve the base register if we need to allocate51 // variable-sized objects at runtime.52 if (TFI->hasBP(MF))53 markSuperRegs(Reserved, CSKY::R7); // bp54 55 if (TFI->hasFP(MF))56 markSuperRegs(Reserved, CSKY::R8); // fp57 58 if (!STI.hasE2()) {59 for (unsigned i = 0; i < 6; i++)60 markSuperRegs(Reserved, CSKY::R8 + i); // R8 - R1361 }62 63 markSuperRegs(Reserved, CSKY::R14); // sp64 markSuperRegs(Reserved, CSKY::R15); // lr65 66 if (!STI.hasHighRegisters()) {67 for (unsigned i = 0; i < 10; i++)68 markSuperRegs(Reserved, CSKY::R16 + i); // R16 - R2569 }70 71 markSuperRegs(Reserved, CSKY::R26);72 markSuperRegs(Reserved, CSKY::R27);73 markSuperRegs(Reserved, CSKY::R28); // gp74 markSuperRegs(Reserved, CSKY::R29);75 markSuperRegs(Reserved, CSKY::R30);76 markSuperRegs(Reserved, CSKY::R31); // tp77 78 assert(checkAllSuperRegsMarked(Reserved));79 return Reserved;80}81 82const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const {83 return CSR_NoRegs_RegMask;84}85 86const MCPhysReg *87CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {88 const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>();89 if (MF->getFunction().hasFnAttribute("interrupt")) {90 if (STI.hasFPUv3DoubleFloat())91 return CSR_GPR_FPR64v3_ISR_SaveList;92 if (STI.hasFPUv3SingleFloat())93 return CSR_GPR_FPR32v3_ISR_SaveList;94 if (STI.hasFPUv2DoubleFloat())95 return CSR_GPR_FPR64_ISR_SaveList;96 if (STI.hasFPUv2SingleFloat())97 return CSR_GPR_FPR32_ISR_SaveList;98 return CSR_GPR_ISR_SaveList;99 }100 101 if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())102 return CSR_GPR_FPR64_SaveList;103 if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())104 return CSR_GPR_FPR32_SaveList;105 return CSR_I32_SaveList;106}107 108static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI,109 int &Offset) {110 const MCInstrDesc &Desc = MI->getDesc();111 unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask);112 unsigned i = 0;113 for (; !MI->getOperand(i).isFI(); ++i) {114 assert(i + 1 < MI->getNumOperands() &&115 "Instr doesn't have FrameIndex operand!");116 }117 118 if (MI->getOpcode() == CSKY::ADDI32) {119 if (!isUInt<12>(std::abs(Offset) - 1))120 return false;121 if (Offset < 0) {122 MI->setDesc(TII->get(CSKY::SUBI32));123 Offset = -Offset;124 }125 126 return true;127 }128 129 if (MI->getOpcode() == CSKY::ADDI16XZ)130 return false;131 132 if (Offset < 0)133 return false;134 135 unsigned NumBits = 0;136 unsigned Scale = 1;137 switch (AddrMode) {138 case CSKYII::AddrMode32B:139 Scale = 1;140 NumBits = 12;141 break;142 case CSKYII::AddrMode32H:143 Scale = 2;144 NumBits = 12;145 break;146 case CSKYII::AddrMode32WD:147 Scale = 4;148 NumBits = 12;149 break;150 case CSKYII::AddrMode16B:151 Scale = 1;152 NumBits = 5;153 break;154 case CSKYII::AddrMode16H:155 Scale = 2;156 NumBits = 5;157 break;158 case CSKYII::AddrMode16W:159 Scale = 4;160 NumBits = 5;161 break;162 case CSKYII::AddrMode32SDF:163 Scale = 4;164 NumBits = 8;165 break;166 default:167 llvm_unreachable("Unsupported addressing mode!");168 }169 170 // Cannot encode offset.171 if ((Offset & (Scale - 1)) != 0)172 return false;173 174 unsigned Mask = (1 << NumBits) - 1;175 if ((unsigned)Offset <= Mask * Scale)176 return true;177 178 // Offset out of range.179 return false;180}181 182bool CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,183 int SPAdj, unsigned FIOperandNum,184 RegScavenger *RS) const {185 assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");186 187 MachineInstr *MI = &*II;188 MachineBasicBlock &MBB = *MI->getParent();189 MachineFunction &MF = *MI->getParent()->getParent();190 MachineRegisterInfo &MRI = MF.getRegInfo();191 const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo();192 DebugLoc DL = MI->getDebugLoc();193 const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();194 195 switch (MI->getOpcode()) {196 default:197 break;198 case CSKY::RESTORE_CARRY: {199 Register NewReg = STI.hasE2()200 ? MRI.createVirtualRegister(&CSKY::GPRRegClass)201 : MRI.createVirtualRegister(&CSKY::mGPRRegClass);202 203 auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg)204 .add(MI->getOperand(1))205 .add(MI->getOperand(2))206 .getInstr();207 208 BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16),209 MI->getOperand(0).getReg())210 .addReg(NewReg, getKillRegState(true))211 .addImm(0);212 213 MI = Temp;214 215 MBB.erase(II);216 break;217 }218 case CSKY::SPILL_CARRY: {219 Register NewReg;220 if (STI.hasE2()) {221 NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);222 BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg)223 .add(MI->getOperand(0));224 } else {225 NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);226 BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0);227 BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16))228 .addReg(NewReg, RegState::Define)229 .addReg(MI->getOperand(0).getReg(), RegState::Define)230 .addReg(NewReg, getKillRegState(true))231 .addReg(NewReg, getKillRegState(true))232 .addReg(MI->getOperand(0).getReg());233 234 BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg())235 .addReg(NewReg)236 .addImm(0);237 }238 239 MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W))240 .addReg(NewReg, getKillRegState(true))241 .add(MI->getOperand(1))242 .add(MI->getOperand(2))243 .getInstr();244 245 MBB.erase(II);246 247 break;248 }249 }250 251 int FrameIndex = MI->getOperand(FIOperandNum).getIndex();252 Register FrameReg;253 int Offset = getFrameLowering(MF)254 ->getFrameIndexReference(MF, FrameIndex, FrameReg)255 .getFixed() +256 MI->getOperand(FIOperandNum + 1).getImm();257 258 if (!isInt<32>(Offset))259 report_fatal_error(260 "Frame offsets outside of the signed 32-bit range not supported");261 262 bool FrameRegIsKill = false;263 MachineBasicBlock::iterator NewII(MI);264 if (!IsLegalOffset(TII, MI, Offset)) {265 assert(isInt<32>(Offset) && "Int32 expected");266 // The offset won't fit in an immediate, so use a scratch register instead267 // Modify Offset and FrameReg appropriately268 Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset);269 BuildMI(MBB, NewII, DL,270 TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg)271 .addReg(ScratchReg, RegState::Kill)272 .addReg(FrameReg);273 274 Offset = 0;275 FrameReg = ScratchReg;276 FrameRegIsKill = true;277 }278 279 if (Offset == 0 &&280 (MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) {281 MI->setDesc(TII->get(TargetOpcode::COPY));282 MI->getOperand(FIOperandNum)283 .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);284 MI->removeOperand(FIOperandNum + 1);285 } else {286 MI->getOperand(FIOperandNum)287 .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);288 MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);289 }290 return false;291}292