brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.8 KiB · acddb7a Raw
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