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 | |