| 1 | //===- MipsSEFrameLowering.cpp - Mips32/64 Frame 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 Mips32/64 implementation of TargetFrameLowering class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "MipsSEFrameLowering.h" |
| 14 | #include "MCTargetDesc/MipsABIInfo.h" |
| 15 | #include "MipsMachineFunction.h" |
| 16 | #include "MipsRegisterInfo.h" |
| 17 | #include "MipsSEInstrInfo.h" |
| 18 | #include "MipsSubtarget.h" |
| 19 | #include "llvm/ADT/BitVector.h" |
| 20 | #include "llvm/ADT/StringRef.h" |
| 21 | #include "llvm/ADT/StringSwitch.h" |
| 22 | #include "llvm/CodeGen/CFIInstBuilder.h" |
| 23 | #include "llvm/CodeGen/MachineBasicBlock.h" |
| 24 | #include "llvm/CodeGen/MachineFrameInfo.h" |
| 25 | #include "llvm/CodeGen/MachineFunction.h" |
| 26 | #include "llvm/CodeGen/MachineInstr.h" |
| 27 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
| 28 | #include "llvm/CodeGen/MachineModuleInfo.h" |
| 29 | #include "llvm/CodeGen/MachineOperand.h" |
| 30 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
| 31 | #include "llvm/CodeGen/RegisterScavenging.h" |
| 32 | #include "llvm/CodeGen/TargetInstrInfo.h" |
| 33 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
| 34 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
| 35 | #include "llvm/IR/DebugLoc.h" |
| 36 | #include "llvm/IR/Function.h" |
| 37 | #include "llvm/Support/CodeGen.h" |
| 38 | #include "llvm/Support/ErrorHandling.h" |
| 39 | #include "llvm/Support/MathExtras.h" |
| 40 | #include <cassert> |
| 41 | #include <cstdint> |
| 42 | #include <utility> |
| 43 | #include <vector> |
| 44 | |
| 45 | using namespace llvm; |
| 46 | |
| 47 | static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) { |
| 48 | if (Mips::ACC64RegClass.contains(Reg: Src)) |
| 49 | return std::make_pair(x: (unsigned)Mips::PseudoMFHI, |
| 50 | y: (unsigned)Mips::PseudoMFLO); |
| 51 | |
| 52 | if (Mips::ACC64DSPRegClass.contains(Reg: Src)) |
| 53 | return std::make_pair(x: (unsigned)Mips::MFHI_DSP, y: (unsigned)Mips::MFLO_DSP); |
| 54 | |
| 55 | if (Mips::ACC128RegClass.contains(Reg: Src)) |
| 56 | return std::make_pair(x: (unsigned)Mips::PseudoMFHI64, |
| 57 | y: (unsigned)Mips::PseudoMFLO64); |
| 58 | |
| 59 | return std::make_pair(x: 0, y: 0); |
| 60 | } |
| 61 | |
| 62 | namespace { |
| 63 | |
| 64 | /// Helper class to expand pseudos. |
| 65 | class ExpandPseudo { |
| 66 | public: |
| 67 | ExpandPseudo(MachineFunction &MF); |
| 68 | bool expand(); |
| 69 | |
| 70 | private: |
| 71 | using Iter = MachineBasicBlock::iterator; |
| 72 | |
| 73 | bool expandInstr(MachineBasicBlock &MBB, Iter I); |
| 74 | void expandLoadCCond(MachineBasicBlock &MBB, Iter I); |
| 75 | void expandStoreCCond(MachineBasicBlock &MBB, Iter I); |
| 76 | void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize); |
| 77 | void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, |
| 78 | unsigned MFLoOpc, unsigned RegSize); |
| 79 | bool expandCopy(MachineBasicBlock &MBB, Iter I); |
| 80 | bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, |
| 81 | unsigned MFLoOpc); |
| 82 | bool expandBuildPairF64(MachineBasicBlock &MBB, |
| 83 | MachineBasicBlock::iterator I, bool FP64) const; |
| 84 | bool expandExtractElementF64(MachineBasicBlock &MBB, |
| 85 | MachineBasicBlock::iterator I, bool FP64) const; |
| 86 | |
| 87 | MachineFunction &MF; |
| 88 | MachineRegisterInfo &MRI; |
| 89 | const MipsSubtarget &Subtarget; |
| 90 | const MipsSEInstrInfo &TII; |
| 91 | const MipsRegisterInfo &RegInfo; |
| 92 | }; |
| 93 | |
| 94 | } // end anonymous namespace |
| 95 | |
| 96 | ExpandPseudo::ExpandPseudo(MachineFunction &MF_) |
| 97 | : MF(MF_), MRI(MF.getRegInfo()), |
| 98 | Subtarget(MF.getSubtarget<MipsSubtarget>()), |
| 99 | TII(*static_cast<const MipsSEInstrInfo *>(Subtarget.getInstrInfo())), |
| 100 | RegInfo(*Subtarget.getRegisterInfo()) {} |
| 101 | |
| 102 | bool ExpandPseudo::expand() { |
| 103 | bool Expanded = false; |
| 104 | |
| 105 | for (auto &MBB : MF) { |
| 106 | for (Iter I = MBB.begin(), End = MBB.end(); I != End;) |
| 107 | Expanded |= expandInstr(MBB, I: I++); |
| 108 | } |
| 109 | |
| 110 | return Expanded; |
| 111 | } |
| 112 | |
| 113 | bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { |
| 114 | switch(I->getOpcode()) { |
| 115 | case Mips::LOAD_CCOND_DSP: |
| 116 | expandLoadCCond(MBB, I); |
| 117 | break; |
| 118 | case Mips::STORE_CCOND_DSP: |
| 119 | expandStoreCCond(MBB, I); |
| 120 | break; |
| 121 | case Mips::LOAD_ACC64: |
| 122 | case Mips::LOAD_ACC64DSP: |
| 123 | expandLoadACC(MBB, I, RegSize: 4); |
| 124 | break; |
| 125 | case Mips::LOAD_ACC128: |
| 126 | expandLoadACC(MBB, I, RegSize: 8); |
| 127 | break; |
| 128 | case Mips::STORE_ACC64: |
| 129 | expandStoreACC(MBB, I, MFHiOpc: Mips::PseudoMFHI, MFLoOpc: Mips::PseudoMFLO, RegSize: 4); |
| 130 | break; |
| 131 | case Mips::STORE_ACC64DSP: |
| 132 | expandStoreACC(MBB, I, MFHiOpc: Mips::MFHI_DSP, MFLoOpc: Mips::MFLO_DSP, RegSize: 4); |
| 133 | break; |
| 134 | case Mips::STORE_ACC128: |
| 135 | expandStoreACC(MBB, I, MFHiOpc: Mips::PseudoMFHI64, MFLoOpc: Mips::PseudoMFLO64, RegSize: 8); |
| 136 | break; |
| 137 | case Mips::BuildPairF64: |
| 138 | if (expandBuildPairF64(MBB, I, FP64: false)) |
| 139 | MBB.erase(I); |
| 140 | return false; |
| 141 | case Mips::BuildPairF64_64: |
| 142 | if (expandBuildPairF64(MBB, I, FP64: true)) |
| 143 | MBB.erase(I); |
| 144 | return false; |
| 145 | case Mips::ExtractElementF64: |
| 146 | if (expandExtractElementF64(MBB, I, FP64: false)) |
| 147 | MBB.erase(I); |
| 148 | return false; |
| 149 | case Mips::ExtractElementF64_64: |
| 150 | if (expandExtractElementF64(MBB, I, FP64: true)) |
| 151 | MBB.erase(I); |
| 152 | return false; |
| 153 | case TargetOpcode::COPY: |
| 154 | if (!expandCopy(MBB, I)) |
| 155 | return false; |
| 156 | break; |
| 157 | default: |
| 158 | return false; |
| 159 | } |
| 160 | |
| 161 | MBB.erase(I); |
| 162 | return true; |
| 163 | } |
| 164 | |
| 165 | void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { |
| 166 | // load $vr, FI |
| 167 | // copy ccond, $vr |
| 168 | |
| 169 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
| 170 | |
| 171 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: 4); |
| 172 | Register VR = MRI.createVirtualRegister(RegClass: RC); |
| 173 | Register Dst = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
| 174 | |
| 175 | TII.loadRegFromStack(MBB, MI: I, DestReg: VR, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
| 176 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: Dst) |
| 177 | .addReg(RegNo: VR, flags: RegState::Kill); |
| 178 | } |
| 179 | |
| 180 | void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { |
| 181 | // copy $vr, ccond |
| 182 | // store $vr, FI |
| 183 | |
| 184 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
| 185 | |
| 186 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: 4); |
| 187 | Register VR = MRI.createVirtualRegister(RegClass: RC); |
| 188 | Register Src = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
| 189 | |
| 190 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: VR) |
| 191 | .addReg(RegNo: Src, flags: getKillRegState(B: I->getOperand(i: 0).isKill())); |
| 192 | TII.storeRegToStack(MBB, MI: I, SrcReg: VR, isKill: true, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
| 193 | } |
| 194 | |
| 195 | void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, |
| 196 | unsigned RegSize) { |
| 197 | // load $vr0, FI |
| 198 | // copy lo, $vr0 |
| 199 | // load $vr1, FI + 4 |
| 200 | // copy hi, $vr1 |
| 201 | |
| 202 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
| 203 | |
| 204 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: RegSize); |
| 205 | Register VR0 = MRI.createVirtualRegister(RegClass: RC); |
| 206 | Register VR1 = MRI.createVirtualRegister(RegClass: RC); |
| 207 | Register Dst = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
| 208 | Register Lo = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_lo); |
| 209 | Register Hi = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_hi); |
| 210 | DebugLoc DL = I->getDebugLoc(); |
| 211 | const MCInstrDesc &Desc = TII.get(Opcode: TargetOpcode::COPY); |
| 212 | |
| 213 | TII.loadRegFromStack(MBB, MI: I, DestReg: VR0, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
| 214 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: Desc, DestReg: Lo).addReg(RegNo: VR0, flags: RegState::Kill); |
| 215 | TII.loadRegFromStack(MBB, MI: I, DestReg: VR1, FrameIndex: FI, RC, TRI: &RegInfo, Offset: RegSize); |
| 216 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: Desc, DestReg: Hi).addReg(RegNo: VR1, flags: RegState::Kill); |
| 217 | } |
| 218 | |
| 219 | void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, |
| 220 | unsigned MFHiOpc, unsigned MFLoOpc, |
| 221 | unsigned RegSize) { |
| 222 | // mflo $vr0, src |
| 223 | // store $vr0, FI |
| 224 | // mfhi $vr1, src |
| 225 | // store $vr1, FI + 4 |
| 226 | |
| 227 | assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); |
| 228 | |
| 229 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: RegSize); |
| 230 | Register VR0 = MRI.createVirtualRegister(RegClass: RC); |
| 231 | Register VR1 = MRI.createVirtualRegister(RegClass: RC); |
| 232 | Register Src = I->getOperand(i: 0).getReg(), FI = I->getOperand(i: 1).getIndex(); |
| 233 | unsigned SrcKill = getKillRegState(B: I->getOperand(i: 0).isKill()); |
| 234 | DebugLoc DL = I->getDebugLoc(); |
| 235 | |
| 236 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFLoOpc), DestReg: VR0).addReg(RegNo: Src); |
| 237 | TII.storeRegToStack(MBB, MI: I, SrcReg: VR0, isKill: true, FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
| 238 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFHiOpc), DestReg: VR1).addReg(RegNo: Src, flags: SrcKill); |
| 239 | TII.storeRegToStack(MBB, MI: I, SrcReg: VR1, isKill: true, FrameIndex: FI, RC, TRI: &RegInfo, Offset: RegSize); |
| 240 | } |
| 241 | |
| 242 | bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) { |
| 243 | Register Src = I->getOperand(i: 1).getReg(); |
| 244 | std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src); |
| 245 | |
| 246 | if (!Opcodes.first) |
| 247 | return false; |
| 248 | |
| 249 | return expandCopyACC(MBB, I, MFHiOpc: Opcodes.first, MFLoOpc: Opcodes.second); |
| 250 | } |
| 251 | |
| 252 | bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, |
| 253 | unsigned MFHiOpc, unsigned MFLoOpc) { |
| 254 | // mflo $vr0, src |
| 255 | // copy dst_lo, $vr0 |
| 256 | // mfhi $vr1, src |
| 257 | // copy dst_hi, $vr1 |
| 258 | |
| 259 | unsigned Dst = I->getOperand(i: 0).getReg(), Src = I->getOperand(i: 1).getReg(); |
| 260 | const TargetRegisterClass *DstRC = RegInfo.getMinimalPhysRegClass(Reg: Dst); |
| 261 | unsigned VRegSize = RegInfo.getRegSizeInBits(RC: *DstRC) / 16; |
| 262 | const TargetRegisterClass *RC = RegInfo.intRegClass(Size: VRegSize); |
| 263 | Register VR0 = MRI.createVirtualRegister(RegClass: RC); |
| 264 | Register VR1 = MRI.createVirtualRegister(RegClass: RC); |
| 265 | unsigned SrcKill = getKillRegState(B: I->getOperand(i: 1).isKill()); |
| 266 | Register DstLo = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_lo); |
| 267 | Register DstHi = RegInfo.getSubReg(Reg: Dst, Idx: Mips::sub_hi); |
| 268 | DebugLoc DL = I->getDebugLoc(); |
| 269 | |
| 270 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFLoOpc), DestReg: VR0).addReg(RegNo: Src); |
| 271 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: DstLo) |
| 272 | .addReg(RegNo: VR0, flags: RegState::Kill); |
| 273 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MFHiOpc), DestReg: VR1).addReg(RegNo: Src, flags: SrcKill); |
| 274 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: TargetOpcode::COPY), DestReg: DstHi) |
| 275 | .addReg(RegNo: VR1, flags: RegState::Kill); |
| 276 | return true; |
| 277 | } |
| 278 | |
| 279 | /// This method expands the same instruction that MipsSEInstrInfo:: |
| 280 | /// expandBuildPairF64 does, for the case when ABI is fpxx and mthc1 is not |
| 281 | /// available and the case where the ABI is FP64A. It is implemented here |
| 282 | /// because frame indexes are eliminated before MipsSEInstrInfo:: |
| 283 | /// expandBuildPairF64 is called. |
| 284 | bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, |
| 285 | MachineBasicBlock::iterator I, |
| 286 | bool FP64) const { |
| 287 | // For fpxx and when mthc1 is not available, use: |
| 288 | // spill + reload via ldc1 |
| 289 | // |
| 290 | // The case where dmtc1 is available doesn't need to be handled here |
| 291 | // because it never creates a BuildPairF64 node. |
| 292 | // |
| 293 | // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence |
| 294 | // for odd-numbered double precision values (because the lower 32-bits is |
| 295 | // transferred with mtc1 which is redirected to the upper half of the even |
| 296 | // register). Unfortunately, we have to make this decision before register |
| 297 | // allocation so for now we use a spill/reload sequence for all |
| 298 | // double-precision values in regardless of being an odd/even register. |
| 299 | // |
| 300 | // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as |
| 301 | // implicit operand, so other passes (like ShrinkWrapping) are aware that |
| 302 | // stack is used. |
| 303 | if (I->getNumOperands() == 4 && I->getOperand(i: 3).isReg() |
| 304 | && I->getOperand(i: 3).getReg() == Mips::SP) { |
| 305 | Register DstReg = I->getOperand(i: 0).getReg(); |
| 306 | Register LoReg = I->getOperand(i: 1).getReg(); |
| 307 | Register HiReg = I->getOperand(i: 2).getReg(); |
| 308 | |
| 309 | // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are |
| 310 | // the cases where mthc1 is not available). 64-bit architectures and |
| 311 | // MIPS32r2 or later can use FGR64 though. |
| 312 | assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || |
| 313 | !Subtarget.isFP64bit()); |
| 314 | |
| 315 | const TargetRegisterClass *RC = &Mips::GPR32RegClass; |
| 316 | const TargetRegisterClass *RC2 = |
| 317 | FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; |
| 318 | |
| 319 | // We re-use the same spill slot each time so that the stack frame doesn't |
| 320 | // grow too much in functions with a large number of moves. |
| 321 | int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC: RC2); |
| 322 | if (!Subtarget.isLittle()) |
| 323 | std::swap(a&: LoReg, b&: HiReg); |
| 324 | TII.storeRegToStack(MBB, MI: I, SrcReg: LoReg, isKill: I->getOperand(i: 1).isKill(), FrameIndex: FI, RC, |
| 325 | TRI: &RegInfo, Offset: 0); |
| 326 | TII.storeRegToStack(MBB, MI: I, SrcReg: HiReg, isKill: I->getOperand(i: 2).isKill(), FrameIndex: FI, RC, |
| 327 | TRI: &RegInfo, Offset: 4); |
| 328 | TII.loadRegFromStack(MBB, MI: I, DestReg: DstReg, FrameIndex: FI, RC: RC2, TRI: &RegInfo, Offset: 0); |
| 329 | return true; |
| 330 | } |
| 331 | |
| 332 | return false; |
| 333 | } |
| 334 | |
| 335 | /// This method expands the same instruction that MipsSEInstrInfo:: |
| 336 | /// expandExtractElementF64 does, for the case when ABI is fpxx and mfhc1 is not |
| 337 | /// available and the case where the ABI is FP64A. It is implemented here |
| 338 | /// because frame indexes are eliminated before MipsSEInstrInfo:: |
| 339 | /// expandExtractElementF64 is called. |
| 340 | bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, |
| 341 | MachineBasicBlock::iterator I, |
| 342 | bool FP64) const { |
| 343 | const MachineOperand &Op1 = I->getOperand(i: 1); |
| 344 | const MachineOperand &Op2 = I->getOperand(i: 2); |
| 345 | |
| 346 | if ((Op1.isReg() && Op1.isUndef()) || (Op2.isReg() && Op2.isUndef())) { |
| 347 | Register DstReg = I->getOperand(i: 0).getReg(); |
| 348 | BuildMI(BB&: MBB, I, MIMD: I->getDebugLoc(), MCID: TII.get(Opcode: Mips::IMPLICIT_DEF), DestReg: DstReg); |
| 349 | return true; |
| 350 | } |
| 351 | |
| 352 | // For fpxx and when mfhc1 is not available, use: |
| 353 | // spill + reload via ldc1 |
| 354 | // |
| 355 | // The case where dmfc1 is available doesn't need to be handled here |
| 356 | // because it never creates a ExtractElementF64 node. |
| 357 | // |
| 358 | // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence |
| 359 | // for odd-numbered double precision values (because the lower 32-bits is |
| 360 | // transferred with mfc1 which is redirected to the upper half of the even |
| 361 | // register). Unfortunately, we have to make this decision before register |
| 362 | // allocation so for now we use a spill/reload sequence for all |
| 363 | // double-precision values in regardless of being an odd/even register. |
| 364 | // |
| 365 | // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as |
| 366 | // implicit operand, so other passes (like ShrinkWrapping) are aware that |
| 367 | // stack is used. |
| 368 | if (I->getNumOperands() == 4 && I->getOperand(i: 3).isReg() |
| 369 | && I->getOperand(i: 3).getReg() == Mips::SP) { |
| 370 | Register DstReg = I->getOperand(i: 0).getReg(); |
| 371 | Register SrcReg = Op1.getReg(); |
| 372 | unsigned N = Op2.getImm(); |
| 373 | int64_t Offset = 4 * (Subtarget.isLittle() ? N : (1 - N)); |
| 374 | |
| 375 | // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are |
| 376 | // the cases where mfhc1 is not available). 64-bit architectures and |
| 377 | // MIPS32r2 or later can use FGR64 though. |
| 378 | assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || |
| 379 | !Subtarget.isFP64bit()); |
| 380 | |
| 381 | const TargetRegisterClass *RC = |
| 382 | FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; |
| 383 | const TargetRegisterClass *RC2 = &Mips::GPR32RegClass; |
| 384 | |
| 385 | // We re-use the same spill slot each time so that the stack frame doesn't |
| 386 | // grow too much in functions with a large number of moves. |
| 387 | int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC); |
| 388 | TII.storeRegToStack(MBB, MI: I, SrcReg, isKill: Op1.isKill(), FrameIndex: FI, RC, TRI: &RegInfo, Offset: 0); |
| 389 | TII.loadRegFromStack(MBB, MI: I, DestReg: DstReg, FrameIndex: FI, RC: RC2, TRI: &RegInfo, Offset); |
| 390 | return true; |
| 391 | } |
| 392 | |
| 393 | return false; |
| 394 | } |
| 395 | |
| 396 | MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI) |
| 397 | : MipsFrameLowering(STI, STI.getStackAlignment()) {} |
| 398 | |
| 399 | void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, |
| 400 | MachineBasicBlock &MBB) const { |
| 401 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 402 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
| 403 | |
| 404 | const MipsSEInstrInfo &TII = |
| 405 | *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); |
| 406 | const MipsRegisterInfo &RegInfo = |
| 407 | *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); |
| 408 | |
| 409 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
| 410 | DebugLoc dl; |
| 411 | MipsABIInfo ABI = STI.getABI(); |
| 412 | unsigned SP = ABI.GetStackPtr(); |
| 413 | unsigned FP = ABI.GetFramePtr(); |
| 414 | unsigned ZERO = ABI.GetNullPtr(); |
| 415 | unsigned MOVE = ABI.GetGPRMoveOp(); |
| 416 | unsigned ADDiu = ABI.GetPtrAddiuOp(); |
| 417 | unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND; |
| 418 | |
| 419 | const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? |
| 420 | &Mips::GPR64RegClass : &Mips::GPR32RegClass; |
| 421 | |
| 422 | // First, compute final stack size. |
| 423 | uint64_t StackSize = MFI.getStackSize(); |
| 424 | |
| 425 | // No need to allocate space on the stack. |
| 426 | if (StackSize == 0 && !MFI.adjustsStack()) return; |
| 427 | |
| 428 | CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::NoFlags); |
| 429 | |
| 430 | // Adjust stack. |
| 431 | TII.adjustStackPtr(SP, Amount: -StackSize, MBB, I: MBBI); |
| 432 | CFIBuilder.buildDefCFAOffset(Offset: StackSize); |
| 433 | |
| 434 | if (MF.getFunction().hasFnAttribute(Kind: "interrupt" )) |
| 435 | emitInterruptPrologueStub(MF, MBB); |
| 436 | |
| 437 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
| 438 | |
| 439 | // Find the instruction past the last instruction that saves a callee-saved |
| 440 | // register to the stack. |
| 441 | std::advance(i&: MBBI, n: CSI.size()); |
| 442 | CFIBuilder.setInsertPoint(MBBI); |
| 443 | |
| 444 | if (!CSI.empty()) { |
| 445 | // Iterate over list of callee-saved registers and emit .cfi_offset |
| 446 | // directives. |
| 447 | for (const CalleeSavedInfo &I : CSI) { |
| 448 | int64_t Offset = MFI.getObjectOffset(ObjectIdx: I.getFrameIdx()); |
| 449 | MCRegister Reg = I.getReg(); |
| 450 | |
| 451 | // If Reg is a double precision register, emit two cfa_offsets, |
| 452 | // one for each of the paired single precision registers. |
| 453 | if (Mips::AFGR64RegClass.contains(Reg)) { |
| 454 | MCRegister Reg0 = RegInfo.getSubReg(Reg, Idx: Mips::sub_lo); |
| 455 | MCRegister Reg1 = RegInfo.getSubReg(Reg, Idx: Mips::sub_hi); |
| 456 | |
| 457 | if (!STI.isLittle()) |
| 458 | std::swap(a&: Reg0, b&: Reg1); |
| 459 | |
| 460 | CFIBuilder.buildOffset(Reg: Reg0, Offset); |
| 461 | CFIBuilder.buildOffset(Reg: Reg1, Offset: Offset + 4); |
| 462 | } else if (Mips::FGR64RegClass.contains(Reg)) { |
| 463 | MCRegister Reg0 = Reg; |
| 464 | MCRegister Reg1 = Reg + 1; |
| 465 | |
| 466 | if (!STI.isLittle()) |
| 467 | std::swap(a&: Reg0, b&: Reg1); |
| 468 | |
| 469 | CFIBuilder.buildOffset(Reg: Reg0, Offset); |
| 470 | CFIBuilder.buildOffset(Reg: Reg1, Offset: Offset + 4); |
| 471 | } else { |
| 472 | // Reg is either in GPR32 or FGR32. |
| 473 | CFIBuilder.buildOffset(Reg, Offset); |
| 474 | } |
| 475 | } |
| 476 | } |
| 477 | |
| 478 | if (MipsFI->callsEhReturn()) { |
| 479 | // Insert instructions that spill eh data registers. |
| 480 | for (int I = 0; I < 4; ++I) { |
| 481 | if (!MBB.isLiveIn(Reg: ABI.GetEhDataReg(I))) |
| 482 | MBB.addLiveIn(PhysReg: ABI.GetEhDataReg(I)); |
| 483 | TII.storeRegToStackSlot(MBB, MBBI, SrcReg: ABI.GetEhDataReg(I), isKill: false, |
| 484 | FrameIndex: MipsFI->getEhDataRegFI(Reg: I), RC, TRI: &RegInfo, |
| 485 | VReg: Register()); |
| 486 | } |
| 487 | |
| 488 | // Emit .cfi_offset directives for eh data registers. |
| 489 | for (int I = 0; I < 4; ++I) { |
| 490 | int64_t Offset = MFI.getObjectOffset(ObjectIdx: MipsFI->getEhDataRegFI(Reg: I)); |
| 491 | CFIBuilder.buildOffset(Reg: ABI.GetEhDataReg(I), Offset); |
| 492 | } |
| 493 | } |
| 494 | |
| 495 | // if framepointer enabled, set it to point to the stack pointer. |
| 496 | if (hasFP(MF)) { |
| 497 | // Insert instruction "move $fp, $sp" at this location. |
| 498 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: MOVE), DestReg: FP).addReg(RegNo: SP).addReg(RegNo: ZERO) |
| 499 | .setMIFlag(MachineInstr::FrameSetup); |
| 500 | |
| 501 | CFIBuilder.buildDefCFARegister(Reg: FP); |
| 502 | |
| 503 | if (RegInfo.hasStackRealignment(MF)) { |
| 504 | // addiu $Reg, $zero, -MaxAlignment |
| 505 | // andi $sp, $sp, $Reg |
| 506 | Register VR = MF.getRegInfo().createVirtualRegister(RegClass: RC); |
| 507 | assert((Log2(MFI.getMaxAlign()) < 16) && |
| 508 | "Function's alignment size requirement is not supported." ); |
| 509 | int64_t MaxAlign = -(int64_t)MFI.getMaxAlign().value(); |
| 510 | |
| 511 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: ADDiu), DestReg: VR).addReg(RegNo: ZERO).addImm(Val: MaxAlign); |
| 512 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: AND), DestReg: SP).addReg(RegNo: SP).addReg(RegNo: VR); |
| 513 | |
| 514 | if (hasBP(MF)) { |
| 515 | // move $s7, $sp |
| 516 | unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7; |
| 517 | BuildMI(BB&: MBB, I: MBBI, MIMD: dl, MCID: TII.get(Opcode: MOVE), DestReg: BP) |
| 518 | .addReg(RegNo: SP) |
| 519 | .addReg(RegNo: ZERO); |
| 520 | } |
| 521 | } |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | void MipsSEFrameLowering::emitInterruptPrologueStub( |
| 526 | MachineFunction &MF, MachineBasicBlock &MBB) const { |
| 527 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
| 528 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
| 529 | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
| 530 | |
| 531 | // Report an error the target doesn't support Mips32r2 or later. |
| 532 | // The epilogue relies on the use of the "ehb" to clear execution |
| 533 | // hazards. Pre R2 Mips relies on an implementation defined number |
| 534 | // of "ssnop"s to clear the execution hazard. Support for ssnop hazard |
| 535 | // clearing is not provided so reject that configuration. |
| 536 | if (!STI.hasMips32r2()) |
| 537 | report_fatal_error( |
| 538 | reason: "\"interrupt\" attribute is not supported on pre-MIPS32R2 or " |
| 539 | "MIPS16 targets." ); |
| 540 | |
| 541 | // The GP register contains the "user" value, so we cannot perform |
| 542 | // any gp relative loads until we restore the "kernel" or "system" gp |
| 543 | // value. Until support is written we shall only accept the static |
| 544 | // relocation model. |
| 545 | if ((STI.getRelocationModel() != Reloc::Static)) |
| 546 | report_fatal_error(reason: "\"interrupt\" attribute is only supported for the " |
| 547 | "static relocation model on MIPS at the present time." ); |
| 548 | |
| 549 | if (!STI.isABI_O32() || STI.hasMips64()) |
| 550 | report_fatal_error(reason: "\"interrupt\" attribute is only supported for the " |
| 551 | "O32 ABI on MIPS32R2+ at the present time." ); |
| 552 | |
| 553 | // Perform ISR handling like GCC |
| 554 | StringRef IntKind = |
| 555 | MF.getFunction().getFnAttribute(Kind: "interrupt" ).getValueAsString(); |
| 556 | const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; |
| 557 | |
| 558 | // EIC interrupt handling needs to read the Cause register to disable |
| 559 | // interrupts. |
| 560 | if (IntKind == "eic" ) { |
| 561 | // Coprocessor registers are always live per se. |
| 562 | MBB.addLiveIn(PhysReg: Mips::COP013); |
| 563 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K0) |
| 564 | .addReg(RegNo: Mips::COP013) |
| 565 | .addImm(Val: 0) |
| 566 | .setMIFlag(MachineInstr::FrameSetup); |
| 567 | |
| 568 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::EXT), DestReg: Mips::K0) |
| 569 | .addReg(RegNo: Mips::K0) |
| 570 | .addImm(Val: 10) |
| 571 | .addImm(Val: 6) |
| 572 | .setMIFlag(MachineInstr::FrameSetup); |
| 573 | } |
| 574 | |
| 575 | // Fetch and spill EPC |
| 576 | MBB.addLiveIn(PhysReg: Mips::COP014); |
| 577 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K1) |
| 578 | .addReg(RegNo: Mips::COP014) |
| 579 | .addImm(Val: 0) |
| 580 | .setMIFlag(MachineInstr::FrameSetup); |
| 581 | |
| 582 | STI.getInstrInfo()->storeRegToStack(MBB, MI: MBBI, SrcReg: Mips::K1, isKill: false, |
| 583 | FrameIndex: MipsFI->getISRRegFI(Reg: 0), RC: PtrRC, |
| 584 | TRI: STI.getRegisterInfo(), Offset: 0); |
| 585 | |
| 586 | // Fetch and Spill Status |
| 587 | MBB.addLiveIn(PhysReg: Mips::COP012); |
| 588 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MFC0), DestReg: Mips::K1) |
| 589 | .addReg(RegNo: Mips::COP012) |
| 590 | .addImm(Val: 0) |
| 591 | .setMIFlag(MachineInstr::FrameSetup); |
| 592 | |
| 593 | STI.getInstrInfo()->storeRegToStack(MBB, MI: MBBI, SrcReg: Mips::K1, isKill: false, |
| 594 | FrameIndex: MipsFI->getISRRegFI(Reg: 1), RC: PtrRC, |
| 595 | TRI: STI.getRegisterInfo(), Offset: 0); |
| 596 | |
| 597 | // Build the configuration for disabling lower priority interrupts. Non EIC |
| 598 | // interrupts need to be masked off with zero, EIC from the Cause register. |
| 599 | unsigned InsPosition = 8; |
| 600 | unsigned InsSize = 0; |
| 601 | unsigned SrcReg = Mips::ZERO; |
| 602 | |
| 603 | // If the interrupt we're tied to is the EIC, switch the source for the |
| 604 | // masking off interrupts to the cause register. |
| 605 | if (IntKind == "eic" ) { |
| 606 | SrcReg = Mips::K0; |
| 607 | InsPosition = 10; |
| 608 | InsSize = 6; |
| 609 | } else |
| 610 | InsSize = StringSwitch<unsigned>(IntKind) |
| 611 | .Case(S: "sw0" , Value: 1) |
| 612 | .Case(S: "sw1" , Value: 2) |
| 613 | .Case(S: "hw0" , Value: 3) |
| 614 | .Case(S: "hw1" , Value: 4) |
| 615 | .Case(S: "hw2" , Value: 5) |
| 616 | .Case(S: "hw3" , Value: 6) |
| 617 | .Case(S: "hw4" , Value: 7) |
| 618 | .Case(S: "hw5" , Value: 8) |
| 619 | .Default(Value: 0); |
| 620 | assert(InsSize != 0 && "Unknown interrupt type!" ); |
| 621 | |
| 622 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1) |
| 623 | .addReg(RegNo: SrcReg) |
| 624 | .addImm(Val: InsPosition) |
| 625 | .addImm(Val: InsSize) |
| 626 | .addReg(RegNo: Mips::K1) |
| 627 | .setMIFlag(MachineInstr::FrameSetup); |
| 628 | |
| 629 | // Mask off KSU, ERL, EXL |
| 630 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1) |
| 631 | .addReg(RegNo: Mips::ZERO) |
| 632 | .addImm(Val: 1) |
| 633 | .addImm(Val: 4) |
| 634 | .addReg(RegNo: Mips::K1) |
| 635 | .setMIFlag(MachineInstr::FrameSetup); |
| 636 | |
| 637 | // Disable the FPU as we are not spilling those register sets. |
| 638 | if (!STI.useSoftFloat()) |
| 639 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::INS), DestReg: Mips::K1) |
| 640 | .addReg(RegNo: Mips::ZERO) |
| 641 | .addImm(Val: 29) |
| 642 | .addImm(Val: 1) |
| 643 | .addReg(RegNo: Mips::K1) |
| 644 | .setMIFlag(MachineInstr::FrameSetup); |
| 645 | |
| 646 | // Set the new status |
| 647 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP012) |
| 648 | .addReg(RegNo: Mips::K1) |
| 649 | .addImm(Val: 0) |
| 650 | .setMIFlag(MachineInstr::FrameSetup); |
| 651 | } |
| 652 | |
| 653 | void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, |
| 654 | MachineBasicBlock &MBB) const { |
| 655 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); |
| 656 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 657 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
| 658 | |
| 659 | const MipsSEInstrInfo &TII = |
| 660 | *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); |
| 661 | const MipsRegisterInfo &RegInfo = |
| 662 | *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); |
| 663 | |
| 664 | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
| 665 | MipsABIInfo ABI = STI.getABI(); |
| 666 | unsigned SP = ABI.GetStackPtr(); |
| 667 | unsigned FP = ABI.GetFramePtr(); |
| 668 | unsigned ZERO = ABI.GetNullPtr(); |
| 669 | unsigned MOVE = ABI.GetGPRMoveOp(); |
| 670 | |
| 671 | // if framepointer enabled, restore the stack pointer. |
| 672 | if (hasFP(MF)) { |
| 673 | // Find the first instruction that restores a callee-saved register. |
| 674 | MachineBasicBlock::iterator I = MBBI; |
| 675 | |
| 676 | for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) |
| 677 | --I; |
| 678 | |
| 679 | // Insert instruction "move $sp, $fp" at this location. |
| 680 | BuildMI(BB&: MBB, I, MIMD: DL, MCID: TII.get(Opcode: MOVE), DestReg: SP).addReg(RegNo: FP).addReg(RegNo: ZERO); |
| 681 | } |
| 682 | |
| 683 | if (MipsFI->callsEhReturn()) { |
| 684 | const TargetRegisterClass *RC = |
| 685 | ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; |
| 686 | |
| 687 | // Find first instruction that restores a callee-saved register. |
| 688 | MachineBasicBlock::iterator I = MBBI; |
| 689 | for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) |
| 690 | --I; |
| 691 | |
| 692 | // Insert instructions that restore eh data registers. |
| 693 | for (int J = 0; J < 4; ++J) { |
| 694 | TII.loadRegFromStackSlot(MBB, MBBI: I, DestReg: ABI.GetEhDataReg(I: J), |
| 695 | FrameIndex: MipsFI->getEhDataRegFI(Reg: J), RC, TRI: &RegInfo, |
| 696 | VReg: Register()); |
| 697 | } |
| 698 | } |
| 699 | |
| 700 | if (MF.getFunction().hasFnAttribute(Kind: "interrupt" )) |
| 701 | emitInterruptEpilogueStub(MF, MBB); |
| 702 | |
| 703 | // Get the number of bytes from FrameInfo |
| 704 | uint64_t StackSize = MFI.getStackSize(); |
| 705 | |
| 706 | if (!StackSize) |
| 707 | return; |
| 708 | |
| 709 | // Adjust stack. |
| 710 | TII.adjustStackPtr(SP, Amount: StackSize, MBB, I: MBBI); |
| 711 | } |
| 712 | |
| 713 | void MipsSEFrameLowering::emitInterruptEpilogueStub( |
| 714 | MachineFunction &MF, MachineBasicBlock &MBB) const { |
| 715 | MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); |
| 716 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
| 717 | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); |
| 718 | |
| 719 | // Perform ISR handling like GCC |
| 720 | const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; |
| 721 | |
| 722 | // Disable Interrupts. |
| 723 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::DI), DestReg: Mips::ZERO); |
| 724 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::EHB)); |
| 725 | |
| 726 | // Restore EPC |
| 727 | STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, DestReg: Mips::K1, |
| 728 | FrameIndex: MipsFI->getISRRegFI(Reg: 0), RC: PtrRC, |
| 729 | TRI: STI.getRegisterInfo(), VReg: Register()); |
| 730 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP014) |
| 731 | .addReg(RegNo: Mips::K1) |
| 732 | .addImm(Val: 0); |
| 733 | |
| 734 | // Restore Status |
| 735 | STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, DestReg: Mips::K1, |
| 736 | FrameIndex: MipsFI->getISRRegFI(Reg: 1), RC: PtrRC, |
| 737 | TRI: STI.getRegisterInfo(), VReg: Register()); |
| 738 | BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: STI.getInstrInfo()->get(Opcode: Mips::MTC0), DestReg: Mips::COP012) |
| 739 | .addReg(RegNo: Mips::K1) |
| 740 | .addImm(Val: 0); |
| 741 | } |
| 742 | |
| 743 | StackOffset |
| 744 | MipsSEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, |
| 745 | Register &FrameReg) const { |
| 746 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 747 | MipsABIInfo ABI = STI.getABI(); |
| 748 | |
| 749 | if (MFI.isFixedObjectIndex(ObjectIdx: FI)) |
| 750 | FrameReg = hasFP(MF) ? ABI.GetFramePtr() : ABI.GetStackPtr(); |
| 751 | else |
| 752 | FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr(); |
| 753 | |
| 754 | return StackOffset::getFixed(Fixed: MFI.getObjectOffset(ObjectIdx: FI) + MFI.getStackSize() - |
| 755 | getOffsetOfLocalArea() + |
| 756 | MFI.getOffsetAdjustment()); |
| 757 | } |
| 758 | |
| 759 | bool MipsSEFrameLowering::spillCalleeSavedRegisters( |
| 760 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
| 761 | ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
| 762 | MachineFunction *MF = MBB.getParent(); |
| 763 | const TargetInstrInfo &TII = *STI.getInstrInfo(); |
| 764 | |
| 765 | for (const CalleeSavedInfo &I : CSI) { |
| 766 | // Add the callee-saved register as live-in. Do not add if the register is |
| 767 | // RA and return address is taken, because it has already been added in |
| 768 | // method MipsTargetLowering::lowerRETURNADDR. |
| 769 | // It's killed at the spill, unless the register is RA and return address |
| 770 | // is taken. |
| 771 | MCRegister Reg = I.getReg(); |
| 772 | bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64) |
| 773 | && MF->getFrameInfo().isReturnAddressTaken(); |
| 774 | if (!IsRAAndRetAddrIsTaken) |
| 775 | MBB.addLiveIn(PhysReg: Reg); |
| 776 | |
| 777 | // ISRs require HI/LO to be spilled into kernel registers to be then |
| 778 | // spilled to the stack frame. |
| 779 | bool IsLOHI = (Reg == Mips::LO0 || Reg == Mips::LO0_64 || |
| 780 | Reg == Mips::HI0 || Reg == Mips::HI0_64); |
| 781 | const Function &Func = MBB.getParent()->getFunction(); |
| 782 | if (IsLOHI && Func.hasFnAttribute(Kind: "interrupt" )) { |
| 783 | DebugLoc DL = MI->getDebugLoc(); |
| 784 | |
| 785 | unsigned Op = 0; |
| 786 | if (!STI.getABI().ArePtrs64bit()) { |
| 787 | Op = (Reg == Mips::HI0) ? Mips::MFHI : Mips::MFLO; |
| 788 | Reg = Mips::K0; |
| 789 | } else { |
| 790 | Op = (Reg == Mips::HI0) ? Mips::MFHI64 : Mips::MFLO64; |
| 791 | Reg = Mips::K0_64; |
| 792 | } |
| 793 | BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: TII.get(Opcode: Op), DestReg: Mips::K0) |
| 794 | .setMIFlag(MachineInstr::FrameSetup); |
| 795 | } |
| 796 | |
| 797 | // Insert the spill to the stack frame. |
| 798 | bool IsKill = !IsRAAndRetAddrIsTaken; |
| 799 | const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); |
| 800 | TII.storeRegToStackSlot(MBB, MI, SrcReg: Reg, isKill: IsKill, FrameIndex: I.getFrameIdx(), RC, TRI, |
| 801 | VReg: Register()); |
| 802 | } |
| 803 | |
| 804 | return true; |
| 805 | } |
| 806 | |
| 807 | bool |
| 808 | MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { |
| 809 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 810 | // Reserve call frame if the size of the maximum call frame fits into 16-bit |
| 811 | // immediate field and there are no variable sized objects on the stack. |
| 812 | // Make sure the second register scavenger spill slot can be accessed with one |
| 813 | // instruction. |
| 814 | return isInt<16>(x: MFI.getMaxCallFrameSize() + getStackAlignment()) && |
| 815 | !MFI.hasVarSizedObjects(); |
| 816 | } |
| 817 | |
| 818 | /// Mark \p Reg and all registers aliasing it in the bitset. |
| 819 | static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs, |
| 820 | unsigned Reg) { |
| 821 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
| 822 | for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) |
| 823 | SavedRegs.set(*AI); |
| 824 | } |
| 825 | |
| 826 | void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF, |
| 827 | BitVector &SavedRegs, |
| 828 | RegScavenger *RS) const { |
| 829 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
| 830 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
| 831 | MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); |
| 832 | MipsABIInfo ABI = STI.getABI(); |
| 833 | unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA; |
| 834 | unsigned FP = ABI.GetFramePtr(); |
| 835 | unsigned BP = ABI.IsN64() ? Mips::S7_64 : Mips::S7; |
| 836 | |
| 837 | // Mark $ra and $fp as used if function has dedicated frame pointer. |
| 838 | if (hasFP(MF)) { |
| 839 | setAliasRegs(MF, SavedRegs, Reg: RA); |
| 840 | setAliasRegs(MF, SavedRegs, Reg: FP); |
| 841 | } |
| 842 | // Mark $s7 as used if function has dedicated base pointer. |
| 843 | if (hasBP(MF)) |
| 844 | setAliasRegs(MF, SavedRegs, Reg: BP); |
| 845 | |
| 846 | // Create spill slots for eh data registers if function calls eh_return. |
| 847 | if (MipsFI->callsEhReturn()) |
| 848 | MipsFI->createEhDataRegsFI(MF); |
| 849 | |
| 850 | // Create spill slots for Coprocessor 0 registers if function is an ISR. |
| 851 | if (MipsFI->isISR()) |
| 852 | MipsFI->createISRRegFI(MF); |
| 853 | |
| 854 | // Expand pseudo instructions which load, store or copy accumulators. |
| 855 | // Add an emergency spill slot if a pseudo was expanded. |
| 856 | if (ExpandPseudo(MF).expand()) { |
| 857 | // The spill slot should be half the size of the accumulator. If target have |
| 858 | // general-purpose registers 64 bits wide, it should be 64-bit, otherwise |
| 859 | // it should be 32-bit. |
| 860 | const TargetRegisterClass &RC = STI.isGP64bit() ? |
| 861 | Mips::GPR64RegClass : Mips::GPR32RegClass; |
| 862 | int FI = MF.getFrameInfo().CreateSpillStackObject(Size: TRI->getSpillSize(RC), |
| 863 | Alignment: TRI->getSpillAlign(RC)); |
| 864 | RS->addScavengingFrameIndex(FI); |
| 865 | } |
| 866 | |
| 867 | // Set scavenging frame index if necessary. |
| 868 | uint64_t MaxSPOffset = estimateStackSize(MF); |
| 869 | |
| 870 | // MSA has a minimum offset of 10 bits signed. If there is a variable |
| 871 | // sized object on the stack, the estimation cannot account for it. |
| 872 | if (isIntN(N: STI.hasMSA() ? 10 : 16, x: MaxSPOffset) && |
| 873 | !MF.getFrameInfo().hasVarSizedObjects()) |
| 874 | return; |
| 875 | |
| 876 | const TargetRegisterClass &RC = |
| 877 | ABI.ArePtrs64bit() ? Mips::GPR64RegClass : Mips::GPR32RegClass; |
| 878 | int FI = MF.getFrameInfo().CreateSpillStackObject(Size: TRI->getSpillSize(RC), |
| 879 | Alignment: TRI->getSpillAlign(RC)); |
| 880 | RS->addScavengingFrameIndex(FI); |
| 881 | } |
| 882 | |
| 883 | const MipsFrameLowering * |
| 884 | llvm::createMipsSEFrameLowering(const MipsSubtarget &ST) { |
| 885 | return new MipsSEFrameLowering(ST); |
| 886 | } |
| 887 | |