267 lines · cpp
1//===-- LanaiRegisterInfo.cpp - Lanai 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 Lanai implementation of the TargetRegisterInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "LanaiRegisterInfo.h"14#include "LanaiAluCode.h"15#include "LanaiCondCode.h"16#include "LanaiFrameLowering.h"17#include "LanaiInstrInfo.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/RegisterScavenging.h"23#include "llvm/CodeGen/TargetFrameLowering.h"24#include "llvm/CodeGen/TargetInstrInfo.h"25#include "llvm/Support/ErrorHandling.h"26 27#define GET_REGINFO_TARGET_DESC28#include "LanaiGenRegisterInfo.inc"29 30using namespace llvm;31 32LanaiRegisterInfo::LanaiRegisterInfo() : LanaiGenRegisterInfo(Lanai::RCA) {}33 34const uint16_t *35LanaiRegisterInfo::getCalleeSavedRegs(const MachineFunction * /*MF*/) const {36 return CSR_SaveList;37}38 39BitVector LanaiRegisterInfo::getReservedRegs(const MachineFunction &MF) const {40 BitVector Reserved(getNumRegs());41 42 Reserved.set(Lanai::R0);43 Reserved.set(Lanai::R1);44 Reserved.set(Lanai::PC);45 Reserved.set(Lanai::R2);46 Reserved.set(Lanai::SP);47 Reserved.set(Lanai::R4);48 Reserved.set(Lanai::FP);49 Reserved.set(Lanai::R5);50 Reserved.set(Lanai::RR1);51 Reserved.set(Lanai::R10);52 Reserved.set(Lanai::RR2);53 Reserved.set(Lanai::R11);54 Reserved.set(Lanai::RCA);55 Reserved.set(Lanai::R15);56 if (hasBasePointer(MF))57 Reserved.set(getBaseRegister());58 return Reserved;59}60 61bool LanaiRegisterInfo::requiresRegisterScavenging(62 const MachineFunction & /*MF*/) const {63 return true;64}65 66static bool isALUArithLoOpcode(unsigned Opcode) {67 switch (Opcode) {68 case Lanai::ADD_I_LO:69 case Lanai::SUB_I_LO:70 case Lanai::ADD_F_I_LO:71 case Lanai::SUB_F_I_LO:72 case Lanai::ADDC_I_LO:73 case Lanai::SUBB_I_LO:74 case Lanai::ADDC_F_I_LO:75 case Lanai::SUBB_F_I_LO:76 return true;77 default:78 return false;79 }80}81 82static unsigned getOppositeALULoOpcode(unsigned Opcode) {83 switch (Opcode) {84 case Lanai::ADD_I_LO:85 return Lanai::SUB_I_LO;86 case Lanai::SUB_I_LO:87 return Lanai::ADD_I_LO;88 case Lanai::ADD_F_I_LO:89 return Lanai::SUB_F_I_LO;90 case Lanai::SUB_F_I_LO:91 return Lanai::ADD_F_I_LO;92 case Lanai::ADDC_I_LO:93 return Lanai::SUBB_I_LO;94 case Lanai::SUBB_I_LO:95 return Lanai::ADDC_I_LO;96 case Lanai::ADDC_F_I_LO:97 return Lanai::SUBB_F_I_LO;98 case Lanai::SUBB_F_I_LO:99 return Lanai::ADDC_F_I_LO;100 default:101 llvm_unreachable("Invalid ALU lo opcode");102 }103}104 105static unsigned getRRMOpcodeVariant(unsigned Opcode) {106 switch (Opcode) {107 case Lanai::LDBs_RI:108 return Lanai::LDBs_RR;109 case Lanai::LDBz_RI:110 return Lanai::LDBz_RR;111 case Lanai::LDHs_RI:112 return Lanai::LDHs_RR;113 case Lanai::LDHz_RI:114 return Lanai::LDHz_RR;115 case Lanai::LDW_RI:116 return Lanai::LDW_RR;117 case Lanai::STB_RI:118 return Lanai::STB_RR;119 case Lanai::STH_RI:120 return Lanai::STH_RR;121 case Lanai::SW_RI:122 return Lanai::SW_RR;123 default:124 llvm_unreachable("Opcode has no RRM variant");125 }126}127 128bool LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,129 int SPAdj, unsigned FIOperandNum,130 RegScavenger *RS) const {131 assert(SPAdj == 0 && "Unexpected");132 133 MachineInstr &MI = *II;134 MachineFunction &MF = *MI.getParent()->getParent();135 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();136 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();137 bool HasFP = TFI->hasFP(MF);138 DebugLoc DL = MI.getDebugLoc();139 140 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();141 142 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +143 MI.getOperand(FIOperandNum + 1).getImm();144 145 // Addressable stack objects are addressed using neg. offsets from fp146 // or pos. offsets from sp/basepointer147 if (!HasFP || (hasStackRealignment(MF) && FrameIndex >= 0))148 Offset += MF.getFrameInfo().getStackSize();149 150 Register FrameReg = getFrameRegister(MF);151 if (FrameIndex >= 0) {152 if (hasBasePointer(MF))153 FrameReg = getBaseRegister();154 else if (hasStackRealignment(MF))155 FrameReg = Lanai::SP;156 }157 158 // Replace frame index with a frame pointer reference.159 // If the offset is small enough to fit in the immediate field, directly160 // encode it.161 // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence.162 if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) ||163 !isInt<16>(Offset)) {164 assert(RS && "Register scavenging must be on");165 Register Reg = RS->FindUnusedReg(&Lanai::GPRRegClass);166 if (!Reg)167 Reg = RS->scavengeRegisterBackwards(Lanai::GPRRegClass, II, false, SPAdj);168 assert(Reg && "Register scavenger failed");169 170 bool HasNegOffset = false;171 // ALU ops have unsigned immediate values. If the Offset is negative, we172 // negate it here and reverse the opcode later.173 if (Offset < 0) {174 HasNegOffset = true;175 Offset = -Offset;176 }177 178 if (!isInt<16>(Offset)) {179 // Reg = hi(offset) | lo(offset)180 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg)181 .addImm(static_cast<uint32_t>(Offset) >> 16);182 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg)183 .addReg(Reg)184 .addImm(Offset & 0xffffU);185 } else {186 // Reg = mov(offset)187 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg)188 .addImm(0)189 .addImm(Offset);190 }191 // Reg = FrameReg OP Reg192 if (MI.getOpcode() == Lanai::ADD_I_LO) {193 BuildMI(*MI.getParent(), II, DL,194 HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R),195 MI.getOperand(0).getReg())196 .addReg(FrameReg)197 .addReg(Reg)198 .addImm(LPCC::ICC_T);199 MI.eraseFromParent();200 return true;201 }202 if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {203 MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode())));204 if (HasNegOffset) {205 // Change the ALU op (operand 3) from LPAC::ADD (the default) to206 // LPAC::SUB with the already negated offset.207 assert((MI.getOperand(3).getImm() == LPAC::ADD) &&208 "Unexpected ALU op in RRM instruction");209 MI.getOperand(3).setImm(LPAC::SUB);210 }211 } else212 llvm_unreachable("Unexpected opcode in frame index operation");213 214 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);215 MI.getOperand(FIOperandNum + 1)216 .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false,217 /*isKill=*/true);218 return false;219 }220 221 // ALU arithmetic ops take unsigned immediates. If the offset is negative,222 // we replace the instruction with one that inverts the opcode and negates223 // the immediate.224 if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) {225 unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode());226 // We know this is an ALU op, so we know the operands are as follows:227 // 0: destination register228 // 1: source register (frame register)229 // 2: immediate230 BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode),231 MI.getOperand(0).getReg())232 .addReg(FrameReg)233 .addImm(-Offset);234 MI.eraseFromParent();235 return true;236 }237 238 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);239 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);240 return false;241}242 243bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const {244 const MachineFrameInfo &MFI = MF.getFrameInfo();245 // When we need stack realignment and there are dynamic allocas, we can't246 // reference off of the stack pointer, so we reserve a base pointer.247 if (hasStackRealignment(MF) && MFI.hasVarSizedObjects())248 return true;249 250 return false;251}252 253unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; }254 255Register256LanaiRegisterInfo::getFrameRegister(const MachineFunction & /*MF*/) const {257 return Lanai::FP;258}259 260Register LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; }261 262const uint32_t *263LanaiRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/,264 CallingConv::ID /*CC*/) const {265 return CSR_RegMask;266}267