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