| 1 | //===- MipsInstrInfo.cpp - Mips Instruction 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 Mips implementation of the TargetInstrInfo class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "MipsInstrInfo.h" |
| 14 | #include "MCTargetDesc/MipsBaseInfo.h" |
| 15 | #include "MCTargetDesc/MipsMCTargetDesc.h" |
| 16 | #include "Mips.h" |
| 17 | #include "MipsSubtarget.h" |
| 18 | #include "llvm/ADT/SmallVector.h" |
| 19 | #include "llvm/CodeGen/MachineBasicBlock.h" |
| 20 | #include "llvm/CodeGen/MachineFrameInfo.h" |
| 21 | #include "llvm/CodeGen/MachineFunction.h" |
| 22 | #include "llvm/CodeGen/MachineInstr.h" |
| 23 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
| 24 | #include "llvm/CodeGen/MachineOperand.h" |
| 25 | #include "llvm/CodeGen/TargetOpcodes.h" |
| 26 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
| 27 | #include "llvm/IR/DebugInfoMetadata.h" |
| 28 | #include "llvm/IR/DebugLoc.h" |
| 29 | #include "llvm/MC/MCInstBuilder.h" |
| 30 | #include "llvm/MC/MCInstrDesc.h" |
| 31 | #include "llvm/Target/TargetMachine.h" |
| 32 | #include <cassert> |
| 33 | |
| 34 | using namespace llvm; |
| 35 | |
| 36 | #define GET_INSTRINFO_CTOR_DTOR |
| 37 | #include "MipsGenInstrInfo.inc" |
| 38 | |
| 39 | // Pin the vtable to this file. |
| 40 | void MipsInstrInfo::anchor() {} |
| 41 | |
| 42 | MipsInstrInfo::MipsInstrInfo(const MipsSubtarget &STI, unsigned UncondBr) |
| 43 | : MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), |
| 44 | Subtarget(STI), UncondBrOpc(UncondBr) {} |
| 45 | |
| 46 | const MipsInstrInfo *MipsInstrInfo::create(MipsSubtarget &STI) { |
| 47 | if (STI.inMips16Mode()) |
| 48 | return createMips16InstrInfo(STI); |
| 49 | |
| 50 | return createMipsSEInstrInfo(STI); |
| 51 | } |
| 52 | |
| 53 | bool MipsInstrInfo::isZeroImm(const MachineOperand &op) const { |
| 54 | return op.isImm() && op.getImm() == 0; |
| 55 | } |
| 56 | |
| 57 | MCInst MipsInstrInfo::getNop() const { |
| 58 | return MCInstBuilder(Mips::SLL) |
| 59 | .addReg(Reg: Mips::ZERO) |
| 60 | .addReg(Reg: Mips::ZERO) |
| 61 | .addImm(Val: 0); |
| 62 | } |
| 63 | |
| 64 | /// insertNoop - If data hazard condition is found insert the target nop |
| 65 | /// instruction. |
| 66 | void MipsInstrInfo:: |
| 67 | insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const |
| 68 | { |
| 69 | DebugLoc DL; |
| 70 | BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: get(Opcode: Mips::NOP)); |
| 71 | } |
| 72 | |
| 73 | MachineInstrBuilder MipsInstrInfo::insertNop(MachineBasicBlock &MBB, |
| 74 | MachineBasicBlock::iterator MI, |
| 75 | DebugLoc DL) const { |
| 76 | assert(!Subtarget.inMips16Mode() && |
| 77 | "insertNop does not support MIPS16e mode at this time" ); |
| 78 | const unsigned MMOpc = |
| 79 | Subtarget.hasMips32r6() ? Mips::SLL_MMR6 : Mips::SLL_MM; |
| 80 | const unsigned Opc = |
| 81 | Subtarget.inMicroMipsMode() ? MMOpc : (unsigned)Mips::SLL; |
| 82 | return BuildMI(BB&: MBB, I: MI, MIMD: DL, MCID: get(Opcode: Opc), DestReg: Mips::ZERO) |
| 83 | .addReg(RegNo: Mips::ZERO) |
| 84 | .addImm(Val: 0); |
| 85 | } |
| 86 | |
| 87 | MachineMemOperand * |
| 88 | MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, |
| 89 | MachineMemOperand::Flags Flags) const { |
| 90 | MachineFunction &MF = *MBB.getParent(); |
| 91 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 92 | |
| 93 | return MF.getMachineMemOperand(PtrInfo: MachinePointerInfo::getFixedStack(MF, FI), |
| 94 | F: Flags, Size: MFI.getObjectSize(ObjectIdx: FI), |
| 95 | BaseAlignment: MFI.getObjectAlign(ObjectIdx: FI)); |
| 96 | } |
| 97 | |
| 98 | //===----------------------------------------------------------------------===// |
| 99 | // Branch Analysis |
| 100 | //===----------------------------------------------------------------------===// |
| 101 | |
| 102 | void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, |
| 103 | MachineBasicBlock *&BB, |
| 104 | SmallVectorImpl<MachineOperand> &Cond) const { |
| 105 | assert(getAnalyzableBrOpc(Opc) && "Not an analyzable branch" ); |
| 106 | int NumOp = Inst->getNumExplicitOperands(); |
| 107 | |
| 108 | // for both int and fp branches, the last explicit operand is the |
| 109 | // MBB. |
| 110 | BB = Inst->getOperand(i: NumOp-1).getMBB(); |
| 111 | Cond.push_back(Elt: MachineOperand::CreateImm(Val: Opc)); |
| 112 | |
| 113 | for (int i = 0; i < NumOp-1; i++) |
| 114 | Cond.push_back(Elt: Inst->getOperand(i)); |
| 115 | } |
| 116 | |
| 117 | bool MipsInstrInfo::analyzeBranch(MachineBasicBlock &MBB, |
| 118 | MachineBasicBlock *&TBB, |
| 119 | MachineBasicBlock *&FBB, |
| 120 | SmallVectorImpl<MachineOperand> &Cond, |
| 121 | bool AllowModify) const { |
| 122 | SmallVector<MachineInstr*, 2> BranchInstrs; |
| 123 | BranchType BT = analyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); |
| 124 | |
| 125 | return (BT == BT_None) || (BT == BT_Indirect); |
| 126 | } |
| 127 | |
| 128 | void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, |
| 129 | const DebugLoc &DL, |
| 130 | ArrayRef<MachineOperand> Cond) const { |
| 131 | unsigned Opc = Cond[0].getImm(); |
| 132 | const MCInstrDesc &MCID = get(Opcode: Opc); |
| 133 | MachineInstrBuilder MIB = BuildMI(BB: &MBB, MIMD: DL, MCID); |
| 134 | |
| 135 | for (unsigned i = 1; i < Cond.size(); ++i) { |
| 136 | assert((Cond[i].isImm() || Cond[i].isReg()) && |
| 137 | "Cannot copy operand for conditional branch!" ); |
| 138 | MIB.add(MO: Cond[i]); |
| 139 | } |
| 140 | MIB.addMBB(MBB: TBB); |
| 141 | } |
| 142 | |
| 143 | unsigned MipsInstrInfo::insertBranch(MachineBasicBlock &MBB, |
| 144 | MachineBasicBlock *TBB, |
| 145 | MachineBasicBlock *FBB, |
| 146 | ArrayRef<MachineOperand> Cond, |
| 147 | const DebugLoc &DL, |
| 148 | int *BytesAdded) const { |
| 149 | // Shouldn't be a fall through. |
| 150 | assert(TBB && "insertBranch must not be told to insert a fallthrough" ); |
| 151 | assert(!BytesAdded && "code size not handled" ); |
| 152 | |
| 153 | // # of condition operands: |
| 154 | // Unconditional branches: 0 |
| 155 | // Floating point branches: 1 (opc) |
| 156 | // Int BranchZero: 2 (opc, reg) |
| 157 | // Int Branch: 3 (opc, reg0, reg1) |
| 158 | assert((Cond.size() <= 3) && |
| 159 | "# of Mips branch conditions must be <= 3!" ); |
| 160 | |
| 161 | // Two-way Conditional branch. |
| 162 | if (FBB) { |
| 163 | BuildCondBr(MBB, TBB, DL, Cond); |
| 164 | BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: UncondBrOpc)).addMBB(MBB: FBB); |
| 165 | return 2; |
| 166 | } |
| 167 | |
| 168 | // One way branch. |
| 169 | // Unconditional branch. |
| 170 | if (Cond.empty()) |
| 171 | BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: UncondBrOpc)).addMBB(MBB: TBB); |
| 172 | else // Conditional branch. |
| 173 | BuildCondBr(MBB, TBB, DL, Cond); |
| 174 | return 1; |
| 175 | } |
| 176 | |
| 177 | unsigned MipsInstrInfo::removeBranch(MachineBasicBlock &MBB, |
| 178 | int *BytesRemoved) const { |
| 179 | assert(!BytesRemoved && "code size not handled" ); |
| 180 | |
| 181 | MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); |
| 182 | unsigned removed = 0; |
| 183 | |
| 184 | // Up to 2 branches are removed. |
| 185 | // Note that indirect branches are not removed. |
| 186 | while (I != REnd && removed < 2) { |
| 187 | // Skip past debug instructions. |
| 188 | if (I->isDebugInstr()) { |
| 189 | ++I; |
| 190 | continue; |
| 191 | } |
| 192 | if (!getAnalyzableBrOpc(Opc: I->getOpcode())) |
| 193 | break; |
| 194 | // Remove the branch. |
| 195 | I->eraseFromParent(); |
| 196 | I = MBB.rbegin(); |
| 197 | ++removed; |
| 198 | } |
| 199 | |
| 200 | return removed; |
| 201 | } |
| 202 | |
| 203 | /// reverseBranchCondition - Return the inverse opcode of the |
| 204 | /// specified Branch instruction. |
| 205 | bool MipsInstrInfo::reverseBranchCondition( |
| 206 | SmallVectorImpl<MachineOperand> &Cond) const { |
| 207 | assert( (Cond.size() && Cond.size() <= 3) && |
| 208 | "Invalid Mips branch condition!" ); |
| 209 | Cond[0].setImm(getOppositeBranchOpc(Opc: Cond[0].getImm())); |
| 210 | return false; |
| 211 | } |
| 212 | |
| 213 | MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( |
| 214 | MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, |
| 215 | SmallVectorImpl<MachineOperand> &Cond, bool AllowModify, |
| 216 | SmallVectorImpl<MachineInstr *> &BranchInstrs) const { |
| 217 | MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); |
| 218 | |
| 219 | // Skip all the debug instructions. |
| 220 | while (I != REnd && I->isDebugInstr()) |
| 221 | ++I; |
| 222 | |
| 223 | if (I == REnd || !isUnpredicatedTerminator(MI: *I)) { |
| 224 | // This block ends with no branches (it just falls through to its succ). |
| 225 | // Leave TBB/FBB null. |
| 226 | TBB = FBB = nullptr; |
| 227 | return BT_NoBranch; |
| 228 | } |
| 229 | |
| 230 | MachineInstr *LastInst = &*I; |
| 231 | unsigned LastOpc = LastInst->getOpcode(); |
| 232 | BranchInstrs.push_back(Elt: LastInst); |
| 233 | |
| 234 | // Not an analyzable branch (e.g., indirect jump). |
| 235 | if (!getAnalyzableBrOpc(Opc: LastOpc)) |
| 236 | return LastInst->isIndirectBranch() ? BT_Indirect : BT_None; |
| 237 | |
| 238 | // Get the second to last instruction in the block. |
| 239 | unsigned SecondLastOpc = 0; |
| 240 | MachineInstr *SecondLastInst = nullptr; |
| 241 | |
| 242 | // Skip past any debug instruction to see if the second last actual |
| 243 | // is a branch. |
| 244 | ++I; |
| 245 | while (I != REnd && I->isDebugInstr()) |
| 246 | ++I; |
| 247 | |
| 248 | if (I != REnd) { |
| 249 | SecondLastInst = &*I; |
| 250 | SecondLastOpc = getAnalyzableBrOpc(Opc: SecondLastInst->getOpcode()); |
| 251 | |
| 252 | // Not an analyzable branch (must be an indirect jump). |
| 253 | if (isUnpredicatedTerminator(MI: *SecondLastInst) && !SecondLastOpc) |
| 254 | return BT_None; |
| 255 | } |
| 256 | |
| 257 | // If there is only one terminator instruction, process it. |
| 258 | if (!SecondLastOpc) { |
| 259 | // Unconditional branch. |
| 260 | if (LastInst->isUnconditionalBranch()) { |
| 261 | TBB = LastInst->getOperand(i: 0).getMBB(); |
| 262 | return BT_Uncond; |
| 263 | } |
| 264 | |
| 265 | // Conditional branch |
| 266 | AnalyzeCondBr(Inst: LastInst, Opc: LastOpc, BB&: TBB, Cond); |
| 267 | return BT_Cond; |
| 268 | } |
| 269 | |
| 270 | // If we reached here, there are two branches. |
| 271 | // If there are three terminators, we don't know what sort of block this is. |
| 272 | if (++I != REnd && isUnpredicatedTerminator(MI: *I)) |
| 273 | return BT_None; |
| 274 | |
| 275 | BranchInstrs.insert(I: BranchInstrs.begin(), Elt: SecondLastInst); |
| 276 | |
| 277 | // If second to last instruction is an unconditional branch, |
| 278 | // analyze it and remove the last instruction. |
| 279 | if (SecondLastInst->isUnconditionalBranch()) { |
| 280 | // Return if the last instruction cannot be removed. |
| 281 | if (!AllowModify) |
| 282 | return BT_None; |
| 283 | |
| 284 | TBB = SecondLastInst->getOperand(i: 0).getMBB(); |
| 285 | LastInst->eraseFromParent(); |
| 286 | BranchInstrs.pop_back(); |
| 287 | return BT_Uncond; |
| 288 | } |
| 289 | |
| 290 | // Conditional branch followed by an unconditional branch. |
| 291 | // The last one must be unconditional. |
| 292 | if (!LastInst->isUnconditionalBranch()) |
| 293 | return BT_None; |
| 294 | |
| 295 | AnalyzeCondBr(Inst: SecondLastInst, Opc: SecondLastOpc, BB&: TBB, Cond); |
| 296 | FBB = LastInst->getOperand(i: 0).getMBB(); |
| 297 | |
| 298 | return BT_CondUncond; |
| 299 | } |
| 300 | |
| 301 | bool MipsInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, |
| 302 | int64_t BrOffset) const { |
| 303 | switch (BranchOpc) { |
| 304 | case Mips::B: |
| 305 | case Mips::BAL: |
| 306 | case Mips::BAL_BR: |
| 307 | case Mips::BAL_BR_MM: |
| 308 | case Mips::BC1F: |
| 309 | case Mips::BC1FL: |
| 310 | case Mips::BC1T: |
| 311 | case Mips::BC1TL: |
| 312 | case Mips::BEQ: case Mips::BEQ64: |
| 313 | case Mips::BEQL: |
| 314 | case Mips::BGEZ: case Mips::BGEZ64: |
| 315 | case Mips::BGEZL: |
| 316 | case Mips::BGEZAL: |
| 317 | case Mips::BGEZALL: |
| 318 | case Mips::BGTZ: case Mips::BGTZ64: |
| 319 | case Mips::BGTZL: |
| 320 | case Mips::BLEZ: case Mips::BLEZ64: |
| 321 | case Mips::BLEZL: |
| 322 | case Mips::BLTZ: case Mips::BLTZ64: |
| 323 | case Mips::BLTZL: |
| 324 | case Mips::BLTZAL: |
| 325 | case Mips::BLTZALL: |
| 326 | case Mips::BNE: case Mips::BNE64: |
| 327 | case Mips::BNEL: |
| 328 | return isInt<18>(x: BrOffset); |
| 329 | |
| 330 | // microMIPSr3 branches |
| 331 | case Mips::B_MM: |
| 332 | case Mips::BC1F_MM: |
| 333 | case Mips::BC1T_MM: |
| 334 | case Mips::BEQ_MM: |
| 335 | case Mips::BGEZ_MM: |
| 336 | case Mips::BGEZAL_MM: |
| 337 | case Mips::BGTZ_MM: |
| 338 | case Mips::BLEZ_MM: |
| 339 | case Mips::BLTZ_MM: |
| 340 | case Mips::BLTZAL_MM: |
| 341 | case Mips::BNE_MM: |
| 342 | case Mips::BEQZC_MM: |
| 343 | case Mips::BNEZC_MM: |
| 344 | return isInt<17>(x: BrOffset); |
| 345 | |
| 346 | // microMIPSR3 short branches. |
| 347 | case Mips::B16_MM: |
| 348 | return isInt<11>(x: BrOffset); |
| 349 | |
| 350 | case Mips::BEQZ16_MM: |
| 351 | case Mips::BNEZ16_MM: |
| 352 | return isInt<8>(x: BrOffset); |
| 353 | |
| 354 | // MIPSR6 branches. |
| 355 | case Mips::BALC: |
| 356 | case Mips::BC: |
| 357 | return isInt<28>(x: BrOffset); |
| 358 | |
| 359 | case Mips::BC1EQZ: |
| 360 | case Mips::BC1NEZ: |
| 361 | case Mips::BC2EQZ: |
| 362 | case Mips::BC2NEZ: |
| 363 | case Mips::BEQC: case Mips::BEQC64: |
| 364 | case Mips::BNEC: case Mips::BNEC64: |
| 365 | case Mips::BGEC: case Mips::BGEC64: |
| 366 | case Mips::BGEUC: case Mips::BGEUC64: |
| 367 | case Mips::BGEZC: case Mips::BGEZC64: |
| 368 | case Mips::BGTZC: case Mips::BGTZC64: |
| 369 | case Mips::BLEZC: case Mips::BLEZC64: |
| 370 | case Mips::BLTC: case Mips::BLTC64: |
| 371 | case Mips::BLTUC: case Mips::BLTUC64: |
| 372 | case Mips::BLTZC: case Mips::BLTZC64: |
| 373 | case Mips::BNVC: |
| 374 | case Mips::BOVC: |
| 375 | case Mips::BGEZALC: |
| 376 | case Mips::BEQZALC: |
| 377 | case Mips::BGTZALC: |
| 378 | case Mips::BLEZALC: |
| 379 | case Mips::BLTZALC: |
| 380 | case Mips::BNEZALC: |
| 381 | return isInt<18>(x: BrOffset); |
| 382 | |
| 383 | case Mips::BEQZC: case Mips::BEQZC64: |
| 384 | case Mips::BNEZC: case Mips::BNEZC64: |
| 385 | return isInt<23>(x: BrOffset); |
| 386 | |
| 387 | // microMIPSR6 branches |
| 388 | case Mips::BC16_MMR6: |
| 389 | return isInt<11>(x: BrOffset); |
| 390 | |
| 391 | case Mips::BEQZC16_MMR6: |
| 392 | case Mips::BNEZC16_MMR6: |
| 393 | return isInt<8>(x: BrOffset); |
| 394 | |
| 395 | case Mips::BALC_MMR6: |
| 396 | case Mips::BC_MMR6: |
| 397 | return isInt<27>(x: BrOffset); |
| 398 | |
| 399 | case Mips::BC1EQZC_MMR6: |
| 400 | case Mips::BC1NEZC_MMR6: |
| 401 | case Mips::BC2EQZC_MMR6: |
| 402 | case Mips::BC2NEZC_MMR6: |
| 403 | case Mips::BGEZALC_MMR6: |
| 404 | case Mips::BEQZALC_MMR6: |
| 405 | case Mips::BGTZALC_MMR6: |
| 406 | case Mips::BLEZALC_MMR6: |
| 407 | case Mips::BLTZALC_MMR6: |
| 408 | case Mips::BNEZALC_MMR6: |
| 409 | case Mips::BNVC_MMR6: |
| 410 | case Mips::BOVC_MMR6: |
| 411 | return isInt<17>(x: BrOffset); |
| 412 | |
| 413 | case Mips::BEQC_MMR6: |
| 414 | case Mips::BNEC_MMR6: |
| 415 | case Mips::BGEC_MMR6: |
| 416 | case Mips::BGEUC_MMR6: |
| 417 | case Mips::BGEZC_MMR6: |
| 418 | case Mips::BGTZC_MMR6: |
| 419 | case Mips::BLEZC_MMR6: |
| 420 | case Mips::BLTC_MMR6: |
| 421 | case Mips::BLTUC_MMR6: |
| 422 | case Mips::BLTZC_MMR6: |
| 423 | return isInt<18>(x: BrOffset); |
| 424 | |
| 425 | case Mips::BEQZC_MMR6: |
| 426 | case Mips::BNEZC_MMR6: |
| 427 | return isInt<23>(x: BrOffset); |
| 428 | |
| 429 | // DSP branches. |
| 430 | case Mips::BPOSGE32: |
| 431 | return isInt<18>(x: BrOffset); |
| 432 | case Mips::BPOSGE32_MM: |
| 433 | case Mips::BPOSGE32C_MMR3: |
| 434 | return isInt<17>(x: BrOffset); |
| 435 | |
| 436 | // cnMIPS branches. |
| 437 | case Mips::BBIT0: |
| 438 | case Mips::BBIT032: |
| 439 | case Mips::BBIT1: |
| 440 | case Mips::BBIT132: |
| 441 | return isInt<18>(x: BrOffset); |
| 442 | |
| 443 | // MSA branches. |
| 444 | case Mips::BZ_B: |
| 445 | case Mips::BZ_H: |
| 446 | case Mips::BZ_W: |
| 447 | case Mips::BZ_D: |
| 448 | case Mips::BZ_V: |
| 449 | case Mips::BNZ_B: |
| 450 | case Mips::BNZ_H: |
| 451 | case Mips::BNZ_W: |
| 452 | case Mips::BNZ_D: |
| 453 | case Mips::BNZ_V: |
| 454 | return isInt<18>(x: BrOffset); |
| 455 | } |
| 456 | |
| 457 | llvm_unreachable("Unknown branch instruction!" ); |
| 458 | } |
| 459 | |
| 460 | /// Return the corresponding compact (no delay slot) form of a branch. |
| 461 | unsigned MipsInstrInfo::getEquivalentCompactForm( |
| 462 | const MachineBasicBlock::iterator I) const { |
| 463 | unsigned Opcode = I->getOpcode(); |
| 464 | bool canUseShortMicroMipsCTI = false; |
| 465 | |
| 466 | if (Subtarget.inMicroMipsMode()) { |
| 467 | switch (Opcode) { |
| 468 | case Mips::BNE: |
| 469 | case Mips::BNE_MM: |
| 470 | case Mips::BEQ: |
| 471 | case Mips::BEQ_MM: |
| 472 | // microMIPS has NE,EQ branches that do not have delay slots provided one |
| 473 | // of the operands is zero. |
| 474 | if (I->getOperand(i: 1).getReg() == Subtarget.getABI().GetZeroReg()) |
| 475 | canUseShortMicroMipsCTI = true; |
| 476 | break; |
| 477 | // For microMIPS the PseudoReturn and PseudoIndirectBranch are always |
| 478 | // expanded to JR_MM, so they can be replaced with JRC16_MM. |
| 479 | case Mips::JR: |
| 480 | case Mips::PseudoReturn: |
| 481 | case Mips::PseudoIndirectBranch: |
| 482 | canUseShortMicroMipsCTI = true; |
| 483 | break; |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | // MIPSR6 forbids both operands being the zero register. |
| 488 | if (Subtarget.hasMips32r6() && (I->getNumOperands() > 1) && |
| 489 | (I->getOperand(i: 0).isReg() && |
| 490 | (I->getOperand(i: 0).getReg() == Mips::ZERO || |
| 491 | I->getOperand(i: 0).getReg() == Mips::ZERO_64)) && |
| 492 | (I->getOperand(i: 1).isReg() && |
| 493 | (I->getOperand(i: 1).getReg() == Mips::ZERO || |
| 494 | I->getOperand(i: 1).getReg() == Mips::ZERO_64))) |
| 495 | return 0; |
| 496 | |
| 497 | if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) { |
| 498 | switch (Opcode) { |
| 499 | case Mips::B: |
| 500 | return Mips::BC; |
| 501 | case Mips::BAL: |
| 502 | return Mips::BALC; |
| 503 | case Mips::BEQ: |
| 504 | case Mips::BEQ_MM: |
| 505 | if (canUseShortMicroMipsCTI) |
| 506 | return Mips::BEQZC_MM; |
| 507 | else if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 508 | return 0; |
| 509 | return Mips::BEQC; |
| 510 | case Mips::BNE: |
| 511 | case Mips::BNE_MM: |
| 512 | if (canUseShortMicroMipsCTI) |
| 513 | return Mips::BNEZC_MM; |
| 514 | else if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 515 | return 0; |
| 516 | return Mips::BNEC; |
| 517 | case Mips::BGE: |
| 518 | if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 519 | return 0; |
| 520 | return Mips::BGEC; |
| 521 | case Mips::BGEU: |
| 522 | if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 523 | return 0; |
| 524 | return Mips::BGEUC; |
| 525 | case Mips::BGEZ: |
| 526 | return Mips::BGEZC; |
| 527 | case Mips::BGTZ: |
| 528 | return Mips::BGTZC; |
| 529 | case Mips::BLEZ: |
| 530 | return Mips::BLEZC; |
| 531 | case Mips::BLT: |
| 532 | if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 533 | return 0; |
| 534 | return Mips::BLTC; |
| 535 | case Mips::BLTU: |
| 536 | if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 537 | return 0; |
| 538 | return Mips::BLTUC; |
| 539 | case Mips::BLTZ: |
| 540 | return Mips::BLTZC; |
| 541 | case Mips::BEQ64: |
| 542 | if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 543 | return 0; |
| 544 | return Mips::BEQC64; |
| 545 | case Mips::BNE64: |
| 546 | if (I->getOperand(i: 0).getReg() == I->getOperand(i: 1).getReg()) |
| 547 | return 0; |
| 548 | return Mips::BNEC64; |
| 549 | case Mips::BGTZ64: |
| 550 | return Mips::BGTZC64; |
| 551 | case Mips::BGEZ64: |
| 552 | return Mips::BGEZC64; |
| 553 | case Mips::BLTZ64: |
| 554 | return Mips::BLTZC64; |
| 555 | case Mips::BLEZ64: |
| 556 | return Mips::BLEZC64; |
| 557 | // For MIPSR6, the instruction 'jic' can be used for these cases. Some |
| 558 | // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'. |
| 559 | case Mips::JR: |
| 560 | case Mips::PseudoIndirectBranchR6: |
| 561 | case Mips::PseudoReturn: |
| 562 | case Mips::TAILCALLR6REG: |
| 563 | if (canUseShortMicroMipsCTI) |
| 564 | return Mips::JRC16_MM; |
| 565 | return Mips::JIC; |
| 566 | case Mips::JALRPseudo: |
| 567 | return Mips::JIALC; |
| 568 | case Mips::JR64: |
| 569 | case Mips::PseudoIndirectBranch64R6: |
| 570 | case Mips::PseudoReturn64: |
| 571 | case Mips::TAILCALL64R6REG: |
| 572 | return Mips::JIC64; |
| 573 | case Mips::JALR64Pseudo: |
| 574 | return Mips::JIALC64; |
| 575 | default: |
| 576 | return 0; |
| 577 | } |
| 578 | } |
| 579 | |
| 580 | return 0; |
| 581 | } |
| 582 | |
| 583 | bool MipsInstrInfo::SafeAfterMflo(const MachineInstr &MI) const { |
| 584 | if (IsDIVMULT(MI.getOpcode())) |
| 585 | return false; |
| 586 | |
| 587 | return true; |
| 588 | } |
| 589 | |
| 590 | /// Predicate for distingushing between control transfer instructions and all |
| 591 | /// other instructions for handling forbidden slots. Consider inline assembly |
| 592 | /// as unsafe as well. |
| 593 | bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const { |
| 594 | if (MI.isInlineAsm()) |
| 595 | return false; |
| 596 | |
| 597 | return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0; |
| 598 | } |
| 599 | |
| 600 | bool MipsInstrInfo::SafeInFPUDelaySlot(const MachineInstr &MIInSlot, |
| 601 | const MachineInstr &FPUMI) const { |
| 602 | if (MIInSlot.isInlineAsm()) |
| 603 | return false; |
| 604 | |
| 605 | if (HasFPUDelaySlot(MI: MIInSlot)) |
| 606 | return false; |
| 607 | |
| 608 | switch (MIInSlot.getOpcode()) { |
| 609 | case Mips::BC1F: |
| 610 | case Mips::BC1FL: |
| 611 | case Mips::BC1T: |
| 612 | case Mips::BC1TL: |
| 613 | return false; |
| 614 | } |
| 615 | |
| 616 | for (const MachineOperand &Op : FPUMI.defs()) { |
| 617 | if (!Op.isReg()) |
| 618 | continue; |
| 619 | |
| 620 | bool Reads, Writes; |
| 621 | std::tie(args&: Reads, args&: Writes) = MIInSlot.readsWritesVirtualRegister(Reg: Op.getReg()); |
| 622 | |
| 623 | if (Reads || Writes) |
| 624 | return false; |
| 625 | } |
| 626 | |
| 627 | return true; |
| 628 | } |
| 629 | |
| 630 | /// Predicate for distinguishing instructions that are hazardous in a load delay |
| 631 | /// slot. Consider inline assembly as unsafe as well. |
| 632 | bool MipsInstrInfo::SafeInLoadDelaySlot(const MachineInstr &MIInSlot, |
| 633 | const MachineInstr &LoadMI) const { |
| 634 | if (MIInSlot.isInlineAsm()) |
| 635 | return false; |
| 636 | |
| 637 | return !llvm::any_of(Range: LoadMI.defs(), P: [&](const MachineOperand &Op) { |
| 638 | return Op.isReg() && MIInSlot.readsRegister(Reg: Op.getReg(), /*TRI=*/nullptr); |
| 639 | }); |
| 640 | } |
| 641 | |
| 642 | bool MipsInstrInfo::IsMfloOrMfhi(const MachineInstr &MI) const { |
| 643 | if (IsMFLOMFHI(MI.getOpcode())) |
| 644 | return true; |
| 645 | |
| 646 | return false; |
| 647 | } |
| 648 | |
| 649 | /// Predicate for distingushing instructions that have forbidden slots. |
| 650 | bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const { |
| 651 | return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0; |
| 652 | } |
| 653 | |
| 654 | /// Predicate for distingushing instructions that have FPU delay slots. |
| 655 | bool MipsInstrInfo::HasFPUDelaySlot(const MachineInstr &MI) const { |
| 656 | switch (MI.getOpcode()) { |
| 657 | case Mips::MTC1: |
| 658 | case Mips::MFC1: |
| 659 | case Mips::MTC1_D64: |
| 660 | case Mips::MFC1_D64: |
| 661 | case Mips::DMTC1: |
| 662 | case Mips::DMFC1: |
| 663 | case Mips::FCMP_S32: |
| 664 | case Mips::FCMP_D32: |
| 665 | case Mips::FCMP_D64: |
| 666 | return true; |
| 667 | |
| 668 | default: |
| 669 | return false; |
| 670 | } |
| 671 | } |
| 672 | |
| 673 | /// Predicate for distingushing instructions that have load delay slots. |
| 674 | bool MipsInstrInfo::HasLoadDelaySlot(const MachineInstr &MI) const { |
| 675 | switch (MI.getOpcode()) { |
| 676 | case Mips::LB: |
| 677 | case Mips::LBu: |
| 678 | case Mips::LH: |
| 679 | case Mips::LHu: |
| 680 | case Mips::LW: |
| 681 | case Mips::LWR: |
| 682 | case Mips::LWL: |
| 683 | return true; |
| 684 | default: |
| 685 | return false; |
| 686 | } |
| 687 | } |
| 688 | |
| 689 | bool MipsInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const { |
| 690 | const unsigned Opcode = MI.getOpcode(); |
| 691 | switch (Opcode) { |
| 692 | default: |
| 693 | break; |
| 694 | case Mips::ADDiu: |
| 695 | case Mips::ADDiu_MM: |
| 696 | case Mips::DADDiu: |
| 697 | return ((MI.getOperand(i: 2).isImm() && MI.getOperand(i: 2).getImm() == 0) || |
| 698 | (MI.getOperand(i: 1).isReg() && |
| 699 | (MI.getOperand(i: 1).getReg() == Mips::ZERO || |
| 700 | MI.getOperand(i: 1).getReg() == Mips::ZERO_64))); |
| 701 | } |
| 702 | return MI.isAsCheapAsAMove(); |
| 703 | } |
| 704 | |
| 705 | /// Return the number of bytes of code the specified instruction may be. |
| 706 | unsigned MipsInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { |
| 707 | switch (MI.getOpcode()) { |
| 708 | default: |
| 709 | return MI.getDesc().getSize(); |
| 710 | case TargetOpcode::INLINEASM: |
| 711 | case TargetOpcode::INLINEASM_BR: { // Inline Asm: Variable size. |
| 712 | const MachineFunction *MF = MI.getParent()->getParent(); |
| 713 | const char *AsmStr = MI.getOperand(i: 0).getSymbolName(); |
| 714 | return getInlineAsmLength(Str: AsmStr, MAI: *MF->getTarget().getMCAsmInfo()); |
| 715 | } |
| 716 | case Mips::CONSTPOOL_ENTRY: |
| 717 | // If this machine instr is a constant pool entry, its size is recorded as |
| 718 | // operand #2. |
| 719 | return MI.getOperand(i: 2).getImm(); |
| 720 | } |
| 721 | } |
| 722 | |
| 723 | MachineInstrBuilder |
| 724 | MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, |
| 725 | MachineBasicBlock::iterator I) const { |
| 726 | MachineInstrBuilder MIB; |
| 727 | |
| 728 | // Certain branches have two forms: e.g beq $1, $zero, dest vs beqz $1, dest |
| 729 | // Pick the zero form of the branch for readable assembly and for greater |
| 730 | // branch distance in non-microMIPS mode. |
| 731 | // Additional MIPSR6 does not permit the use of register $zero for compact |
| 732 | // branches. |
| 733 | // FIXME: Certain atomic sequences on mips64 generate 32bit references to |
| 734 | // Mips::ZERO, which is incorrect. This test should be updated to use |
| 735 | // Subtarget.getABI().GetZeroReg() when those atomic sequences and others |
| 736 | // are fixed. |
| 737 | int ZeroOperandPosition = -1; |
| 738 | bool BranchWithZeroOperand = false; |
| 739 | if (I->isBranch() && !I->isPseudo()) { |
| 740 | auto TRI = I->getParent()->getParent()->getSubtarget().getRegisterInfo(); |
| 741 | ZeroOperandPosition = I->findRegisterUseOperandIdx(Reg: Mips::ZERO, TRI, isKill: false); |
| 742 | BranchWithZeroOperand = ZeroOperandPosition != -1; |
| 743 | } |
| 744 | |
| 745 | if (BranchWithZeroOperand) { |
| 746 | switch (NewOpc) { |
| 747 | case Mips::BEQC: |
| 748 | NewOpc = Mips::BEQZC; |
| 749 | break; |
| 750 | case Mips::BNEC: |
| 751 | NewOpc = Mips::BNEZC; |
| 752 | break; |
| 753 | case Mips::BGEC: |
| 754 | NewOpc = Mips::BGEZC; |
| 755 | break; |
| 756 | case Mips::BLTC: |
| 757 | NewOpc = Mips::BLTZC; |
| 758 | break; |
| 759 | case Mips::BEQC64: |
| 760 | NewOpc = Mips::BEQZC64; |
| 761 | break; |
| 762 | case Mips::BNEC64: |
| 763 | NewOpc = Mips::BNEZC64; |
| 764 | break; |
| 765 | } |
| 766 | } |
| 767 | |
| 768 | MIB = BuildMI(BB&: *I->getParent(), I, MIMD: I->getDebugLoc(), MCID: get(Opcode: NewOpc)); |
| 769 | |
| 770 | // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an |
| 771 | // immediate 0 as an operand and requires the removal of it's implicit-def %ra |
| 772 | // implicit operand as copying the implicit operations of the instructio we're |
| 773 | // looking at will give us the correct flags. |
| 774 | if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || |
| 775 | NewOpc == Mips::JIALC64) { |
| 776 | |
| 777 | if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64) |
| 778 | MIB->removeOperand(OpNo: 0); |
| 779 | |
| 780 | for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { |
| 781 | MIB.add(MO: I->getOperand(i: J)); |
| 782 | } |
| 783 | |
| 784 | MIB.addImm(Val: 0); |
| 785 | |
| 786 | // If I has an MCSymbol operand (used by asm printer, to emit R_MIPS_JALR), |
| 787 | // add it to the new instruction. |
| 788 | for (unsigned J = I->getDesc().getNumOperands(), E = I->getNumOperands(); |
| 789 | J < E; ++J) { |
| 790 | const MachineOperand &MO = I->getOperand(i: J); |
| 791 | if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) |
| 792 | MIB.addSym(Sym: MO.getMCSymbol(), TargetFlags: MipsII::MO_JALR); |
| 793 | } |
| 794 | |
| 795 | |
| 796 | } else { |
| 797 | for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { |
| 798 | if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) |
| 799 | continue; |
| 800 | |
| 801 | MIB.add(MO: I->getOperand(i: J)); |
| 802 | } |
| 803 | } |
| 804 | |
| 805 | MIB.copyImplicitOps(OtherMI: *I); |
| 806 | MIB.cloneMemRefs(OtherMI: *I); |
| 807 | return MIB; |
| 808 | } |
| 809 | |
| 810 | bool MipsInstrInfo::findCommutedOpIndices(const MachineInstr &MI, |
| 811 | unsigned &SrcOpIdx1, |
| 812 | unsigned &SrcOpIdx2) const { |
| 813 | assert(!MI.isBundle() && |
| 814 | "TargetInstrInfo::findCommutedOpIndices() can't handle bundles" ); |
| 815 | |
| 816 | const MCInstrDesc &MCID = MI.getDesc(); |
| 817 | if (!MCID.isCommutable()) |
| 818 | return false; |
| 819 | |
| 820 | switch (MI.getOpcode()) { |
| 821 | case Mips::DPADD_U_H: |
| 822 | case Mips::DPADD_U_W: |
| 823 | case Mips::DPADD_U_D: |
| 824 | case Mips::DPADD_S_H: |
| 825 | case Mips::DPADD_S_W: |
| 826 | case Mips::DPADD_S_D: |
| 827 | // The first operand is both input and output, so it should not commute |
| 828 | if (!fixCommutedOpIndices(ResultIdx1&: SrcOpIdx1, ResultIdx2&: SrcOpIdx2, CommutableOpIdx1: 2, CommutableOpIdx2: 3)) |
| 829 | return false; |
| 830 | |
| 831 | if (!MI.getOperand(i: SrcOpIdx1).isReg() || !MI.getOperand(i: SrcOpIdx2).isReg()) |
| 832 | return false; |
| 833 | return true; |
| 834 | } |
| 835 | return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2); |
| 836 | } |
| 837 | |
| 838 | // ins, ext, dext*, dins have the following constraints: |
| 839 | // X <= pos < Y |
| 840 | // X < size <= Y |
| 841 | // X < pos+size <= Y |
| 842 | // |
| 843 | // dinsm and dinsu have the following constraints: |
| 844 | // X <= pos < Y |
| 845 | // X <= size <= Y |
| 846 | // X < pos+size <= Y |
| 847 | // |
| 848 | // The callee of verifyInsExtInstruction however gives the bounds of |
| 849 | // dins[um] like the other (d)ins (d)ext(um) instructions, so that this |
| 850 | // function doesn't have to vary it's behaviour based on the instruction |
| 851 | // being checked. |
| 852 | static bool verifyInsExtInstruction(const MachineInstr &MI, StringRef &ErrInfo, |
| 853 | const int64_t PosLow, const int64_t PosHigh, |
| 854 | const int64_t SizeLow, |
| 855 | const int64_t SizeHigh, |
| 856 | const int64_t BothLow, |
| 857 | const int64_t BothHigh) { |
| 858 | MachineOperand MOPos = MI.getOperand(i: 2); |
| 859 | if (!MOPos.isImm()) { |
| 860 | ErrInfo = "Position is not an immediate!" ; |
| 861 | return false; |
| 862 | } |
| 863 | int64_t Pos = MOPos.getImm(); |
| 864 | if (!((PosLow <= Pos) && (Pos < PosHigh))) { |
| 865 | ErrInfo = "Position operand is out of range!" ; |
| 866 | return false; |
| 867 | } |
| 868 | |
| 869 | MachineOperand MOSize = MI.getOperand(i: 3); |
| 870 | if (!MOSize.isImm()) { |
| 871 | ErrInfo = "Size operand is not an immediate!" ; |
| 872 | return false; |
| 873 | } |
| 874 | int64_t Size = MOSize.getImm(); |
| 875 | if (!((SizeLow < Size) && (Size <= SizeHigh))) { |
| 876 | ErrInfo = "Size operand is out of range!" ; |
| 877 | return false; |
| 878 | } |
| 879 | |
| 880 | if (!((BothLow < (Pos + Size)) && ((Pos + Size) <= BothHigh))) { |
| 881 | ErrInfo = "Position + Size is out of range!" ; |
| 882 | return false; |
| 883 | } |
| 884 | |
| 885 | return true; |
| 886 | } |
| 887 | |
| 888 | // Perform target specific instruction verification. |
| 889 | bool MipsInstrInfo::verifyInstruction(const MachineInstr &MI, |
| 890 | StringRef &ErrInfo) const { |
| 891 | // Verify that ins and ext instructions are well formed. |
| 892 | switch (MI.getOpcode()) { |
| 893 | case Mips::EXT: |
| 894 | case Mips::EXT_MM: |
| 895 | case Mips::INS: |
| 896 | case Mips::INS_MM: |
| 897 | case Mips::DINS: |
| 898 | return verifyInsExtInstruction(MI, ErrInfo, PosLow: 0, PosHigh: 32, SizeLow: 0, SizeHigh: 32, BothLow: 0, BothHigh: 32); |
| 899 | case Mips::DINSM: |
| 900 | // The ISA spec has a subtle difference between dinsm and dextm |
| 901 | // in that it says: |
| 902 | // 2 <= size <= 64 for 'dinsm' but 'dextm' has 32 < size <= 64. |
| 903 | // To make the bounds checks similar, the range 1 < size <= 64 is checked |
| 904 | // for 'dinsm'. |
| 905 | return verifyInsExtInstruction(MI, ErrInfo, PosLow: 0, PosHigh: 32, SizeLow: 1, SizeHigh: 64, BothLow: 32, BothHigh: 64); |
| 906 | case Mips::DINSU: |
| 907 | // The ISA spec has a subtle difference between dinsu and dextu in that |
| 908 | // the size range of dinsu is specified as 1 <= size <= 32 whereas size |
| 909 | // for dextu is 0 < size <= 32. The range checked for dinsu here is |
| 910 | // 0 < size <= 32, which is equivalent and similar to dextu. |
| 911 | return verifyInsExtInstruction(MI, ErrInfo, PosLow: 32, PosHigh: 64, SizeLow: 0, SizeHigh: 32, BothLow: 32, BothHigh: 64); |
| 912 | case Mips::DEXT: |
| 913 | return verifyInsExtInstruction(MI, ErrInfo, PosLow: 0, PosHigh: 32, SizeLow: 0, SizeHigh: 32, BothLow: 0, BothHigh: 63); |
| 914 | case Mips::DEXTM: |
| 915 | return verifyInsExtInstruction(MI, ErrInfo, PosLow: 0, PosHigh: 32, SizeLow: 32, SizeHigh: 64, BothLow: 32, BothHigh: 64); |
| 916 | case Mips::DEXTU: |
| 917 | return verifyInsExtInstruction(MI, ErrInfo, PosLow: 32, PosHigh: 64, SizeLow: 0, SizeHigh: 32, BothLow: 32, BothHigh: 64); |
| 918 | case Mips::TAILCALLREG: |
| 919 | case Mips::PseudoIndirectBranch: |
| 920 | case Mips::JR: |
| 921 | case Mips::JR64: |
| 922 | case Mips::JALR: |
| 923 | case Mips::JALR64: |
| 924 | case Mips::JALRPseudo: |
| 925 | if (!Subtarget.useIndirectJumpsHazard()) |
| 926 | return true; |
| 927 | |
| 928 | ErrInfo = "invalid instruction when using jump guards!" ; |
| 929 | return false; |
| 930 | default: |
| 931 | return true; |
| 932 | } |
| 933 | |
| 934 | return true; |
| 935 | } |
| 936 | |
| 937 | std::pair<unsigned, unsigned> |
| 938 | MipsInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { |
| 939 | return std::make_pair(x&: TF, y: 0u); |
| 940 | } |
| 941 | |
| 942 | ArrayRef<std::pair<unsigned, const char*>> |
| 943 | MipsInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { |
| 944 | using namespace MipsII; |
| 945 | |
| 946 | static const std::pair<unsigned, const char*> Flags[] = { |
| 947 | {MO_GOT, "mips-got" }, |
| 948 | {MO_GOT_CALL, "mips-got-call" }, |
| 949 | {MO_GPREL, "mips-gprel" }, |
| 950 | {MO_ABS_HI, "mips-abs-hi" }, |
| 951 | {MO_ABS_LO, "mips-abs-lo" }, |
| 952 | {MO_TLSGD, "mips-tlsgd" }, |
| 953 | {MO_TLSLDM, "mips-tlsldm" }, |
| 954 | {MO_DTPREL_HI, "mips-dtprel-hi" }, |
| 955 | {MO_DTPREL_LO, "mips-dtprel-lo" }, |
| 956 | {MO_GOTTPREL, "mips-gottprel" }, |
| 957 | {MO_TPREL_HI, "mips-tprel-hi" }, |
| 958 | {MO_TPREL_LO, "mips-tprel-lo" }, |
| 959 | {MO_GPOFF_HI, "mips-gpoff-hi" }, |
| 960 | {MO_GPOFF_LO, "mips-gpoff-lo" }, |
| 961 | {MO_GOT_DISP, "mips-got-disp" }, |
| 962 | {MO_GOT_PAGE, "mips-got-page" }, |
| 963 | {MO_GOT_OFST, "mips-got-ofst" }, |
| 964 | {MO_HIGHER, "mips-higher" }, |
| 965 | {MO_HIGHEST, "mips-highest" }, |
| 966 | {MO_GOT_HI16, "mips-got-hi16" }, |
| 967 | {MO_GOT_LO16, "mips-got-lo16" }, |
| 968 | {MO_CALL_HI16, "mips-call-hi16" }, |
| 969 | {MO_CALL_LO16, "mips-call-lo16" }, |
| 970 | {MO_JALR, "mips-jalr" } |
| 971 | }; |
| 972 | return ArrayRef(Flags); |
| 973 | } |
| 974 | |
| 975 | std::optional<ParamLoadedValue> |
| 976 | MipsInstrInfo::describeLoadedValue(const MachineInstr &MI, Register Reg) const { |
| 977 | DIExpression *Expr = |
| 978 | DIExpression::get(Context&: MI.getMF()->getFunction().getContext(), Elements: {}); |
| 979 | |
| 980 | // TODO: Special MIPS instructions that need to be described separately. |
| 981 | if (auto RegImm = isAddImmediate(MI, Reg)) { |
| 982 | Register SrcReg = RegImm->Reg; |
| 983 | int64_t Offset = RegImm->Imm; |
| 984 | // When SrcReg is $zero, treat loaded value as immediate only. |
| 985 | // Ex. $a2 = ADDiu $zero, 10 |
| 986 | if (SrcReg == Mips::ZERO || SrcReg == Mips::ZERO_64) { |
| 987 | return ParamLoadedValue(MI.getOperand(i: 2), Expr); |
| 988 | } |
| 989 | Expr = DIExpression::prepend(Expr, Flags: DIExpression::ApplyOffset, Offset); |
| 990 | return ParamLoadedValue(MachineOperand::CreateReg(Reg: SrcReg, isDef: false), Expr); |
| 991 | } else if (auto DestSrc = isCopyInstr(MI)) { |
| 992 | const MachineFunction *MF = MI.getMF(); |
| 993 | const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); |
| 994 | Register DestReg = DestSrc->Destination->getReg(); |
| 995 | // TODO: Handle cases where the Reg is sub- or super-register of the |
| 996 | // DestReg. |
| 997 | if (TRI->isSuperRegister(RegA: Reg, RegB: DestReg) || TRI->isSubRegister(RegA: Reg, RegB: DestReg)) |
| 998 | return std::nullopt; |
| 999 | } |
| 1000 | |
| 1001 | return TargetInstrInfo::describeLoadedValue(MI, Reg); |
| 1002 | } |
| 1003 | |
| 1004 | std::optional<RegImmPair> MipsInstrInfo::isAddImmediate(const MachineInstr &MI, |
| 1005 | Register Reg) const { |
| 1006 | // TODO: Handle cases where Reg is a super- or sub-register of the |
| 1007 | // destination register. |
| 1008 | const MachineOperand &Op0 = MI.getOperand(i: 0); |
| 1009 | if (!Op0.isReg() || Reg != Op0.getReg()) |
| 1010 | return std::nullopt; |
| 1011 | |
| 1012 | switch (MI.getOpcode()) { |
| 1013 | case Mips::ADDiu: |
| 1014 | case Mips::DADDiu: { |
| 1015 | const MachineOperand &Dop = MI.getOperand(i: 0); |
| 1016 | const MachineOperand &Sop1 = MI.getOperand(i: 1); |
| 1017 | const MachineOperand &Sop2 = MI.getOperand(i: 2); |
| 1018 | // Value is sum of register and immediate. Immediate value could be |
| 1019 | // global string address which is not supported. |
| 1020 | if (Dop.isReg() && Sop1.isReg() && Sop2.isImm()) |
| 1021 | return RegImmPair{Sop1.getReg(), Sop2.getImm()}; |
| 1022 | // TODO: Handle case where Sop1 is a frame-index. |
| 1023 | } |
| 1024 | } |
| 1025 | return std::nullopt; |
| 1026 | } |
| 1027 | |