Path: blob/main/contrib/llvm-project/llvm/lib/Target/Mips/Mips16InstrInfo.cpp
35266 views
//===- Mips16InstrInfo.cpp - Mips16 Instruction Information ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the Mips16 implementation of the TargetInstrInfo class.9//10//===----------------------------------------------------------------------===//1112#include "Mips16InstrInfo.h"13#include "llvm/ADT/BitVector.h"14#include "llvm/CodeGen/MachineBasicBlock.h"15#include "llvm/CodeGen/MachineFrameInfo.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/MachineInstr.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/MachineMemOperand.h"20#include "llvm/CodeGen/MachineOperand.h"21#include "llvm/CodeGen/RegisterScavenging.h"22#include "llvm/CodeGen/TargetRegisterInfo.h"23#include "llvm/IR/DebugLoc.h"24#include "llvm/MC/MCAsmInfo.h"25#include "llvm/Support/Debug.h"26#include "llvm/Support/ErrorHandling.h"27#include "llvm/Support/MathExtras.h"28#include "llvm/Support/raw_ostream.h"29#include <cassert>30#include <cctype>31#include <cstdint>32#include <cstdlib>33#include <cstring>34#include <iterator>35#include <vector>3637using namespace llvm;3839#define DEBUG_TYPE "mips16-instrinfo"4041Mips16InstrInfo::Mips16InstrInfo(const MipsSubtarget &STI)42: MipsInstrInfo(STI, Mips::Bimm16) {}4344const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const {45return RI;46}4748/// isLoadFromStackSlot - If the specified machine instruction is a direct49/// load from a stack slot, return the virtual or physical register number of50/// the destination along with the FrameIndex of the loaded stack slot. If51/// not, return 0. This predicate must return 0 if the instruction has52/// any side effects other than loading from the stack slot.53Register Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr &MI,54int &FrameIndex) const {55return 0;56}5758/// isStoreToStackSlot - If the specified machine instruction is a direct59/// store to a stack slot, return the virtual or physical register number of60/// the source reg along with the FrameIndex of the loaded stack slot. If61/// not, return 0. This predicate must return 0 if the instruction has62/// any side effects other than storing to the stack slot.63Register Mips16InstrInfo::isStoreToStackSlot(const MachineInstr &MI,64int &FrameIndex) const {65return 0;66}6768void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB,69MachineBasicBlock::iterator I,70const DebugLoc &DL, MCRegister DestReg,71MCRegister SrcReg, bool KillSrc) const {72unsigned Opc = 0;7374if (Mips::CPU16RegsRegClass.contains(DestReg) &&75Mips::GPR32RegClass.contains(SrcReg))76Opc = Mips::MoveR3216;77else if (Mips::GPR32RegClass.contains(DestReg) &&78Mips::CPU16RegsRegClass.contains(SrcReg))79Opc = Mips::Move32R16;80else if ((SrcReg == Mips::HI0) &&81(Mips::CPU16RegsRegClass.contains(DestReg)))82Opc = Mips::Mfhi16, SrcReg = 0;83else if ((SrcReg == Mips::LO0) &&84(Mips::CPU16RegsRegClass.contains(DestReg)))85Opc = Mips::Mflo16, SrcReg = 0;8687assert(Opc && "Cannot copy registers");8889MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc));9091if (DestReg)92MIB.addReg(DestReg, RegState::Define);9394if (SrcReg)95MIB.addReg(SrcReg, getKillRegState(KillSrc));96}9798std::optional<DestSourcePair>99Mips16InstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {100if (MI.isMoveReg())101return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};102return std::nullopt;103}104105void Mips16InstrInfo::storeRegToStack(MachineBasicBlock &MBB,106MachineBasicBlock::iterator I,107Register SrcReg, bool isKill, int FI,108const TargetRegisterClass *RC,109const TargetRegisterInfo *TRI,110int64_t Offset) const {111DebugLoc DL;112if (I != MBB.end()) DL = I->getDebugLoc();113MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);114unsigned Opc = 0;115if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))116Opc = Mips::SwRxSpImmX16;117assert(Opc && "Register class not handled!");118BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)).119addFrameIndex(FI).addImm(Offset)120.addMemOperand(MMO);121}122123void Mips16InstrInfo::loadRegFromStack(MachineBasicBlock &MBB,124MachineBasicBlock::iterator I,125Register DestReg, int FI,126const TargetRegisterClass *RC,127const TargetRegisterInfo *TRI,128int64_t Offset) const {129DebugLoc DL;130if (I != MBB.end()) DL = I->getDebugLoc();131MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);132unsigned Opc = 0;133134if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))135Opc = Mips::LwRxSpImmX16;136assert(Opc && "Register class not handled!");137BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset)138.addMemOperand(MMO);139}140141bool Mips16InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {142MachineBasicBlock &MBB = *MI.getParent();143switch (MI.getDesc().getOpcode()) {144default:145return false;146case Mips::RetRA16:147ExpandRetRA16(MBB, MI, Mips::JrcRa16);148break;149}150151MBB.erase(MI.getIterator());152return true;153}154155/// GetOppositeBranchOpc - Return the inverse of the specified156/// opcode, e.g. turning BEQ to BNE.157unsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const {158switch (Opc) {159case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16;160case Mips::BnezRxImmX16: return Mips::BeqzRxImmX16;161case Mips::BeqzRxImm16: return Mips::BnezRxImm16;162case Mips::BnezRxImm16: return Mips::BeqzRxImm16;163case Mips::BteqzT8CmpX16: return Mips::BtnezT8CmpX16;164case Mips::BteqzT8SltX16: return Mips::BtnezT8SltX16;165case Mips::BteqzT8SltiX16: return Mips::BtnezT8SltiX16;166case Mips::Btnez16: return Mips::Bteqz16;167case Mips::BtnezX16: return Mips::BteqzX16;168case Mips::BtnezT8CmpiX16: return Mips::BteqzT8CmpiX16;169case Mips::BtnezT8SltuX16: return Mips::BteqzT8SltuX16;170case Mips::BtnezT8SltiuX16: return Mips::BteqzT8SltiuX16;171case Mips::Bteqz16: return Mips::Btnez16;172case Mips::BteqzX16: return Mips::BtnezX16;173case Mips::BteqzT8CmpiX16: return Mips::BtnezT8CmpiX16;174case Mips::BteqzT8SltuX16: return Mips::BtnezT8SltuX16;175case Mips::BteqzT8SltiuX16: return Mips::BtnezT8SltiuX16;176case Mips::BtnezT8CmpX16: return Mips::BteqzT8CmpX16;177case Mips::BtnezT8SltX16: return Mips::BteqzT8SltX16;178case Mips::BtnezT8SltiX16: return Mips::BteqzT8SltiX16;179}180llvm_unreachable("Illegal opcode!");181}182183static void addSaveRestoreRegs(MachineInstrBuilder &MIB,184ArrayRef<CalleeSavedInfo> CSI,185unsigned Flags = 0) {186for (unsigned i = 0, e = CSI.size(); i != e; ++i) {187// Add the callee-saved register as live-in. Do not add if the register is188// RA and return address is taken, because it has already been added in189// method MipsTargetLowering::lowerRETURNADDR.190// It's killed at the spill, unless the register is RA and return address191// is taken.192Register Reg = CSI[e-i-1].getReg();193switch (Reg) {194case Mips::RA:195case Mips::S0:196case Mips::S1:197MIB.addReg(Reg, Flags);198break;199case Mips::S2:200break;201default:202llvm_unreachable("unexpected mips16 callee saved register");203204}205}206}207208// Adjust SP by FrameSize bytes. Save RA, S0, S1209void Mips16InstrInfo::makeFrame(unsigned SP, int64_t FrameSize,210MachineBasicBlock &MBB,211MachineBasicBlock::iterator I) const {212DebugLoc DL;213MachineFunction &MF = *MBB.getParent();214MachineFrameInfo &MFI = MF.getFrameInfo();215const BitVector Reserved = RI.getReservedRegs(MF);216bool SaveS2 = Reserved[Mips::S2];217MachineInstrBuilder MIB;218unsigned Opc = ((FrameSize <= 128) && !SaveS2)? Mips::Save16:Mips::SaveX16;219MIB = BuildMI(MBB, I, DL, get(Opc));220const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();221addSaveRestoreRegs(MIB, CSI);222if (SaveS2)223MIB.addReg(Mips::S2);224if (isUInt<11>(FrameSize))225MIB.addImm(FrameSize);226else {227int Base = 2040; // should create template function like isUInt that228// returns largest possible n bit unsigned integer229int64_t Remainder = FrameSize - Base;230MIB.addImm(Base);231if (isInt<16>(-Remainder))232BuildAddiuSpImm(MBB, I, -Remainder);233else234adjustStackPtrBig(SP, -Remainder, MBB, I, Mips::V0, Mips::V1);235}236}237238// Adjust SP by FrameSize bytes. Restore RA, S0, S1239void Mips16InstrInfo::restoreFrame(unsigned SP, int64_t FrameSize,240MachineBasicBlock &MBB,241MachineBasicBlock::iterator I) const {242DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();243MachineFunction *MF = MBB.getParent();244MachineFrameInfo &MFI = MF->getFrameInfo();245const BitVector Reserved = RI.getReservedRegs(*MF);246bool SaveS2 = Reserved[Mips::S2];247MachineInstrBuilder MIB;248unsigned Opc = ((FrameSize <= 128) && !SaveS2)?249Mips::Restore16:Mips::RestoreX16;250251if (!isUInt<11>(FrameSize)) {252unsigned Base = 2040;253int64_t Remainder = FrameSize - Base;254FrameSize = Base; // should create template function like isUInt that255// returns largest possible n bit unsigned integer256257if (isInt<16>(Remainder))258BuildAddiuSpImm(MBB, I, Remainder);259else260adjustStackPtrBig(SP, Remainder, MBB, I, Mips::A0, Mips::A1);261}262MIB = BuildMI(MBB, I, DL, get(Opc));263const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();264addSaveRestoreRegs(MIB, CSI, RegState::Define);265if (SaveS2)266MIB.addReg(Mips::S2, RegState::Define);267MIB.addImm(FrameSize);268}269270// Adjust SP by Amount bytes where bytes can be up to 32bit number.271// This can only be called at times that we know that there is at least one free272// register.273// This is clearly safe at prologue and epilogue.274void Mips16InstrInfo::adjustStackPtrBig(unsigned SP, int64_t Amount,275MachineBasicBlock &MBB,276MachineBasicBlock::iterator I,277unsigned Reg1, unsigned Reg2) const {278DebugLoc DL;279//280// li reg1, constant281// move reg2, sp282// add reg1, reg1, reg2283// move sp, reg1284//285//286MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwConstant32), Reg1);287MIB1.addImm(Amount).addImm(-1);288MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::MoveR3216), Reg2);289MIB2.addReg(Mips::SP, RegState::Kill);290MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::AdduRxRyRz16), Reg1);291MIB3.addReg(Reg1);292MIB3.addReg(Reg2, RegState::Kill);293MachineInstrBuilder MIB4 = BuildMI(MBB, I, DL, get(Mips::Move32R16),294Mips::SP);295MIB4.addReg(Reg1, RegState::Kill);296}297298void Mips16InstrInfo::adjustStackPtrBigUnrestricted(299unsigned SP, int64_t Amount, MachineBasicBlock &MBB,300MachineBasicBlock::iterator I) const {301llvm_unreachable("adjust stack pointer amount exceeded");302}303304/// Adjust SP by Amount bytes.305void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,306MachineBasicBlock &MBB,307MachineBasicBlock::iterator I) const {308if (Amount == 0)309return;310311if (isInt<16>(Amount)) // need to change to addiu sp, ....and isInt<16>312BuildAddiuSpImm(MBB, I, Amount);313else314adjustStackPtrBigUnrestricted(SP, Amount, MBB, I);315}316317/// This function generates the sequence of instructions needed to get the318/// result of adding register REG and immediate IMM.319unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm,320MachineBasicBlock &MBB,321MachineBasicBlock::iterator II,322const DebugLoc &DL,323unsigned &NewImm) const {324//325// given original instruction is:326// Instr rx, T[offset] where offset is too big.327//328// lo = offset & 0xFFFF329// hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF;330//331// let T = temporary register332// li T, hi333// shl T, 16334// add T, Rx, T335//336RegScavenger rs;337int32_t lo = Imm & 0xFFFF;338NewImm = lo;339int Reg =0;340int SpReg = 0;341342rs.enterBasicBlockEnd(MBB);343rs.backward(std::next(II));344//345// We need to know which registers can be used, in the case where there346// are not enough free registers. We exclude all registers that347// are used in the instruction that we are helping.348// // Consider all allocatable registers in the register class initially349BitVector Candidates =350RI.getAllocatableSet351(*II->getParent()->getParent(), &Mips::CPU16RegsRegClass);352// Exclude all the registers being used by the instruction.353for (MachineOperand &MO : II->operands()) {354if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() &&355!MO.getReg().isVirtual())356Candidates.reset(MO.getReg());357}358359// If the same register was used and defined in an instruction, then360// it will not be in the list of candidates.361//362// we need to analyze the instruction that we are helping.363// we need to know if it defines register x but register x is not364// present as an operand of the instruction. this tells365// whether the register is live before the instruction. if it's not366// then we don't need to save it in case there are no free registers.367int DefReg = 0;368for (MachineOperand &MO : II->operands()) {369if (MO.isReg() && MO.isDef()) {370DefReg = MO.getReg();371break;372}373}374375BitVector Available = rs.getRegsAvailable(&Mips::CPU16RegsRegClass);376Available &= Candidates;377//378// we use T0 for the first register, if we need to save something away.379// we use T1 for the second register, if we need to save something away.380//381unsigned FirstRegSaved =0, SecondRegSaved=0;382unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0;383384Reg = Available.find_first();385386if (Reg == -1) {387Reg = Candidates.find_first();388Candidates.reset(Reg);389if (DefReg != Reg) {390FirstRegSaved = Reg;391FirstRegSavedTo = Mips::T0;392copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true);393}394}395else396Available.reset(Reg);397BuildMI(MBB, II, DL, get(Mips::LwConstant32), Reg).addImm(Imm).addImm(-1);398NewImm = 0;399if (FrameReg == Mips::SP) {400SpReg = Available.find_first();401if (SpReg == -1) {402SpReg = Candidates.find_first();403// Candidates.reset(SpReg); // not really needed404if (DefReg!= SpReg) {405SecondRegSaved = SpReg;406SecondRegSavedTo = Mips::T1;407}408if (SecondRegSaved)409copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true);410}411else412Available.reset(SpReg);413copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false);414BuildMI(MBB, II, DL, get(Mips::AdduRxRyRz16), Reg)415.addReg(SpReg, RegState::Kill)416.addReg(Reg);417}418else419BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(FrameReg)420.addReg(Reg, RegState::Kill);421if (FirstRegSaved || SecondRegSaved) {422II = std::next(II);423if (FirstRegSaved)424copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true);425if (SecondRegSaved)426copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true);427}428return Reg;429}430431unsigned Mips16InstrInfo::getAnalyzableBrOpc(unsigned Opc) const {432return (Opc == Mips::BeqzRxImmX16 || Opc == Mips::BimmX16 ||433Opc == Mips::Bimm16 ||434Opc == Mips::Bteqz16 || Opc == Mips::Btnez16 ||435Opc == Mips::BeqzRxImm16 || Opc == Mips::BnezRxImm16 ||436Opc == Mips::BnezRxImmX16 || Opc == Mips::BteqzX16 ||437Opc == Mips::BteqzT8CmpX16 || Opc == Mips::BteqzT8CmpiX16 ||438Opc == Mips::BteqzT8SltX16 || Opc == Mips::BteqzT8SltuX16 ||439Opc == Mips::BteqzT8SltiX16 || Opc == Mips::BteqzT8SltiuX16 ||440Opc == Mips::BtnezX16 || Opc == Mips::BtnezT8CmpX16 ||441Opc == Mips::BtnezT8CmpiX16 || Opc == Mips::BtnezT8SltX16 ||442Opc == Mips::BtnezT8SltuX16 || Opc == Mips::BtnezT8SltiX16 ||443Opc == Mips::BtnezT8SltiuX16 ) ? Opc : 0;444}445446void Mips16InstrInfo::ExpandRetRA16(MachineBasicBlock &MBB,447MachineBasicBlock::iterator I,448unsigned Opc) const {449BuildMI(MBB, I, I->getDebugLoc(), get(Opc));450}451452const MCInstrDesc &Mips16InstrInfo::AddiuSpImm(int64_t Imm) const {453if (validSpImm8(Imm))454return get(Mips::AddiuSpImm16);455else456return get(Mips::AddiuSpImmX16);457}458459void Mips16InstrInfo::BuildAddiuSpImm460(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const {461DebugLoc DL;462BuildMI(MBB, I, DL, AddiuSpImm(Imm)).addImm(Imm);463}464465const MipsInstrInfo *llvm::createMips16InstrInfo(const MipsSubtarget &STI) {466return new Mips16InstrInfo(STI);467}468469bool Mips16InstrInfo::validImmediate(unsigned Opcode, unsigned Reg,470int64_t Amount) {471switch (Opcode) {472case Mips::LbRxRyOffMemX16:473case Mips::LbuRxRyOffMemX16:474case Mips::LhRxRyOffMemX16:475case Mips::LhuRxRyOffMemX16:476case Mips::SbRxRyOffMemX16:477case Mips::ShRxRyOffMemX16:478case Mips::LwRxRyOffMemX16:479case Mips::SwRxRyOffMemX16:480case Mips::SwRxSpImmX16:481case Mips::LwRxSpImmX16:482return isInt<16>(Amount);483case Mips::AddiuRxRyOffMemX16:484if ((Reg == Mips::PC) || (Reg == Mips::SP))485return isInt<16>(Amount);486return isInt<15>(Amount);487}488llvm_unreachable("unexpected Opcode in validImmediate");489}490491492