235 lines · cpp
1//===- ARCRegisterInfo.cpp - ARC 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 ARC implementation of the MRegisterInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "ARCRegisterInfo.h"14#include "ARC.h"15#include "ARCInstrInfo.h"16#include "ARCMachineFunctionInfo.h"17#include "ARCSubtarget.h"18#include "llvm/ADT/BitVector.h"19#include "llvm/CodeGen/MachineFrameInfo.h"20#include "llvm/CodeGen/MachineFunction.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/CodeGen/MachineModuleInfo.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/CodeGen/RegisterScavenging.h"25#include "llvm/CodeGen/TargetFrameLowering.h"26#include "llvm/IR/Function.h"27#include "llvm/Support/Debug.h"28#include "llvm/Target/TargetMachine.h"29#include "llvm/Target/TargetOptions.h"30 31using namespace llvm;32 33#define DEBUG_TYPE "arc-reg-info"34 35#define GET_REGINFO_TARGET_DESC36#include "ARCGenRegisterInfo.inc"37 38static void replaceFrameIndex(MachineBasicBlock::iterator II,39 const ARCInstrInfo &TII, unsigned Reg,40 unsigned FrameReg, int Offset, int StackSize,41 int ObjSize, RegScavenger *RS, int SPAdj) {42 assert(RS && "Need register scavenger.");43 MachineInstr &MI = *II;44 MachineBasicBlock &MBB = *MI.getParent();45 DebugLoc DL = MI.getDebugLoc();46 unsigned BaseReg = FrameReg;47 unsigned KillState = 0;48 if (MI.getOpcode() == ARC::LD_rs9 && (Offset >= 256 || Offset < -256)) {49 // Loads can always be reached with LD_rlimm.50 BuildMI(MBB, II, DL, TII.get(ARC::LD_rlimm), Reg)51 .addReg(BaseReg)52 .addImm(Offset)53 .addMemOperand(*MI.memoperands_begin());54 MBB.erase(II);55 return;56 }57 58 if (MI.getOpcode() != ARC::GETFI && (Offset >= 256 || Offset < -256)) {59 // We need to use a scratch register to reach the far-away frame indexes.60 BaseReg = RS->FindUnusedReg(&ARC::GPR32RegClass);61 if (!BaseReg) {62 // We can be sure that the scavenged-register slot is within the range63 // of the load offset.64 const TargetRegisterInfo *TRI =65 MBB.getParent()->getSubtarget().getRegisterInfo();66 BaseReg =67 RS->scavengeRegisterBackwards(ARC::GPR32RegClass, II, false, SPAdj);68 assert(BaseReg && "Register scavenging failed.");69 LLVM_DEBUG(dbgs() << "Scavenged register " << printReg(BaseReg, TRI)70 << " for FrameReg=" << printReg(FrameReg, TRI)71 << "+Offset=" << Offset << "\n");72 (void)TRI;73 RS->setRegUsed(BaseReg);74 }75 unsigned AddOpc = isUInt<6>(Offset) ? ARC::ADD_rru6 : ARC::ADD_rrlimm;76 BuildMI(MBB, II, DL, TII.get(AddOpc))77 .addReg(BaseReg, RegState::Define)78 .addReg(FrameReg)79 .addImm(Offset);80 Offset = 0;81 KillState = RegState::Kill;82 }83 switch (MI.getOpcode()) {84 case ARC::LD_rs9:85 assert((Offset % 4 == 0) && "LD needs 4 byte alignment.");86 [[fallthrough]];87 case ARC::LDH_rs9:88 case ARC::LDH_X_rs9:89 assert((Offset % 2 == 0) && "LDH needs 2 byte alignment.");90 [[fallthrough]];91 case ARC::LDB_rs9:92 case ARC::LDB_X_rs9:93 LLVM_DEBUG(dbgs() << "Building LDFI\n");94 BuildMI(MBB, II, DL, TII.get(MI.getOpcode()), Reg)95 .addReg(BaseReg, KillState)96 .addImm(Offset)97 .addMemOperand(*MI.memoperands_begin());98 break;99 case ARC::ST_rs9:100 assert((Offset % 4 == 0) && "ST needs 4 byte alignment.");101 [[fallthrough]];102 case ARC::STH_rs9:103 assert((Offset % 2 == 0) && "STH needs 2 byte alignment.");104 [[fallthrough]];105 case ARC::STB_rs9:106 LLVM_DEBUG(dbgs() << "Building STFI\n");107 BuildMI(MBB, II, DL, TII.get(MI.getOpcode()))108 .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))109 .addReg(BaseReg, KillState)110 .addImm(Offset)111 .addMemOperand(*MI.memoperands_begin());112 break;113 case ARC::GETFI:114 LLVM_DEBUG(dbgs() << "Building GETFI\n");115 BuildMI(MBB, II, DL,116 TII.get(isUInt<6>(Offset) ? ARC::ADD_rru6 : ARC::ADD_rrlimm))117 .addReg(Reg, RegState::Define)118 .addReg(FrameReg)119 .addImm(Offset);120 break;121 default:122 llvm_unreachable("Unhandled opcode.");123 }124 125 // Erase old instruction.126 MBB.erase(II);127}128 129ARCRegisterInfo::ARCRegisterInfo(const ARCSubtarget &ST)130 : ARCGenRegisterInfo(ARC::BLINK), ST(ST) {}131 132bool ARCRegisterInfo::needsFrameMoves(const MachineFunction &MF) {133 return MF.needsFrameMoves();134}135 136const MCPhysReg *137ARCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {138 return CSR_ARC_SaveList;139}140 141BitVector ARCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {142 BitVector Reserved(getNumRegs());143 144 Reserved.set(ARC::ILINK);145 Reserved.set(ARC::SP);146 Reserved.set(ARC::GP);147 Reserved.set(ARC::R25);148 Reserved.set(ARC::BLINK);149 Reserved.set(ARC::FP);150 151 return Reserved;152}153 154bool ARCRegisterInfo::requiresRegisterScavenging(155 const MachineFunction &MF) const {156 return true;157}158 159bool ARCRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {160 return true;161}162 163bool ARCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,164 int SPAdj, unsigned FIOperandNum,165 RegScavenger *RS) const {166 assert(SPAdj == 0 && "Unexpected");167 MachineInstr &MI = *II;168 MachineOperand &FrameOp = MI.getOperand(FIOperandNum);169 int FrameIndex = FrameOp.getIndex();170 171 MachineFunction &MF = *MI.getParent()->getParent();172 const ARCInstrInfo &TII = *MF.getSubtarget<ARCSubtarget>().getInstrInfo();173 const ARCFrameLowering *TFI = getFrameLowering(MF);174 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);175 int ObjSize = MF.getFrameInfo().getObjectSize(FrameIndex);176 int StackSize = MF.getFrameInfo().getStackSize();177 int LocalFrameSize = MF.getFrameInfo().getLocalFrameSize();178 179 LLVM_DEBUG(dbgs() << "\nFunction : " << MF.getName() << "\n");180 LLVM_DEBUG(dbgs() << "<--------->\n");181 LLVM_DEBUG(dbgs() << MI << "\n");182 LLVM_DEBUG(dbgs() << "FrameIndex : " << FrameIndex << "\n");183 LLVM_DEBUG(dbgs() << "ObjSize : " << ObjSize << "\n");184 LLVM_DEBUG(dbgs() << "FrameOffset : " << Offset << "\n");185 LLVM_DEBUG(dbgs() << "StackSize : " << StackSize << "\n");186 LLVM_DEBUG(dbgs() << "LocalFrameSize : " << LocalFrameSize << "\n");187 (void)LocalFrameSize;188 189 // Special handling of DBG_VALUE instructions.190 if (MI.isDebugValue()) {191 Register FrameReg = getFrameRegister(MF);192 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);193 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);194 return false;195 }196 197 // fold constant into offset.198 Offset += MI.getOperand(FIOperandNum + 1).getImm();199 200 // TODO: assert based on the load type:201 // ldb needs no alignment,202 // ldh needs 2 byte alignment203 // ld needs 4 byte alignment204 LLVM_DEBUG(dbgs() << "Offset : " << Offset << "\n"205 << "<--------->\n");206 207 Register Reg = MI.getOperand(0).getReg();208 assert(ARC::GPR32RegClass.contains(Reg) && "Unexpected register operand");209 210 if (!TFI->hasFP(MF)) {211 Offset = StackSize + Offset;212 if (FrameIndex >= 0)213 assert((Offset >= 0 && Offset < StackSize) && "SP Offset not in bounds.");214 } else {215 if (FrameIndex >= 0) {216 assert((Offset < 0 && -Offset <= StackSize) &&217 "FP Offset not in bounds.");218 }219 }220 replaceFrameIndex(II, TII, Reg, getFrameRegister(MF), Offset, StackSize,221 ObjSize, RS, SPAdj);222 return true; 223}224 225Register ARCRegisterInfo::getFrameRegister(const MachineFunction &MF) const {226 const ARCFrameLowering *TFI = getFrameLowering(MF);227 return TFI->hasFP(MF) ? ARC::FP : ARC::SP;228}229 230const uint32_t *231ARCRegisterInfo::getCallPreservedMask(const MachineFunction &MF,232 CallingConv::ID CC) const {233 return CSR_ARC_RegMask;234}235