1//===-- MipsExpandPseudoInsts.cpp - Expand pseudo instructions ------------===//
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 a pass that expands pseudo instructions into target
10// instructions to allow proper scheduling, if-conversion, and other late
11// optimizations. This pass should be run after register allocation but before
12// the post-regalloc scheduling pass.
13//
14// This is currently only used for expanding atomic pseudos after register
15// allocation. We do this to avoid the fast register allocator introducing
16// spills between ll and sc. These stores cause some MIPS implementations to
17// abort the atomic RMW sequence.
18//
19//===----------------------------------------------------------------------===//
20
21#include "Mips.h"
22#include "MipsInstrInfo.h"
23#include "MipsSubtarget.h"
24#include "llvm/CodeGen/LivePhysRegs.h"
25#include "llvm/CodeGen/MachineFunctionPass.h"
26#include "llvm/CodeGen/MachineInstrBuilder.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "mips-pseudo"
31
32namespace {
33 class MipsExpandPseudo : public MachineFunctionPass {
34 public:
35 static char ID;
36 MipsExpandPseudo() : MachineFunctionPass(ID) {}
37
38 const MipsInstrInfo *TII;
39 const MipsSubtarget *STI;
40
41 bool runOnMachineFunction(MachineFunction &Fn) override;
42
43 MachineFunctionProperties getRequiredProperties() const override {
44 return MachineFunctionProperties().setNoVRegs();
45 }
46
47 StringRef getPassName() const override {
48 return "Mips pseudo instruction expansion pass";
49 }
50
51 private:
52 bool expandAtomicCmpSwap(MachineBasicBlock &MBB,
53 MachineBasicBlock::iterator MBBI,
54 MachineBasicBlock::iterator &NextMBBI);
55 bool expandAtomicCmpSwapSubword(MachineBasicBlock &MBB,
56 MachineBasicBlock::iterator MBBI,
57 MachineBasicBlock::iterator &NextMBBI);
58
59 bool expandAtomicBinOp(MachineBasicBlock &BB,
60 MachineBasicBlock::iterator I,
61 MachineBasicBlock::iterator &NMBBI, unsigned Size);
62 bool expandAtomicBinOpSubword(MachineBasicBlock &BB,
63 MachineBasicBlock::iterator I,
64 MachineBasicBlock::iterator &NMBBI);
65
66 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
67 MachineBasicBlock::iterator &NMBB);
68 bool expandMBB(MachineBasicBlock &MBB);
69 };
70 char MipsExpandPseudo::ID = 0;
71}
72
73bool MipsExpandPseudo::expandAtomicCmpSwapSubword(
74 MachineBasicBlock &BB, MachineBasicBlock::iterator I,
75 MachineBasicBlock::iterator &NMBBI) {
76
77 MachineFunction *MF = BB.getParent();
78
79 const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
80 DebugLoc DL = I->getDebugLoc();
81 unsigned LL, SC;
82
83 unsigned ZERO = Mips::ZERO;
84 unsigned BNE = Mips::BNE;
85 unsigned BEQ = Mips::BEQ;
86 unsigned SEOp =
87 I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I8_POSTRA ? Mips::SEB : Mips::SEH;
88
89 if (STI->inMicroMipsMode()) {
90 LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
91 SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
92 BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM;
93 BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
94 } else {
95 LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
96 : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
97 SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
98 : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
99 }
100
101 Register Dest = I->getOperand(i: 0).getReg();
102 Register Ptr = I->getOperand(i: 1).getReg();
103 Register Mask = I->getOperand(i: 2).getReg();
104 Register ShiftCmpVal = I->getOperand(i: 3).getReg();
105 Register Mask2 = I->getOperand(i: 4).getReg();
106 Register ShiftNewVal = I->getOperand(i: 5).getReg();
107 Register ShiftAmnt = I->getOperand(i: 6).getReg();
108 Register Scratch = I->getOperand(i: 7).getReg();
109 Register Scratch2 = I->getOperand(i: 8).getReg();
110
111 // insert new blocks after the current block
112 const BasicBlock *LLVM_BB = BB.getBasicBlock();
113 MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
114 MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
115 MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
116 MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
117 MachineFunction::iterator It = ++BB.getIterator();
118 MF->insert(MBBI: It, MBB: loop1MBB);
119 MF->insert(MBBI: It, MBB: loop2MBB);
120 MF->insert(MBBI: It, MBB: sinkMBB);
121 MF->insert(MBBI: It, MBB: exitMBB);
122
123 // Transfer the remainder of BB and its successor edges to exitMBB.
124 exitMBB->splice(Where: exitMBB->begin(), Other: &BB,
125 From: std::next(x: MachineBasicBlock::iterator(I)), To: BB.end());
126 exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB);
127
128 // thisMBB:
129 // ...
130 // fallthrough --> loop1MBB
131 BB.addSuccessor(Succ: loop1MBB, Prob: BranchProbability::getOne());
132 loop1MBB->addSuccessor(Succ: sinkMBB);
133 loop1MBB->addSuccessor(Succ: loop2MBB);
134 loop1MBB->normalizeSuccProbs();
135 loop2MBB->addSuccessor(Succ: loop1MBB);
136 loop2MBB->addSuccessor(Succ: sinkMBB);
137 loop2MBB->normalizeSuccProbs();
138 sinkMBB->addSuccessor(Succ: exitMBB, Prob: BranchProbability::getOne());
139
140 // loop1MBB:
141 // ll dest, 0(ptr)
142 // and Mask', dest, Mask
143 // bne Mask', ShiftCmpVal, exitMBB
144 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: Scratch).addReg(RegNo: Ptr).addImm(Val: 0);
145 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: Scratch2)
146 .addReg(RegNo: Scratch)
147 .addReg(RegNo: Mask);
148 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: BNE))
149 .addReg(RegNo: Scratch2).addReg(RegNo: ShiftCmpVal).addMBB(MBB: sinkMBB);
150
151 // loop2MBB:
152 // and dest, dest, mask2
153 // or dest, dest, ShiftNewVal
154 // sc dest, dest, 0(ptr)
155 // beq dest, $0, loop1MBB
156 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: Scratch)
157 .addReg(RegNo: Scratch, flags: RegState::Kill)
158 .addReg(RegNo: Mask2);
159 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: Scratch)
160 .addReg(RegNo: Scratch, flags: RegState::Kill)
161 .addReg(RegNo: ShiftNewVal);
162 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch)
163 .addReg(RegNo: Scratch, flags: RegState::Kill)
164 .addReg(RegNo: Ptr)
165 .addImm(Val: 0);
166 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
167 .addReg(RegNo: Scratch, flags: RegState::Kill)
168 .addReg(RegNo: ZERO)
169 .addMBB(MBB: loop1MBB);
170
171 // sinkMBB:
172 // srl srlres, Mask', shiftamt
173 // sign_extend dest,srlres
174 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRLV), DestReg: Dest)
175 .addReg(RegNo: Scratch2)
176 .addReg(RegNo: ShiftAmnt);
177 if (STI->hasMips32r2()) {
178 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: Dest).addReg(RegNo: Dest);
179 } else {
180 const unsigned ShiftImm =
181 I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I16_POSTRA ? 16 : 24;
182 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: Dest)
183 .addReg(RegNo: Dest, flags: RegState::Kill)
184 .addImm(Val: ShiftImm);
185 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRA), DestReg: Dest)
186 .addReg(RegNo: Dest, flags: RegState::Kill)
187 .addImm(Val: ShiftImm);
188 }
189
190 LivePhysRegs LiveRegs;
191 computeAndAddLiveIns(LiveRegs, MBB&: *loop1MBB);
192 computeAndAddLiveIns(LiveRegs, MBB&: *loop2MBB);
193 computeAndAddLiveIns(LiveRegs, MBB&: *sinkMBB);
194 computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB);
195
196 NMBBI = BB.end();
197 I->eraseFromParent();
198 return true;
199}
200
201bool MipsExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB,
202 MachineBasicBlock::iterator I,
203 MachineBasicBlock::iterator &NMBBI) {
204
205 const unsigned Size =
206 I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I32_POSTRA ? 4 : 8;
207 MachineFunction *MF = BB.getParent();
208
209 const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
210 DebugLoc DL = I->getDebugLoc();
211
212 unsigned LL, SC, ZERO, BNE, BEQ, MOVE;
213
214 if (Size == 4) {
215 if (STI->inMicroMipsMode()) {
216 LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
217 SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
218 BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM;
219 BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
220 } else {
221 LL = STI->hasMips32r6()
222 ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
223 : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
224 SC = STI->hasMips32r6()
225 ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
226 : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
227 BNE = Mips::BNE;
228 BEQ = Mips::BEQ;
229 }
230
231 ZERO = Mips::ZERO;
232 MOVE = Mips::OR;
233 } else {
234 LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD;
235 SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD;
236 ZERO = Mips::ZERO_64;
237 BNE = Mips::BNE64;
238 BEQ = Mips::BEQ64;
239 MOVE = Mips::OR64;
240 }
241
242 Register Dest = I->getOperand(i: 0).getReg();
243 Register Ptr = I->getOperand(i: 1).getReg();
244 Register OldVal = I->getOperand(i: 2).getReg();
245 Register NewVal = I->getOperand(i: 3).getReg();
246 Register Scratch = I->getOperand(i: 4).getReg();
247
248 // insert new blocks after the current block
249 const BasicBlock *LLVM_BB = BB.getBasicBlock();
250 MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
251 MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
252 MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
253 MachineFunction::iterator It = ++BB.getIterator();
254 MF->insert(MBBI: It, MBB: loop1MBB);
255 MF->insert(MBBI: It, MBB: loop2MBB);
256 MF->insert(MBBI: It, MBB: exitMBB);
257
258 // Transfer the remainder of BB and its successor edges to exitMBB.
259 exitMBB->splice(Where: exitMBB->begin(), Other: &BB,
260 From: std::next(x: MachineBasicBlock::iterator(I)), To: BB.end());
261 exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB);
262
263 // thisMBB:
264 // ...
265 // fallthrough --> loop1MBB
266 BB.addSuccessor(Succ: loop1MBB, Prob: BranchProbability::getOne());
267 loop1MBB->addSuccessor(Succ: exitMBB);
268 loop1MBB->addSuccessor(Succ: loop2MBB);
269 loop1MBB->normalizeSuccProbs();
270 loop2MBB->addSuccessor(Succ: loop1MBB);
271 loop2MBB->addSuccessor(Succ: exitMBB);
272 loop2MBB->normalizeSuccProbs();
273
274 // loop1MBB:
275 // ll dest, 0(ptr)
276 // bne dest, oldval, exitMBB
277 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: Dest).addReg(RegNo: Ptr).addImm(Val: 0);
278 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: BNE))
279 .addReg(RegNo: Dest, flags: RegState::Kill).addReg(RegNo: OldVal).addMBB(MBB: exitMBB);
280
281 // loop2MBB:
282 // move scratch, NewVal
283 // sc Scratch, Scratch, 0(ptr)
284 // beq Scratch, $0, loop1MBB
285 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: MOVE), DestReg: Scratch).addReg(RegNo: NewVal).addReg(RegNo: ZERO);
286 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch)
287 .addReg(RegNo: Scratch).addReg(RegNo: Ptr).addImm(Val: 0);
288 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
289 .addReg(RegNo: Scratch, flags: RegState::Kill).addReg(RegNo: ZERO).addMBB(MBB: loop1MBB);
290
291 LivePhysRegs LiveRegs;
292 computeAndAddLiveIns(LiveRegs, MBB&: *loop1MBB);
293 computeAndAddLiveIns(LiveRegs, MBB&: *loop2MBB);
294 computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB);
295
296 NMBBI = BB.end();
297 I->eraseFromParent();
298 return true;
299}
300
301bool MipsExpandPseudo::expandAtomicBinOpSubword(
302 MachineBasicBlock &BB, MachineBasicBlock::iterator I,
303 MachineBasicBlock::iterator &NMBBI) {
304
305 MachineFunction *MF = BB.getParent();
306
307 const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
308 DebugLoc DL = I->getDebugLoc();
309
310 unsigned LL, SC, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ;
311 unsigned BEQ = Mips::BEQ;
312 unsigned SEOp = Mips::SEH;
313
314 if (STI->inMicroMipsMode()) {
315 LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
316 SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
317 BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
318 SLT = Mips::SLT_MM;
319 SLTu = Mips::SLTu_MM;
320 OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM;
321 MOVN = Mips::MOVN_I_MM;
322 MOVZ = Mips::MOVZ_I_MM;
323 SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ;
324 SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ;
325 } else {
326 LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
327 : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
328 SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
329 : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
330 SLT = Mips::SLT;
331 SLTu = Mips::SLTu;
332 OR = Mips::OR;
333 MOVN = Mips::MOVN_I_I;
334 MOVZ = Mips::MOVZ_I_I;
335 SELNEZ = Mips::SELNEZ;
336 SELEQZ = Mips::SELEQZ;
337 }
338
339 bool IsSwap = false;
340 bool IsNand = false;
341 bool IsMin = false;
342 bool IsMax = false;
343 bool IsUnsigned = false;
344 bool DestOK = false;
345
346 unsigned Opcode = 0;
347 switch (I->getOpcode()) {
348 case Mips::ATOMIC_LOAD_NAND_I8_POSTRA:
349 SEOp = Mips::SEB;
350 [[fallthrough]];
351 case Mips::ATOMIC_LOAD_NAND_I16_POSTRA:
352 IsNand = true;
353 break;
354 case Mips::ATOMIC_SWAP_I8_POSTRA:
355 SEOp = Mips::SEB;
356 [[fallthrough]];
357 case Mips::ATOMIC_SWAP_I16_POSTRA:
358 IsSwap = true;
359 break;
360 case Mips::ATOMIC_LOAD_ADD_I8_POSTRA:
361 SEOp = Mips::SEB;
362 [[fallthrough]];
363 case Mips::ATOMIC_LOAD_ADD_I16_POSTRA:
364 Opcode = Mips::ADDu;
365 break;
366 case Mips::ATOMIC_LOAD_SUB_I8_POSTRA:
367 SEOp = Mips::SEB;
368 [[fallthrough]];
369 case Mips::ATOMIC_LOAD_SUB_I16_POSTRA:
370 Opcode = Mips::SUBu;
371 break;
372 case Mips::ATOMIC_LOAD_AND_I8_POSTRA:
373 SEOp = Mips::SEB;
374 [[fallthrough]];
375 case Mips::ATOMIC_LOAD_AND_I16_POSTRA:
376 Opcode = Mips::AND;
377 break;
378 case Mips::ATOMIC_LOAD_OR_I8_POSTRA:
379 SEOp = Mips::SEB;
380 [[fallthrough]];
381 case Mips::ATOMIC_LOAD_OR_I16_POSTRA:
382 Opcode = Mips::OR;
383 break;
384 case Mips::ATOMIC_LOAD_XOR_I8_POSTRA:
385 SEOp = Mips::SEB;
386 [[fallthrough]];
387 case Mips::ATOMIC_LOAD_XOR_I16_POSTRA:
388 Opcode = Mips::XOR;
389 break;
390 case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA:
391 SEOp = Mips::SEB;
392 IsUnsigned = true;
393 IsMin = true;
394 break;
395 case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA:
396 IsUnsigned = true;
397 IsMin = true;
398 break;
399 case Mips::ATOMIC_LOAD_MIN_I8_POSTRA:
400 SEOp = Mips::SEB;
401 IsMin = true;
402 break;
403 case Mips::ATOMIC_LOAD_MIN_I16_POSTRA:
404 IsMin = true;
405 break;
406 case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA:
407 SEOp = Mips::SEB;
408 IsUnsigned = true;
409 IsMax = true;
410 break;
411 case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA:
412 IsUnsigned = true;
413 IsMax = true;
414 break;
415 case Mips::ATOMIC_LOAD_MAX_I8_POSTRA:
416 SEOp = Mips::SEB;
417 IsMax = true;
418 break;
419 case Mips::ATOMIC_LOAD_MAX_I16_POSTRA:
420 IsMax = true;
421 break;
422 default:
423 llvm_unreachable("Unknown subword atomic pseudo for expansion!");
424 }
425
426 Register Dest = I->getOperand(i: 0).getReg();
427 Register Ptr = I->getOperand(i: 1).getReg();
428 Register Incr = I->getOperand(i: 2).getReg();
429 Register Mask = I->getOperand(i: 3).getReg();
430 Register Mask2 = I->getOperand(i: 4).getReg();
431 Register ShiftAmnt = I->getOperand(i: 5).getReg();
432 Register OldVal = I->getOperand(i: 6).getReg();
433 Register BinOpRes = I->getOperand(i: 7).getReg();
434 Register StoreVal = I->getOperand(i: 8).getReg();
435
436 const BasicBlock *LLVM_BB = BB.getBasicBlock();
437 MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
438 MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
439 MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
440 MachineFunction::iterator It = ++BB.getIterator();
441 MF->insert(MBBI: It, MBB: loopMBB);
442 MF->insert(MBBI: It, MBB: sinkMBB);
443 MF->insert(MBBI: It, MBB: exitMBB);
444
445 exitMBB->splice(Where: exitMBB->begin(), Other: &BB, From: std::next(x: I), To: BB.end());
446 exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB);
447
448 BB.addSuccessor(Succ: loopMBB, Prob: BranchProbability::getOne());
449 loopMBB->addSuccessor(Succ: sinkMBB);
450 loopMBB->addSuccessor(Succ: loopMBB);
451 loopMBB->normalizeSuccProbs();
452
453 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: OldVal).addReg(RegNo: Ptr).addImm(Val: 0);
454 if (IsNand) {
455 // and andres, oldval, incr2
456 // nor binopres, $0, andres
457 // and newval, binopres, mask
458 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
459 .addReg(RegNo: OldVal)
460 .addReg(RegNo: Incr);
461 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::NOR), DestReg: BinOpRes)
462 .addReg(RegNo: Mips::ZERO)
463 .addReg(RegNo: BinOpRes);
464 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
465 .addReg(RegNo: BinOpRes)
466 .addReg(RegNo: Mask);
467 } else if (IsMin || IsMax) {
468
469 assert(I->getNumOperands() == 10 &&
470 "Atomics min|max|umin|umax use an additional register");
471 Register Scratch4 = I->getOperand(i: 9).getReg();
472
473 unsigned SLTScratch4 = IsUnsigned ? SLTu : SLT;
474 unsigned SELIncr = IsMax ? SELNEZ : SELEQZ;
475 unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ;
476 unsigned MOVIncr = IsMax ? MOVN : MOVZ;
477
478 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRAV), DestReg: StoreVal)
479 .addReg(RegNo: OldVal)
480 .addReg(RegNo: ShiftAmnt);
481 if (IsUnsigned) {
482 const unsigned OpMask = SEOp == Mips::SEH ? 0xffff : 0xff;
483 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::ANDi), DestReg: StoreVal)
484 .addReg(RegNo: StoreVal)
485 .addImm(Val: OpMask);
486 } else if (STI->hasMips32r2()) {
487 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: StoreVal).addReg(RegNo: StoreVal);
488 } else {
489 const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24;
490 const unsigned SROp = IsUnsigned ? Mips::SRL : Mips::SRA;
491 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: StoreVal)
492 .addReg(RegNo: StoreVal, flags: RegState::Kill)
493 .addImm(Val: ShiftImm);
494 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SROp), DestReg: StoreVal)
495 .addReg(RegNo: StoreVal, flags: RegState::Kill)
496 .addImm(Val: ShiftImm);
497 }
498 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: Dest)
499 .addReg(RegNo: Mips::ZERO)
500 .addReg(RegNo: StoreVal);
501 DestOK = true;
502 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLLV), DestReg: StoreVal)
503 .addReg(RegNo: StoreVal)
504 .addReg(RegNo: ShiftAmnt);
505
506 // unsigned: sltu Scratch4, StoreVal, Incr
507 // signed: slt Scratch4, StoreVal, Incr
508 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SLTScratch4), DestReg: Scratch4)
509 .addReg(RegNo: StoreVal)
510 .addReg(RegNo: Incr);
511
512 if (STI->hasMips64r6() || STI->hasMips32r6()) {
513 // max: seleqz BinOpRes, OldVal, Scratch4
514 // selnez Scratch4, Incr, Scratch4
515 // or BinOpRes, BinOpRes, Scratch4
516 // min: selnqz BinOpRes, OldVal, Scratch4
517 // seleqz Scratch4, Incr, Scratch4
518 // or BinOpRes, BinOpRes, Scratch4
519 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELOldVal), DestReg: BinOpRes)
520 .addReg(RegNo: StoreVal)
521 .addReg(RegNo: Scratch4);
522 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELIncr), DestReg: Scratch4)
523 .addReg(RegNo: Incr)
524 .addReg(RegNo: Scratch4);
525 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
526 .addReg(RegNo: BinOpRes)
527 .addReg(RegNo: Scratch4);
528 } else {
529 // max: move BinOpRes, StoreVal
530 // movn BinOpRes, Incr, Scratch4, BinOpRes
531 // min: move BinOpRes, StoreVal
532 // movz BinOpRes, Incr, Scratch4, BinOpRes
533 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
534 .addReg(RegNo: StoreVal)
535 .addReg(RegNo: Mips::ZERO);
536 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: MOVIncr), DestReg: BinOpRes)
537 .addReg(RegNo: Incr)
538 .addReg(RegNo: Scratch4)
539 .addReg(RegNo: BinOpRes);
540 }
541
542 // and BinOpRes, BinOpRes, Mask
543 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
544 .addReg(RegNo: BinOpRes)
545 .addReg(RegNo: Mask);
546
547 } else if (!IsSwap) {
548 // <binop> binopres, oldval, incr2
549 // and newval, binopres, mask
550 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode), DestReg: BinOpRes)
551 .addReg(RegNo: OldVal)
552 .addReg(RegNo: Incr);
553 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
554 .addReg(RegNo: BinOpRes)
555 .addReg(RegNo: Mask);
556 } else { // atomic.swap
557 // and newval, incr2, mask
558 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
559 .addReg(RegNo: Incr)
560 .addReg(RegNo: Mask);
561 }
562
563 // and StoreVal, OlddVal, Mask2
564 // or StoreVal, StoreVal, BinOpRes
565 // StoreVal<tied1> = sc StoreVal, 0(Ptr)
566 // beq StoreVal, zero, loopMBB
567 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: StoreVal)
568 .addReg(RegNo: OldVal).addReg(RegNo: Mask2);
569 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: StoreVal)
570 .addReg(RegNo: StoreVal).addReg(RegNo: BinOpRes);
571 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: StoreVal)
572 .addReg(RegNo: StoreVal).addReg(RegNo: Ptr).addImm(Val: 0);
573 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
574 .addReg(RegNo: StoreVal).addReg(RegNo: Mips::ZERO).addMBB(MBB: loopMBB);
575
576 // sinkMBB:
577 // and maskedoldval1,oldval,mask
578 // srl srlres,maskedoldval1,shiftamt
579 // sign_extend dest,srlres
580
581 if (!DestOK) {
582 sinkMBB->addSuccessor(Succ: exitMBB, Prob: BranchProbability::getOne());
583 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: Dest).addReg(RegNo: OldVal).addReg(RegNo: Mask);
584 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRLV), DestReg: Dest)
585 .addReg(RegNo: Dest)
586 .addReg(RegNo: ShiftAmnt);
587
588 if (STI->hasMips32r2()) {
589 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: Dest).addReg(RegNo: Dest);
590 } else {
591 const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24;
592 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: Dest)
593 .addReg(RegNo: Dest, flags: RegState::Kill)
594 .addImm(Val: ShiftImm);
595 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRA), DestReg: Dest)
596 .addReg(RegNo: Dest, flags: RegState::Kill)
597 .addImm(Val: ShiftImm);
598 }
599 }
600
601 LivePhysRegs LiveRegs;
602 computeAndAddLiveIns(LiveRegs, MBB&: *loopMBB);
603 computeAndAddLiveIns(LiveRegs, MBB&: *sinkMBB);
604 computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB);
605
606 NMBBI = BB.end();
607 I->eraseFromParent();
608
609 return true;
610}
611
612bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB,
613 MachineBasicBlock::iterator I,
614 MachineBasicBlock::iterator &NMBBI,
615 unsigned Size) {
616 MachineFunction *MF = BB.getParent();
617
618 const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
619 DebugLoc DL = I->getDebugLoc();
620
621 unsigned LL, SC, ZERO, BEQ, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ;
622
623 if (Size == 4) {
624 if (STI->inMicroMipsMode()) {
625 LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
626 SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
627 BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
628 SLT = Mips::SLT_MM;
629 SLTu = Mips::SLTu_MM;
630 OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM;
631 MOVN = Mips::MOVN_I_MM;
632 MOVZ = Mips::MOVZ_I_MM;
633 SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ;
634 SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ;
635 } else {
636 LL = STI->hasMips32r6()
637 ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
638 : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
639 SC = STI->hasMips32r6()
640 ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
641 : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
642 BEQ = Mips::BEQ;
643 SLT = Mips::SLT;
644 SLTu = Mips::SLTu;
645 OR = Mips::OR;
646 MOVN = Mips::MOVN_I_I;
647 MOVZ = Mips::MOVZ_I_I;
648 SELNEZ = Mips::SELNEZ;
649 SELEQZ = Mips::SELEQZ;
650 }
651
652 ZERO = Mips::ZERO;
653 } else {
654 LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD;
655 SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD;
656 ZERO = Mips::ZERO_64;
657 BEQ = Mips::BEQ64;
658 SLT = Mips::SLT64;
659 SLTu = Mips::SLTu64;
660 OR = Mips::OR64;
661 MOVN = Mips::MOVN_I64_I64;
662 MOVZ = Mips::MOVZ_I64_I64;
663 SELNEZ = Mips::SELNEZ64;
664 SELEQZ = Mips::SELEQZ64;
665 }
666
667 Register OldVal = I->getOperand(i: 0).getReg();
668 Register Ptr = I->getOperand(i: 1).getReg();
669 Register Incr = I->getOperand(i: 2).getReg();
670 Register Scratch = I->getOperand(i: 3).getReg();
671
672 unsigned Opcode = 0;
673 unsigned AND = 0;
674 unsigned NOR = 0;
675
676 bool IsOr = false;
677 bool IsNand = false;
678 bool IsMin = false;
679 bool IsMax = false;
680 bool IsUnsigned = false;
681
682 switch (I->getOpcode()) {
683 case Mips::ATOMIC_LOAD_ADD_I32_POSTRA:
684 Opcode = Mips::ADDu;
685 break;
686 case Mips::ATOMIC_LOAD_SUB_I32_POSTRA:
687 Opcode = Mips::SUBu;
688 break;
689 case Mips::ATOMIC_LOAD_AND_I32_POSTRA:
690 Opcode = Mips::AND;
691 break;
692 case Mips::ATOMIC_LOAD_OR_I32_POSTRA:
693 Opcode = Mips::OR;
694 break;
695 case Mips::ATOMIC_LOAD_XOR_I32_POSTRA:
696 Opcode = Mips::XOR;
697 break;
698 case Mips::ATOMIC_LOAD_NAND_I32_POSTRA:
699 IsNand = true;
700 AND = Mips::AND;
701 NOR = Mips::NOR;
702 break;
703 case Mips::ATOMIC_SWAP_I32_POSTRA:
704 IsOr = true;
705 break;
706 case Mips::ATOMIC_LOAD_ADD_I64_POSTRA:
707 Opcode = Mips::DADDu;
708 break;
709 case Mips::ATOMIC_LOAD_SUB_I64_POSTRA:
710 Opcode = Mips::DSUBu;
711 break;
712 case Mips::ATOMIC_LOAD_AND_I64_POSTRA:
713 Opcode = Mips::AND64;
714 break;
715 case Mips::ATOMIC_LOAD_OR_I64_POSTRA:
716 Opcode = Mips::OR64;
717 break;
718 case Mips::ATOMIC_LOAD_XOR_I64_POSTRA:
719 Opcode = Mips::XOR64;
720 break;
721 case Mips::ATOMIC_LOAD_NAND_I64_POSTRA:
722 IsNand = true;
723 AND = Mips::AND64;
724 NOR = Mips::NOR64;
725 break;
726 case Mips::ATOMIC_SWAP_I64_POSTRA:
727 IsOr = true;
728 break;
729 case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA:
730 case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA:
731 IsUnsigned = true;
732 [[fallthrough]];
733 case Mips::ATOMIC_LOAD_MIN_I32_POSTRA:
734 case Mips::ATOMIC_LOAD_MIN_I64_POSTRA:
735 IsMin = true;
736 break;
737 case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA:
738 case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA:
739 IsUnsigned = true;
740 [[fallthrough]];
741 case Mips::ATOMIC_LOAD_MAX_I32_POSTRA:
742 case Mips::ATOMIC_LOAD_MAX_I64_POSTRA:
743 IsMax = true;
744 break;
745 default:
746 llvm_unreachable("Unknown pseudo atomic!");
747 }
748
749 const BasicBlock *LLVM_BB = BB.getBasicBlock();
750 MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
751 MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
752 MachineFunction::iterator It = ++BB.getIterator();
753 MF->insert(MBBI: It, MBB: loopMBB);
754 MF->insert(MBBI: It, MBB: exitMBB);
755
756 exitMBB->splice(Where: exitMBB->begin(), Other: &BB, From: std::next(x: I), To: BB.end());
757 exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB);
758
759 BB.addSuccessor(Succ: loopMBB, Prob: BranchProbability::getOne());
760 loopMBB->addSuccessor(Succ: exitMBB);
761 loopMBB->addSuccessor(Succ: loopMBB);
762 loopMBB->normalizeSuccProbs();
763
764 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: OldVal).addReg(RegNo: Ptr).addImm(Val: 0);
765 assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!");
766 assert((OldVal != Incr) && "Clobbered the wrong reg!");
767 if (IsMin || IsMax) {
768
769 assert(I->getNumOperands() == 5 &&
770 "Atomics min|max|umin|umax use an additional register");
771 MCRegister Scratch2 = I->getOperand(i: 4).getReg().asMCReg();
772
773 // On Mips64 result of slt is GPR32.
774 MCRegister Scratch2_32 =
775 (Size == 8) ? STI->getRegisterInfo()->getSubReg(Reg: Scratch2, Idx: Mips::sub_32)
776 : Scratch2;
777
778 unsigned SLTScratch2 = IsUnsigned ? SLTu : SLT;
779 unsigned SELIncr = IsMax ? SELNEZ : SELEQZ;
780 unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ;
781 unsigned MOVIncr = IsMax ? MOVN : MOVZ;
782
783 // unsigned: sltu Scratch2, oldVal, Incr
784 // signed: slt Scratch2, oldVal, Incr
785 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SLTScratch2), DestReg: Scratch2_32)
786 .addReg(RegNo: OldVal)
787 .addReg(RegNo: Incr);
788
789 if (STI->hasMips64r6() || STI->hasMips32r6()) {
790 // max: seleqz Scratch, OldVal, Scratch2
791 // selnez Scratch2, Incr, Scratch2
792 // or Scratch, Scratch, Scratch2
793 // min: selnez Scratch, OldVal, Scratch2
794 // seleqz Scratch2, Incr, Scratch2
795 // or Scratch, Scratch, Scratch2
796 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELOldVal), DestReg: Scratch)
797 .addReg(RegNo: OldVal)
798 .addReg(RegNo: Scratch2);
799 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELIncr), DestReg: Scratch2)
800 .addReg(RegNo: Incr)
801 .addReg(RegNo: Scratch2);
802 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch)
803 .addReg(RegNo: Scratch)
804 .addReg(RegNo: Scratch2);
805 } else {
806 // max: move Scratch, OldVal
807 // movn Scratch, Incr, Scratch2, Scratch
808 // min: move Scratch, OldVal
809 // movz Scratch, Incr, Scratch2, Scratch
810 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch)
811 .addReg(RegNo: OldVal)
812 .addReg(RegNo: ZERO);
813 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: MOVIncr), DestReg: Scratch)
814 .addReg(RegNo: Incr)
815 .addReg(RegNo: Scratch2)
816 .addReg(RegNo: Scratch);
817 }
818
819 } else if (Opcode) {
820 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode), DestReg: Scratch).addReg(RegNo: OldVal).addReg(RegNo: Incr);
821 } else if (IsNand) {
822 assert(AND && NOR &&
823 "Unknown nand instruction for atomic pseudo expansion");
824 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: AND), DestReg: Scratch).addReg(RegNo: OldVal).addReg(RegNo: Incr);
825 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: NOR), DestReg: Scratch).addReg(RegNo: ZERO).addReg(RegNo: Scratch);
826 } else {
827 assert(IsOr && OR && "Unknown instruction for atomic pseudo expansion!");
828 (void)IsOr;
829 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch).addReg(RegNo: Incr).addReg(RegNo: ZERO);
830 }
831
832 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch)
833 .addReg(RegNo: Scratch)
834 .addReg(RegNo: Ptr)
835 .addImm(Val: 0);
836 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
837 .addReg(RegNo: Scratch)
838 .addReg(RegNo: ZERO)
839 .addMBB(MBB: loopMBB);
840
841 NMBBI = BB.end();
842 I->eraseFromParent();
843
844 LivePhysRegs LiveRegs;
845 computeAndAddLiveIns(LiveRegs, MBB&: *loopMBB);
846 computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB);
847
848 return true;
849}
850
851bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB,
852 MachineBasicBlock::iterator MBBI,
853 MachineBasicBlock::iterator &NMBB) {
854
855 bool Modified = false;
856
857 switch (MBBI->getOpcode()) {
858 case Mips::ATOMIC_CMP_SWAP_I32_POSTRA:
859 case Mips::ATOMIC_CMP_SWAP_I64_POSTRA:
860 return expandAtomicCmpSwap(BB&: MBB, I: MBBI, NMBBI&: NMBB);
861 case Mips::ATOMIC_CMP_SWAP_I8_POSTRA:
862 case Mips::ATOMIC_CMP_SWAP_I16_POSTRA:
863 return expandAtomicCmpSwapSubword(BB&: MBB, I: MBBI, NMBBI&: NMBB);
864 case Mips::ATOMIC_SWAP_I8_POSTRA:
865 case Mips::ATOMIC_SWAP_I16_POSTRA:
866 case Mips::ATOMIC_LOAD_NAND_I8_POSTRA:
867 case Mips::ATOMIC_LOAD_NAND_I16_POSTRA:
868 case Mips::ATOMIC_LOAD_ADD_I8_POSTRA:
869 case Mips::ATOMIC_LOAD_ADD_I16_POSTRA:
870 case Mips::ATOMIC_LOAD_SUB_I8_POSTRA:
871 case Mips::ATOMIC_LOAD_SUB_I16_POSTRA:
872 case Mips::ATOMIC_LOAD_AND_I8_POSTRA:
873 case Mips::ATOMIC_LOAD_AND_I16_POSTRA:
874 case Mips::ATOMIC_LOAD_OR_I8_POSTRA:
875 case Mips::ATOMIC_LOAD_OR_I16_POSTRA:
876 case Mips::ATOMIC_LOAD_XOR_I8_POSTRA:
877 case Mips::ATOMIC_LOAD_XOR_I16_POSTRA:
878 case Mips::ATOMIC_LOAD_MIN_I8_POSTRA:
879 case Mips::ATOMIC_LOAD_MIN_I16_POSTRA:
880 case Mips::ATOMIC_LOAD_MAX_I8_POSTRA:
881 case Mips::ATOMIC_LOAD_MAX_I16_POSTRA:
882 case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA:
883 case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA:
884 case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA:
885 case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA:
886 return expandAtomicBinOpSubword(BB&: MBB, I: MBBI, NMBBI&: NMBB);
887 case Mips::ATOMIC_LOAD_ADD_I32_POSTRA:
888 case Mips::ATOMIC_LOAD_SUB_I32_POSTRA:
889 case Mips::ATOMIC_LOAD_AND_I32_POSTRA:
890 case Mips::ATOMIC_LOAD_OR_I32_POSTRA:
891 case Mips::ATOMIC_LOAD_XOR_I32_POSTRA:
892 case Mips::ATOMIC_LOAD_NAND_I32_POSTRA:
893 case Mips::ATOMIC_SWAP_I32_POSTRA:
894 case Mips::ATOMIC_LOAD_MIN_I32_POSTRA:
895 case Mips::ATOMIC_LOAD_MAX_I32_POSTRA:
896 case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA:
897 case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA:
898 return expandAtomicBinOp(BB&: MBB, I: MBBI, NMBBI&: NMBB, Size: 4);
899 case Mips::ATOMIC_LOAD_ADD_I64_POSTRA:
900 case Mips::ATOMIC_LOAD_SUB_I64_POSTRA:
901 case Mips::ATOMIC_LOAD_AND_I64_POSTRA:
902 case Mips::ATOMIC_LOAD_OR_I64_POSTRA:
903 case Mips::ATOMIC_LOAD_XOR_I64_POSTRA:
904 case Mips::ATOMIC_LOAD_NAND_I64_POSTRA:
905 case Mips::ATOMIC_SWAP_I64_POSTRA:
906 case Mips::ATOMIC_LOAD_MIN_I64_POSTRA:
907 case Mips::ATOMIC_LOAD_MAX_I64_POSTRA:
908 case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA:
909 case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA:
910 return expandAtomicBinOp(BB&: MBB, I: MBBI, NMBBI&: NMBB, Size: 8);
911 default:
912 return Modified;
913 }
914}
915
916bool MipsExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
917 bool Modified = false;
918
919 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
920 while (MBBI != E) {
921 MachineBasicBlock::iterator NMBBI = std::next(x: MBBI);
922 Modified |= expandMI(MBB, MBBI, NMBB&: NMBBI);
923 MBBI = NMBBI;
924 }
925
926 return Modified;
927}
928
929bool MipsExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
930 STI = &MF.getSubtarget<MipsSubtarget>();
931 TII = STI->getInstrInfo();
932
933 bool Modified = false;
934 for (MachineBasicBlock &MBB : MF)
935 Modified |= expandMBB(MBB);
936
937 if (Modified)
938 MF.RenumberBlocks();
939
940 return Modified;
941}
942
943/// createMipsExpandPseudoPass - returns an instance of the pseudo instruction
944/// expansion pass.
945FunctionPass *llvm::createMipsExpandPseudoPass() {
946 return new MipsExpandPseudo();
947}
948