brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.1 KiB · 9c5f8ed Raw
261 lines · cpp
1//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- 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 LoongArch implementation of the TargetRegisterInfo10// class.11//12//===----------------------------------------------------------------------===//13 14#include "LoongArchRegisterInfo.h"15#include "LoongArch.h"16#include "LoongArchInstrInfo.h"17#include "LoongArchSubtarget.h"18#include "MCTargetDesc/LoongArchBaseInfo.h"19#include "MCTargetDesc/LoongArchMCTargetDesc.h"20#include "llvm/CodeGen/MachineFrameInfo.h"21#include "llvm/CodeGen/MachineFunction.h"22#include "llvm/CodeGen/MachineInstrBuilder.h"23#include "llvm/CodeGen/RegisterScavenging.h"24#include "llvm/CodeGen/TargetFrameLowering.h"25#include "llvm/CodeGen/TargetInstrInfo.h"26#include "llvm/Support/ErrorHandling.h"27 28using namespace llvm;29 30#define GET_REGINFO_TARGET_DESC31#include "LoongArchGenRegisterInfo.inc"32 33LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)34    : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,35                               /*EHFlavor*/ 0,36                               /*PC*/ 0, HwMode) {}37 38const MCPhysReg *39LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {40  auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>();41 42  if (MF->getFunction().getCallingConv() == CallingConv::GHC)43    return CSR_NoRegs_SaveList;44  if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)45    return CSR_MostRegs_SaveList;46  switch (Subtarget.getTargetABI()) {47  default:48    llvm_unreachable("Unrecognized ABI");49  case LoongArchABI::ABI_ILP32S:50  case LoongArchABI::ABI_LP64S:51    return CSR_ILP32S_LP64S_SaveList;52  case LoongArchABI::ABI_ILP32F:53  case LoongArchABI::ABI_LP64F:54    return CSR_ILP32F_LP64F_SaveList;55  case LoongArchABI::ABI_ILP32D:56  case LoongArchABI::ABI_LP64D:57    return CSR_ILP32D_LP64D_SaveList;58  }59}60 61const uint32_t *62LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,63                                            CallingConv::ID CC) const {64  auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();65 66  if (CC == CallingConv::GHC)67    return CSR_NoRegs_RegMask;68  if (CC == CallingConv::PreserveMost)69    return CSR_MostRegs_RegMask;70  switch (Subtarget.getTargetABI()) {71  default:72    llvm_unreachable("Unrecognized ABI");73  case LoongArchABI::ABI_ILP32S:74  case LoongArchABI::ABI_LP64S:75    return CSR_ILP32S_LP64S_RegMask;76  case LoongArchABI::ABI_ILP32F:77  case LoongArchABI::ABI_LP64F:78    return CSR_ILP32F_LP64F_RegMask;79  case LoongArchABI::ABI_ILP32D:80  case LoongArchABI::ABI_LP64D:81    return CSR_ILP32D_LP64D_RegMask;82  }83}84 85const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {86  return CSR_NoRegs_RegMask;87}88 89BitVector90LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {91  const LoongArchFrameLowering *TFI = getFrameLowering(MF);92  BitVector Reserved(getNumRegs());93 94  // Use markSuperRegs to ensure any register aliases are also reserved95  markSuperRegs(Reserved, LoongArch::R0);  // zero96  markSuperRegs(Reserved, LoongArch::R2);  // tp97  markSuperRegs(Reserved, LoongArch::R3);  // sp98  markSuperRegs(Reserved, LoongArch::R21); // non-allocatable99  if (TFI->hasFP(MF))100    markSuperRegs(Reserved, LoongArch::R22); // fp101  // Reserve the base register if we need to realign the stack and allocate102  // variable-sized objects at runtime.103  if (TFI->hasBP(MF))104    markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp105 106  assert(checkAllSuperRegsMarked(Reserved));107  return Reserved;108}109 110Register111LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {112  const TargetFrameLowering *TFI = getFrameLowering(MF);113  return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;114}115 116bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,117                                                int SPAdj,118                                                unsigned FIOperandNum,119                                                RegScavenger *RS) const {120  // TODO: this implementation is a temporary placeholder which does just121  // enough to allow other aspects of code generation to be tested.122 123  assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");124 125  MachineInstr &MI = *II;126  assert(MI.getOperand(FIOperandNum + 1).isImm() &&127         "Unexpected FI-consuming insn");128 129  MachineBasicBlock &MBB = *MI.getParent();130  MachineFunction &MF = *MI.getParent()->getParent();131  MachineRegisterInfo &MRI = MF.getRegInfo();132  const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();133  const LoongArchInstrInfo *TII = STI.getInstrInfo();134  const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();135  DebugLoc DL = MI.getDebugLoc();136  bool IsLA64 = STI.is64Bit();137  unsigned MIOpc = MI.getOpcode();138 139  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();140  Register FrameReg;141  StackOffset Offset =142      TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) +143      StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());144 145  bool FrameRegIsKill = false;146 147  int FixedOffset = Offset.getFixed();148  bool OffsetLegal = true;149 150  // Handle offsets that exceed the immediate range of the instruction.151  switch (MIOpc) {152  case LoongArch::VSTELM_B:153  case LoongArch::XVSTELM_B:154    OffsetLegal = isInt<8>(FixedOffset);155    break;156  case LoongArch::VSTELM_H:157  case LoongArch::XVSTELM_H:158    OffsetLegal = isShiftedInt<8, 1>(FixedOffset);159    break;160  case LoongArch::VSTELM_W:161  case LoongArch::XVSTELM_W:162    OffsetLegal = isShiftedInt<8, 2>(FixedOffset);163    break;164  case LoongArch::VSTELM_D:165  case LoongArch::XVSTELM_D:166    OffsetLegal = isShiftedInt<8, 3>(FixedOffset);167    break;168  }169 170  if (!OffsetLegal && isInt<12>(FixedOffset)) {171    unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;172 173    // The offset fits in si12 but is not legal for the instruction,174    // so use only one scratch register instead.175    Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);176    BuildMI(MBB, II, DL, TII->get(Addi), ScratchReg)177        .addReg(FrameReg)178        .addImm(FixedOffset);179    Offset = StackOffset::getFixed(0);180    FrameReg = ScratchReg;181    FrameRegIsKill = true;182  }183 184  if (!isInt<12>(FixedOffset)) {185    unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;186    unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;187 188    // The offset won't fit in an immediate, so use a scratch register instead.189    // Modify Offset and FrameReg appropriately.190    Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);191    TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());192    if (MIOpc == Addi) {193      BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())194          .addReg(FrameReg)195          .addReg(ScratchReg, RegState::Kill);196      MI.eraseFromParent();197      return true;198    }199    BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)200        .addReg(FrameReg)201        .addReg(ScratchReg, RegState::Kill);202    Offset = StackOffset::getFixed(0);203    FrameReg = ScratchReg;204    FrameRegIsKill = true;205  }206 207  // Spill CFRs.208  if (MIOpc == LoongArch::PseudoST_CFR) {209    Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);210    BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg)211        .add(MI.getOperand(0));212    BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))213        .addReg(ScratchReg, RegState::Kill)214        .addReg(FrameReg)215        .addImm(Offset.getFixed());216    MI.eraseFromParent();217    return true;218  }219 220  // Reload CFRs.221  if (MIOpc == LoongArch::PseudoLD_CFR) {222    Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);223    BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W),224            ScratchReg)225        .addReg(FrameReg)226        .addImm(Offset.getFixed());227    BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF))228        .add(MI.getOperand(0))229        .addReg(ScratchReg, RegState::Kill);230    MI.eraseFromParent();231    return true;232  }233 234  MI.getOperand(FIOperandNum)235      .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);236  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());237  return false;238}239 240bool LoongArchRegisterInfo::canRealignStack(const MachineFunction &MF) const {241  if (!TargetRegisterInfo::canRealignStack(MF))242    return false;243 244  const MachineRegisterInfo *MRI = &MF.getRegInfo();245  const LoongArchFrameLowering *TFI = getFrameLowering(MF);246 247  // Stack realignment requires a frame pointer.  If we already started248  // register allocation with frame pointer elimination, it is too late now.249  if (!MRI->canReserveReg(LoongArch::R22))250    return false;251 252  // We may also need a base pointer if there are dynamic allocas or stack253  // pointer adjustments around calls.254  if (TFI->hasReservedCallFrame(MF))255    return true;256 257  // A base pointer is required and allowed.  Check that it isn't too late to258  // reserve it.259  return MRI->canReserveReg(LoongArchABI::getBPReg());260}261