10b57cec5SDimitry Andric //===-- Mips16RegisterInfo.cpp - MIPS16 Register Information --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the MIPS16 implementation of the TargetRegisterInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "Mips16RegisterInfo.h"
140b57cec5SDimitry Andric #include "Mips.h"
150b57cec5SDimitry Andric #include "Mips16InstrInfo.h"
160b57cec5SDimitry Andric #include "MipsInstrInfo.h"
170b57cec5SDimitry Andric #include "MipsMachineFunction.h"
180b57cec5SDimitry Andric #include "MipsSubtarget.h"
190b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
260b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
270b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h"
280b57cec5SDimitry Andric #include "llvm/IR/Function.h"
290b57cec5SDimitry Andric #include "llvm/IR/Type.h"
300b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
310b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
330b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
340b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h"
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric #define DEBUG_TYPE "mips16-registerinfo"
390b57cec5SDimitry Andric
40*81ad6265SDimitry Andric Mips16RegisterInfo::Mips16RegisterInfo() = default;
410b57cec5SDimitry Andric
requiresRegisterScavenging(const MachineFunction & MF) const420b57cec5SDimitry Andric bool Mips16RegisterInfo::requiresRegisterScavenging
430b57cec5SDimitry Andric (const MachineFunction &MF) const {
440b57cec5SDimitry Andric return false;
450b57cec5SDimitry Andric }
requiresFrameIndexScavenging(const MachineFunction & MF) const460b57cec5SDimitry Andric bool Mips16RegisterInfo::requiresFrameIndexScavenging
470b57cec5SDimitry Andric (const MachineFunction &MF) const {
480b57cec5SDimitry Andric return false;
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric
useFPForScavengingIndex(const MachineFunction & MF) const510b57cec5SDimitry Andric bool Mips16RegisterInfo::useFPForScavengingIndex
520b57cec5SDimitry Andric (const MachineFunction &MF) const {
530b57cec5SDimitry Andric return false;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
saveScavengerRegister(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,MachineBasicBlock::iterator & UseMI,const TargetRegisterClass * RC,Register Reg) const565ffd83dbSDimitry Andric bool Mips16RegisterInfo::saveScavengerRegister(
575ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
585ffd83dbSDimitry Andric MachineBasicBlock::iterator &UseMI, const TargetRegisterClass *RC,
595ffd83dbSDimitry Andric Register Reg) const {
600b57cec5SDimitry Andric DebugLoc DL;
610b57cec5SDimitry Andric const TargetInstrInfo &TII = *MBB.getParent()->getSubtarget().getInstrInfo();
620b57cec5SDimitry Andric TII.copyPhysReg(MBB, I, DL, Mips::T0, Reg, true);
630b57cec5SDimitry Andric TII.copyPhysReg(MBB, UseMI, DL, Reg, Mips::T0, true);
640b57cec5SDimitry Andric return true;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric const TargetRegisterClass *
intRegClass(unsigned Size) const680b57cec5SDimitry Andric Mips16RegisterInfo::intRegClass(unsigned Size) const {
690b57cec5SDimitry Andric assert(Size == 4);
700b57cec5SDimitry Andric return &Mips::CPU16RegsRegClass;
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric
eliminateFI(MachineBasicBlock::iterator II,unsigned OpNo,int FrameIndex,uint64_t StackSize,int64_t SPOffset) const730b57cec5SDimitry Andric void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
740b57cec5SDimitry Andric unsigned OpNo, int FrameIndex,
750b57cec5SDimitry Andric uint64_t StackSize,
760b57cec5SDimitry Andric int64_t SPOffset) const {
770b57cec5SDimitry Andric MachineInstr &MI = *II;
780b57cec5SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent();
790b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
820b57cec5SDimitry Andric int MinCSFI = 0;
830b57cec5SDimitry Andric int MaxCSFI = -1;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric if (CSI.size()) {
860b57cec5SDimitry Andric MinCSFI = CSI[0].getFrameIdx();
870b57cec5SDimitry Andric MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric // The following stack frame objects are always
910b57cec5SDimitry Andric // referenced relative to $sp:
920b57cec5SDimitry Andric // 1. Outgoing arguments.
930b57cec5SDimitry Andric // 2. Pointer to dynamically allocated stack space.
940b57cec5SDimitry Andric // 3. Locations for callee-saved registers.
950b57cec5SDimitry Andric // Everything else is referenced relative to whatever register
960b57cec5SDimitry Andric // getFrameRegister() returns.
975ffd83dbSDimitry Andric Register FrameReg;
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)
1000b57cec5SDimitry Andric FrameReg = Mips::SP;
1010b57cec5SDimitry Andric else {
1020b57cec5SDimitry Andric const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
1030b57cec5SDimitry Andric if (TFI->hasFP(MF)) {
1040b57cec5SDimitry Andric FrameReg = Mips::S0;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric else {
1070b57cec5SDimitry Andric if ((MI.getNumOperands()> OpNo+2) && MI.getOperand(OpNo+2).isReg())
1080b57cec5SDimitry Andric FrameReg = MI.getOperand(OpNo+2).getReg();
1090b57cec5SDimitry Andric else
1100b57cec5SDimitry Andric FrameReg = Mips::SP;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric // Calculate final offset.
1140b57cec5SDimitry Andric // - There is no need to change the offset if the frame object
1150b57cec5SDimitry Andric // is one of the
1160b57cec5SDimitry Andric // following: an outgoing argument, pointer to a dynamically allocated
1170b57cec5SDimitry Andric // stack space or a $gp restore location,
1180b57cec5SDimitry Andric // - If the frame object is any of the following,
1190b57cec5SDimitry Andric // its offset must be adjusted
1200b57cec5SDimitry Andric // by adding the size of the stack:
1210b57cec5SDimitry Andric // incoming argument, callee-saved register location or local variable.
1220b57cec5SDimitry Andric int64_t Offset;
1230b57cec5SDimitry Andric bool IsKill = false;
1240b57cec5SDimitry Andric Offset = SPOffset + (int64_t)StackSize;
1250b57cec5SDimitry Andric Offset += MI.getOperand(OpNo + 1).getImm();
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric LLVM_DEBUG(errs() << "Offset : " << Offset << "\n"
1280b57cec5SDimitry Andric << "<--------->\n");
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric if (!MI.isDebugValue() &&
1310b57cec5SDimitry Andric !Mips16InstrInfo::validImmediate(MI.getOpcode(), FrameReg, Offset)) {
1320b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent();
1330b57cec5SDimitry Andric DebugLoc DL = II->getDebugLoc();
1340b57cec5SDimitry Andric unsigned NewImm;
1350b57cec5SDimitry Andric const Mips16InstrInfo &TII =
1360b57cec5SDimitry Andric *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo());
1370b57cec5SDimitry Andric FrameReg = TII.loadImmediate(FrameReg, Offset, MBB, II, DL, NewImm);
1380b57cec5SDimitry Andric Offset = SignExtend64<16>(NewImm);
1390b57cec5SDimitry Andric IsKill = true;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
1420b57cec5SDimitry Andric MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric }
146