| 1 | //===-- Mips16RegisterInfo.cpp - MIPS16 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-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file contains the MIPS16 implementation of the TargetRegisterInfo class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "Mips16RegisterInfo.h" |
| 14 | #include "Mips16InstrInfo.h" |
| 15 | #include "MipsInstrInfo.h" |
| 16 | #include "llvm/CodeGen/MachineFrameInfo.h" |
| 17 | #include "llvm/CodeGen/MachineFunction.h" |
| 18 | #include "llvm/CodeGen/TargetFrameLowering.h" |
| 19 | #include "llvm/CodeGen/TargetInstrInfo.h" |
| 20 | #include "llvm/IR/Function.h" |
| 21 | #include "llvm/IR/Type.h" |
| 22 | #include "llvm/Support/Debug.h" |
| 23 | #include "llvm/Support/raw_ostream.h" |
| 24 | #include "llvm/Target/TargetMachine.h" |
| 25 | #include "llvm/Target/TargetOptions.h" |
| 26 | |
| 27 | using namespace llvm; |
| 28 | |
| 29 | #define DEBUG_TYPE "mips16-registerinfo" |
| 30 | |
| 31 | Mips16RegisterInfo::Mips16RegisterInfo(const MipsSubtarget &STI) |
| 32 | : MipsRegisterInfo(STI) {} |
| 33 | |
| 34 | bool Mips16RegisterInfo::requiresRegisterScavenging |
| 35 | (const MachineFunction &MF) const { |
| 36 | return false; |
| 37 | } |
| 38 | bool Mips16RegisterInfo::requiresFrameIndexScavenging |
| 39 | (const MachineFunction &MF) const { |
| 40 | return false; |
| 41 | } |
| 42 | |
| 43 | bool Mips16RegisterInfo::useFPForScavengingIndex |
| 44 | (const MachineFunction &MF) const { |
| 45 | return false; |
| 46 | } |
| 47 | |
| 48 | bool Mips16RegisterInfo::saveScavengerRegister( |
| 49 | MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
| 50 | MachineBasicBlock::iterator &UseMI, const TargetRegisterClass *RC, |
| 51 | Register Reg) const { |
| 52 | DebugLoc DL; |
| 53 | const TargetInstrInfo &TII = *MBB.getParent()->getSubtarget().getInstrInfo(); |
| 54 | TII.copyPhysReg(MBB, MI: I, DL, DestReg: Mips::T0, SrcReg: Reg, KillSrc: true); |
| 55 | TII.copyPhysReg(MBB, MI: UseMI, DL, DestReg: Reg, SrcReg: Mips::T0, KillSrc: true); |
| 56 | return true; |
| 57 | } |
| 58 | |
| 59 | const TargetRegisterClass * |
| 60 | Mips16RegisterInfo::intRegClass(unsigned Size) const { |
| 61 | assert(Size == 4); |
| 62 | return &Mips::CPU16RegsRegClass; |
| 63 | } |
| 64 | |
| 65 | void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, |
| 66 | unsigned OpNo, int FrameIndex, |
| 67 | uint64_t StackSize, |
| 68 | int64_t SPOffset) const { |
| 69 | MachineInstr &MI = *II; |
| 70 | MachineFunction &MF = *MI.getParent()->getParent(); |
| 71 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 72 | |
| 73 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
| 74 | int MinCSFI = 0; |
| 75 | int MaxCSFI = -1; |
| 76 | |
| 77 | if (CSI.size()) { |
| 78 | MinCSFI = CSI[0].getFrameIdx(); |
| 79 | MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); |
| 80 | } |
| 81 | |
| 82 | // The following stack frame objects are always |
| 83 | // referenced relative to $sp: |
| 84 | // 1. Outgoing arguments. |
| 85 | // 2. Pointer to dynamically allocated stack space. |
| 86 | // 3. Locations for callee-saved registers. |
| 87 | // Everything else is referenced relative to whatever register |
| 88 | // getFrameRegister() returns. |
| 89 | Register FrameReg; |
| 90 | |
| 91 | if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) |
| 92 | FrameReg = Mips::SP; |
| 93 | else { |
| 94 | const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); |
| 95 | if (TFI->hasFP(MF)) { |
| 96 | FrameReg = Mips::S0; |
| 97 | } |
| 98 | else { |
| 99 | if ((MI.getNumOperands()> OpNo+2) && MI.getOperand(i: OpNo+2).isReg()) |
| 100 | FrameReg = MI.getOperand(i: OpNo+2).getReg(); |
| 101 | else |
| 102 | FrameReg = Mips::SP; |
| 103 | } |
| 104 | } |
| 105 | // Calculate final offset. |
| 106 | // - There is no need to change the offset if the frame object |
| 107 | // is one of the |
| 108 | // following: an outgoing argument, pointer to a dynamically allocated |
| 109 | // stack space or a $gp restore location, |
| 110 | // - If the frame object is any of the following, |
| 111 | // its offset must be adjusted |
| 112 | // by adding the size of the stack: |
| 113 | // incoming argument, callee-saved register location or local variable. |
| 114 | int64_t Offset; |
| 115 | bool IsKill = false; |
| 116 | Offset = SPOffset + (int64_t)StackSize; |
| 117 | Offset += MI.getOperand(i: OpNo + 1).getImm(); |
| 118 | |
| 119 | LLVM_DEBUG(errs() << "Offset : " << Offset << "\n" |
| 120 | << "<--------->\n" ); |
| 121 | |
| 122 | if (!MI.isDebugValue() && |
| 123 | !Mips16InstrInfo::validImmediate(Opcode: MI.getOpcode(), Reg: FrameReg, Amount: Offset)) { |
| 124 | MachineBasicBlock &MBB = *MI.getParent(); |
| 125 | DebugLoc DL = II->getDebugLoc(); |
| 126 | unsigned NewImm; |
| 127 | const Mips16InstrInfo &TII = |
| 128 | *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); |
| 129 | FrameReg = TII.loadImmediate(FrameReg, Imm: Offset, MBB, II, DL, NewImm); |
| 130 | Offset = SignExtend64<16>(x: NewImm); |
| 131 | IsKill = true; |
| 132 | } |
| 133 | MI.getOperand(i: OpNo).ChangeToRegister(Reg: FrameReg, isDef: false, isImp: false, isKill: IsKill); |
| 134 | MI.getOperand(i: OpNo + 1).ChangeToImmediate(ImmVal: Offset); |
| 135 | |
| 136 | |
| 137 | } |
| 138 | |