323 lines · cpp
1//===-- XCoreRegisterInfo.cpp - XCore Register Information ----------------===//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 XCore implementation of the MRegisterInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "XCoreRegisterInfo.h"14#include "XCoreInstrInfo.h"15#include "XCoreSubtarget.h"16#include "llvm/ADT/BitVector.h"17#include "llvm/CodeGen/MachineFrameInfo.h"18#include "llvm/CodeGen/MachineFunction.h"19#include "llvm/CodeGen/MachineInstrBuilder.h"20#include "llvm/CodeGen/MachineModuleInfo.h"21#include "llvm/CodeGen/RegisterScavenging.h"22#include "llvm/CodeGen/TargetFrameLowering.h"23#include "llvm/IR/Function.h"24#include "llvm/IR/Type.h"25#include "llvm/Support/Debug.h"26#include "llvm/Support/ErrorHandling.h"27#include "llvm/Support/raw_ostream.h"28#include "llvm/Target/TargetMachine.h"29#include "llvm/Target/TargetOptions.h"30 31using namespace llvm;32 33#define DEBUG_TYPE "xcore-reg-info"34 35#define GET_REGINFO_TARGET_DESC36#include "XCoreGenRegisterInfo.inc"37 38XCoreRegisterInfo::XCoreRegisterInfo()39 : XCoreGenRegisterInfo(XCore::LR) {40}41 42// helper functions43static inline bool isImmUs(unsigned val) {44 return val <= 11;45}46 47static inline bool isImmU6(unsigned val) {48 return val < (1 << 6);49}50 51static inline bool isImmU16(unsigned val) {52 return val < (1 << 16);53}54 55 56static void InsertFPImmInst(MachineBasicBlock::iterator II,57 const XCoreInstrInfo &TII,58 unsigned Reg, unsigned FrameReg, int Offset ) {59 MachineInstr &MI = *II;60 MachineBasicBlock &MBB = *MI.getParent();61 DebugLoc dl = MI.getDebugLoc();62 63 switch (MI.getOpcode()) {64 case XCore::LDWFI:65 BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)66 .addReg(FrameReg)67 .addImm(Offset)68 .addMemOperand(*MI.memoperands_begin());69 break;70 case XCore::STWFI:71 BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))72 .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))73 .addReg(FrameReg)74 .addImm(Offset)75 .addMemOperand(*MI.memoperands_begin());76 break;77 case XCore::LDAWFI:78 BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)79 .addReg(FrameReg)80 .addImm(Offset);81 break;82 default:83 llvm_unreachable("Unexpected Opcode");84 }85}86 87static void InsertFPConstInst(MachineBasicBlock::iterator II,88 const XCoreInstrInfo &TII,89 unsigned Reg, unsigned FrameReg,90 int Offset, RegScavenger *RS ) {91 assert(RS && "requiresRegisterScavenging failed");92 MachineInstr &MI = *II;93 MachineBasicBlock &MBB = *MI.getParent();94 DebugLoc dl = MI.getDebugLoc();95 Register ScratchOffset =96 RS->scavengeRegisterBackwards(XCore::GRRegsRegClass, II, false, 0);97 RS->setRegUsed(ScratchOffset);98 TII.loadImmediate(MBB, II, ScratchOffset, Offset);99 100 switch (MI.getOpcode()) {101 case XCore::LDWFI:102 BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)103 .addReg(FrameReg)104 .addReg(ScratchOffset, RegState::Kill)105 .addMemOperand(*MI.memoperands_begin());106 break;107 case XCore::STWFI:108 BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))109 .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))110 .addReg(FrameReg)111 .addReg(ScratchOffset, RegState::Kill)112 .addMemOperand(*MI.memoperands_begin());113 break;114 case XCore::LDAWFI:115 BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)116 .addReg(FrameReg)117 .addReg(ScratchOffset, RegState::Kill);118 break;119 default:120 llvm_unreachable("Unexpected Opcode");121 }122}123 124static void InsertSPImmInst(MachineBasicBlock::iterator II,125 const XCoreInstrInfo &TII,126 unsigned Reg, int Offset) {127 MachineInstr &MI = *II;128 MachineBasicBlock &MBB = *MI.getParent();129 DebugLoc dl = MI.getDebugLoc();130 bool isU6 = isImmU6(Offset);131 132 switch (MI.getOpcode()) {133 int NewOpcode;134 case XCore::LDWFI:135 NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;136 BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)137 .addImm(Offset)138 .addMemOperand(*MI.memoperands_begin());139 break;140 case XCore::STWFI:141 NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;142 BuildMI(MBB, II, dl, TII.get(NewOpcode))143 .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))144 .addImm(Offset)145 .addMemOperand(*MI.memoperands_begin());146 break;147 case XCore::LDAWFI:148 NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;149 BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)150 .addImm(Offset);151 break;152 default:153 llvm_unreachable("Unexpected Opcode");154 }155}156 157static void InsertSPConstInst(MachineBasicBlock::iterator II,158 const XCoreInstrInfo &TII,159 unsigned Reg, int Offset, RegScavenger *RS ) {160 assert(RS && "requiresRegisterScavenging failed");161 MachineInstr &MI = *II;162 MachineBasicBlock &MBB = *MI.getParent();163 DebugLoc dl = MI.getDebugLoc();164 unsigned OpCode = MI.getOpcode();165 166 unsigned ScratchBase;167 if (OpCode==XCore::STWFI) {168 ScratchBase =169 RS->scavengeRegisterBackwards(XCore::GRRegsRegClass, II, false, 0);170 RS->setRegUsed(ScratchBase);171 } else172 ScratchBase = Reg;173 BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0);174 Register ScratchOffset =175 RS->scavengeRegisterBackwards(XCore::GRRegsRegClass, II, false, 0);176 RS->setRegUsed(ScratchOffset);177 TII.loadImmediate(MBB, II, ScratchOffset, Offset);178 179 switch (OpCode) {180 case XCore::LDWFI:181 BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)182 .addReg(ScratchBase, RegState::Kill)183 .addReg(ScratchOffset, RegState::Kill)184 .addMemOperand(*MI.memoperands_begin());185 break;186 case XCore::STWFI:187 BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))188 .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))189 .addReg(ScratchBase, RegState::Kill)190 .addReg(ScratchOffset, RegState::Kill)191 .addMemOperand(*MI.memoperands_begin());192 break;193 case XCore::LDAWFI:194 BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)195 .addReg(ScratchBase, RegState::Kill)196 .addReg(ScratchOffset, RegState::Kill);197 break;198 default:199 llvm_unreachable("Unexpected Opcode");200 }201}202 203bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {204 return MF.needsFrameMoves();205}206 207const MCPhysReg *208XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {209 // The callee saved registers LR & FP are explicitly handled during210 // emitPrologue & emitEpilogue and related functions.211 static const MCPhysReg CalleeSavedRegs[] = {212 XCore::R4, XCore::R5, XCore::R6, XCore::R7,213 XCore::R8, XCore::R9, XCore::R10,214 0215 };216 static const MCPhysReg CalleeSavedRegsFP[] = {217 XCore::R4, XCore::R5, XCore::R6, XCore::R7,218 XCore::R8, XCore::R9,219 0220 };221 const XCoreFrameLowering *TFI = getFrameLowering(*MF);222 if (TFI->hasFP(*MF))223 return CalleeSavedRegsFP;224 return CalleeSavedRegs;225}226 227BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {228 BitVector Reserved(getNumRegs());229 const XCoreFrameLowering *TFI = getFrameLowering(MF);230 231 Reserved.set(XCore::CP);232 Reserved.set(XCore::DP);233 Reserved.set(XCore::SP);234 Reserved.set(XCore::LR);235 if (TFI->hasFP(MF)) {236 Reserved.set(XCore::R10);237 }238 return Reserved;239}240 241bool242XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {243 return true;244}245 246bool247XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {248 return false;249}250 251bool252XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,253 int SPAdj, unsigned FIOperandNum,254 RegScavenger *RS) const {255 assert(SPAdj == 0 && "Unexpected");256 MachineInstr &MI = *II;257 MachineOperand &FrameOp = MI.getOperand(FIOperandNum);258 int FrameIndex = FrameOp.getIndex();259 260 MachineFunction &MF = *MI.getParent()->getParent();261 const XCoreInstrInfo &TII =262 *static_cast<const XCoreInstrInfo *>(MF.getSubtarget().getInstrInfo());263 264 const XCoreFrameLowering *TFI = getFrameLowering(MF);265 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);266 int StackSize = MF.getFrameInfo().getStackSize();267 268 #ifndef NDEBUG269 LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n");270 LLVM_DEBUG(errs() << "<--------->\n");271 LLVM_DEBUG(MI.print(errs()));272 LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n");273 LLVM_DEBUG(errs() << "FrameOffset : " << Offset << "\n");274 LLVM_DEBUG(errs() << "StackSize : " << StackSize << "\n");275#endif276 277 Offset += StackSize;278 279 Register FrameReg = getFrameRegister(MF);280 281 // Special handling of DBG_VALUE instructions.282 if (MI.isDebugValue()) {283 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);284 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);285 return false;286 }287 288 // fold constant into offset.289 Offset += MI.getOperand(FIOperandNum + 1).getImm();290 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);291 292 assert(Offset%4 == 0 && "Misaligned stack offset");293 LLVM_DEBUG(errs() << "Offset : " << Offset << "\n"294 << "<--------->\n");295 Offset/=4;296 297 Register Reg = MI.getOperand(0).getReg();298 assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");299 300 if (TFI->hasFP(MF)) {301 if (isImmUs(Offset))302 InsertFPImmInst(II, TII, Reg, FrameReg, Offset);303 else304 InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);305 } else {306 if (isImmU16(Offset))307 InsertSPImmInst(II, TII, Reg, Offset);308 else309 InsertSPConstInst(II, TII, Reg, Offset, RS);310 }311 // Erase old instruction.312 MachineBasicBlock &MBB = *MI.getParent();313 MBB.erase(II);314 return true;315}316 317 318Register XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {319 const XCoreFrameLowering *TFI = getFrameLowering(MF);320 321 return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;322}323