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 bool NoMovnInstr = (IsMin || IsMax) && !STI->hasMips4() && !STI->hasMips32();
436
437 const BasicBlock *LLVM_BB = BB.getBasicBlock();
438 MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
439 MachineBasicBlock *loop1MBB = nullptr;
440 MachineBasicBlock *loop2MBB = nullptr;
441 if (NoMovnInstr) {
442 loop1MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
443 loop2MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
444 }
445 MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
446 MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
447 MachineFunction::iterator It = ++BB.getIterator();
448 MF->insert(MBBI: It, MBB: loopMBB);
449 if (NoMovnInstr) {
450 MF->insert(MBBI: It, MBB: loop1MBB);
451 MF->insert(MBBI: It, MBB: loop2MBB);
452 }
453 MF->insert(MBBI: It, MBB: sinkMBB);
454 MF->insert(MBBI: It, MBB: exitMBB);
455
456 exitMBB->splice(Where: exitMBB->begin(), Other: &BB, From: std::next(x: I), To: BB.end());
457 exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB);
458
459 BB.addSuccessor(Succ: loopMBB, Prob: BranchProbability::getOne());
460 if (NoMovnInstr) {
461 loopMBB->addSuccessor(Succ: loop1MBB);
462 loopMBB->addSuccessor(Succ: loop2MBB);
463 } else {
464 loopMBB->addSuccessor(Succ: sinkMBB);
465 loopMBB->addSuccessor(Succ: loopMBB);
466 loopMBB->normalizeSuccProbs();
467 }
468 if (NoMovnInstr) {
469 loop1MBB->addSuccessor(Succ: loop2MBB);
470 loop2MBB->addSuccessor(Succ: loopMBB);
471 loop2MBB->addSuccessor(Succ: sinkMBB);
472 }
473
474 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: OldVal).addReg(RegNo: Ptr).addImm(Val: 0);
475 if (IsNand) {
476 // and andres, oldval, incr2
477 // nor binopres, $0, andres
478 // and newval, binopres, mask
479 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
480 .addReg(RegNo: OldVal)
481 .addReg(RegNo: Incr);
482 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::NOR), DestReg: BinOpRes)
483 .addReg(RegNo: Mips::ZERO)
484 .addReg(RegNo: BinOpRes);
485 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
486 .addReg(RegNo: BinOpRes)
487 .addReg(RegNo: Mask);
488 } else if (IsMin || IsMax) {
489
490 assert(I->getNumOperands() == 10 &&
491 "Atomics min|max|umin|umax use an additional register");
492 Register Scratch4 = I->getOperand(i: 9).getReg();
493
494 unsigned SLTScratch4 = IsUnsigned ? SLTu : SLT;
495 unsigned SELIncr = IsMax ? SELNEZ : SELEQZ;
496 unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ;
497 unsigned MOVIncr = IsMax ? MOVN : MOVZ;
498
499 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRAV), DestReg: StoreVal)
500 .addReg(RegNo: OldVal)
501 .addReg(RegNo: ShiftAmnt);
502 if (IsUnsigned) {
503 const unsigned OpMask = SEOp == Mips::SEH ? 0xffff : 0xff;
504 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::ANDi), DestReg: StoreVal)
505 .addReg(RegNo: StoreVal)
506 .addImm(Val: OpMask);
507 } else if (STI->hasMips32r2()) {
508 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: StoreVal).addReg(RegNo: StoreVal);
509 } else {
510 const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24;
511 const unsigned SROp = IsUnsigned ? Mips::SRL : Mips::SRA;
512 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: StoreVal)
513 .addReg(RegNo: StoreVal, Flags: RegState::Kill)
514 .addImm(Val: ShiftImm);
515 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SROp), DestReg: StoreVal)
516 .addReg(RegNo: StoreVal, Flags: RegState::Kill)
517 .addImm(Val: ShiftImm);
518 }
519 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: Dest)
520 .addReg(RegNo: Mips::ZERO)
521 .addReg(RegNo: StoreVal);
522 DestOK = true;
523 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLLV), DestReg: StoreVal)
524 .addReg(RegNo: StoreVal)
525 .addReg(RegNo: ShiftAmnt);
526
527 // unsigned: sltu Scratch4, StoreVal, Incr
528 // signed: slt Scratch4, StoreVal, Incr
529 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SLTScratch4), DestReg: Scratch4)
530 .addReg(RegNo: StoreVal)
531 .addReg(RegNo: Incr);
532
533 if (STI->hasMips64r6() || STI->hasMips32r6()) {
534 // max: seleqz BinOpRes, OldVal, Scratch4
535 // selnez Scratch4, Incr, Scratch4
536 // or BinOpRes, BinOpRes, Scratch4
537 // min: selnqz BinOpRes, OldVal, Scratch4
538 // seleqz Scratch4, Incr, Scratch4
539 // or BinOpRes, BinOpRes, Scratch4
540 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELOldVal), DestReg: BinOpRes)
541 .addReg(RegNo: StoreVal)
542 .addReg(RegNo: Scratch4);
543 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELIncr), DestReg: Scratch4)
544 .addReg(RegNo: Incr)
545 .addReg(RegNo: Scratch4);
546 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
547 .addReg(RegNo: BinOpRes)
548 .addReg(RegNo: Scratch4);
549 } else if (STI->hasMips4() || STI->hasMips32()) {
550 // max: move BinOpRes, StoreVal
551 // movn BinOpRes, Incr, Scratch4, BinOpRes
552 // min: move BinOpRes, StoreVal
553 // movz BinOpRes, Incr, Scratch4, BinOpRes
554 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
555 .addReg(RegNo: StoreVal)
556 .addReg(RegNo: Mips::ZERO);
557 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: MOVIncr), DestReg: BinOpRes)
558 .addReg(RegNo: Incr)
559 .addReg(RegNo: Scratch4)
560 .addReg(RegNo: BinOpRes);
561 } else {
562 // if min:
563 // loopMBB: move BinOpRes, StoreVal
564 // beq Scratch4, 0, loop1MBB
565 // j loop2MBB
566 // loop1MBB: move BinOpRes, Incr
567 // loop2MBB: and BinOpRes, BinOpRes, Mask
568 // and StoreVal, OlddVal, Mask2
569 // or StoreVal, StoreVal, BinOpRes
570 // StoreVal<tied1> = sc StoreVal, 0(Ptr)
571 // beq StoreVal, zero, loopMBB
572 //
573 // if max:
574 // loopMBB: move BinOpRes, Incr
575 // beq Scratch4, 0, loop1MBB
576 // j loop2MBB
577 // loop1MBB: move BinOpRes, StoreVal
578 // loop2MBB: and BinOpRes, BinOpRes, Mask
579 // and StoreVal, OlddVal, Mask2
580 // or StoreVal, StoreVal, BinOpRes
581 // StoreVal<tied1> = sc StoreVal, 0(Ptr)
582 // beq StoreVal, zero, loopMBB
583 if (IsMin) {
584 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
585 .addReg(RegNo: StoreVal)
586 .addReg(RegNo: Mips::ZERO);
587 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
588 .addReg(RegNo: Incr)
589 .addReg(RegNo: Mips::ZERO);
590 } else {
591 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
592 .addReg(RegNo: Incr)
593 .addReg(RegNo: Mips::ZERO);
594 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes)
595 .addReg(RegNo: StoreVal)
596 .addReg(RegNo: Mips::ZERO);
597 }
598 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
599 .addReg(RegNo: Scratch4)
600 .addReg(RegNo: Mips::ZERO)
601 .addMBB(MBB: loop1MBB);
602 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::J)).addMBB(MBB: loop2MBB);
603 }
604
605 // and BinOpRes, BinOpRes, Mask
606 if (NoMovnInstr)
607 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
608 .addReg(RegNo: BinOpRes)
609 .addReg(RegNo: Mask);
610 else
611 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
612 .addReg(RegNo: BinOpRes)
613 .addReg(RegNo: Mask);
614
615 } else if (!IsSwap) {
616 // <binop> binopres, oldval, incr2
617 // and newval, binopres, mask
618 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode), DestReg: BinOpRes)
619 .addReg(RegNo: OldVal)
620 .addReg(RegNo: Incr);
621 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
622 .addReg(RegNo: BinOpRes)
623 .addReg(RegNo: Mask);
624 } else { // atomic.swap
625 // and newval, incr2, mask
626 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes)
627 .addReg(RegNo: Incr)
628 .addReg(RegNo: Mask);
629 }
630
631 // and StoreVal, OlddVal, Mask2
632 // or StoreVal, StoreVal, BinOpRes
633 // StoreVal<tied1> = sc StoreVal, 0(Ptr)
634 // beq StoreVal, zero, loopMBB
635 if (NoMovnInstr) {
636 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: StoreVal)
637 .addReg(RegNo: OldVal)
638 .addReg(RegNo: Mask2);
639 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: StoreVal)
640 .addReg(RegNo: StoreVal)
641 .addReg(RegNo: BinOpRes);
642 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: StoreVal)
643 .addReg(RegNo: StoreVal)
644 .addReg(RegNo: Ptr)
645 .addImm(Val: 0);
646 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
647 .addReg(RegNo: StoreVal)
648 .addReg(RegNo: Mips::ZERO)
649 .addMBB(MBB: loopMBB);
650 } else {
651 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: StoreVal)
652 .addReg(RegNo: OldVal)
653 .addReg(RegNo: Mask2);
654 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: StoreVal)
655 .addReg(RegNo: StoreVal)
656 .addReg(RegNo: BinOpRes);
657 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: StoreVal)
658 .addReg(RegNo: StoreVal)
659 .addReg(RegNo: Ptr)
660 .addImm(Val: 0);
661 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
662 .addReg(RegNo: StoreVal)
663 .addReg(RegNo: Mips::ZERO)
664 .addMBB(MBB: loopMBB);
665 }
666
667 // sinkMBB:
668 // and maskedoldval1,oldval,mask
669 // srl srlres,maskedoldval1,shiftamt
670 // sign_extend dest,srlres
671
672 if (!DestOK) {
673 sinkMBB->addSuccessor(Succ: exitMBB, Prob: BranchProbability::getOne());
674 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: Dest).addReg(RegNo: OldVal).addReg(RegNo: Mask);
675 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRLV), DestReg: Dest)
676 .addReg(RegNo: Dest)
677 .addReg(RegNo: ShiftAmnt);
678
679 if (STI->hasMips32r2()) {
680 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: Dest).addReg(RegNo: Dest);
681 } else {
682 const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24;
683 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: Dest)
684 .addReg(RegNo: Dest, Flags: RegState::Kill)
685 .addImm(Val: ShiftImm);
686 BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRA), DestReg: Dest)
687 .addReg(RegNo: Dest, Flags: RegState::Kill)
688 .addImm(Val: ShiftImm);
689 }
690 }
691
692 LivePhysRegs LiveRegs;
693 computeAndAddLiveIns(LiveRegs, MBB&: *loopMBB);
694 if (loop1MBB) {
695 assert(loop2MBB && "should have 2 loop blocks");
696 computeAndAddLiveIns(LiveRegs, MBB&: *loop1MBB);
697 computeAndAddLiveIns(LiveRegs, MBB&: *loop2MBB);
698 }
699 computeAndAddLiveIns(LiveRegs, MBB&: *sinkMBB);
700 computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB);
701
702 NMBBI = BB.end();
703 I->eraseFromParent();
704
705 return true;
706}
707
708bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB,
709 MachineBasicBlock::iterator I,
710 MachineBasicBlock::iterator &NMBBI,
711 unsigned Size) {
712 MachineFunction *MF = BB.getParent();
713
714 const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
715 DebugLoc DL = I->getDebugLoc();
716
717 unsigned LL, SC, ZERO, BEQ, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ;
718
719 if (Size == 4) {
720 if (STI->inMicroMipsMode()) {
721 LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
722 SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
723 BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
724 SLT = Mips::SLT_MM;
725 SLTu = Mips::SLTu_MM;
726 OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM;
727 MOVN = Mips::MOVN_I_MM;
728 MOVZ = Mips::MOVZ_I_MM;
729 SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ;
730 SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ;
731 } else {
732 LL = STI->hasMips32r6()
733 ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
734 : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
735 SC = STI->hasMips32r6()
736 ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
737 : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
738 BEQ = Mips::BEQ;
739 SLT = Mips::SLT;
740 SLTu = Mips::SLTu;
741 OR = Mips::OR;
742 MOVN = Mips::MOVN_I_I;
743 MOVZ = Mips::MOVZ_I_I;
744 SELNEZ = Mips::SELNEZ;
745 SELEQZ = Mips::SELEQZ;
746 }
747
748 ZERO = Mips::ZERO;
749 } else {
750 LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD;
751 SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD;
752 ZERO = Mips::ZERO_64;
753 BEQ = Mips::BEQ64;
754 SLT = Mips::SLT64;
755 SLTu = Mips::SLTu64;
756 OR = Mips::OR64;
757 MOVN = Mips::MOVN_I64_I64;
758 MOVZ = Mips::MOVZ_I64_I64;
759 SELNEZ = Mips::SELNEZ64;
760 SELEQZ = Mips::SELEQZ64;
761 }
762
763 Register OldVal = I->getOperand(i: 0).getReg();
764 Register Ptr = I->getOperand(i: 1).getReg();
765 Register Incr = I->getOperand(i: 2).getReg();
766 Register Scratch = I->getOperand(i: 3).getReg();
767
768 unsigned Opcode = 0;
769 unsigned AND = 0;
770 unsigned NOR = 0;
771
772 bool IsOr = false;
773 bool IsNand = false;
774 bool IsMin = false;
775 bool IsMax = false;
776 bool IsUnsigned = false;
777
778 switch (I->getOpcode()) {
779 case Mips::ATOMIC_LOAD_ADD_I32_POSTRA:
780 Opcode = Mips::ADDu;
781 break;
782 case Mips::ATOMIC_LOAD_SUB_I32_POSTRA:
783 Opcode = Mips::SUBu;
784 break;
785 case Mips::ATOMIC_LOAD_AND_I32_POSTRA:
786 Opcode = Mips::AND;
787 break;
788 case Mips::ATOMIC_LOAD_OR_I32_POSTRA:
789 Opcode = Mips::OR;
790 break;
791 case Mips::ATOMIC_LOAD_XOR_I32_POSTRA:
792 Opcode = Mips::XOR;
793 break;
794 case Mips::ATOMIC_LOAD_NAND_I32_POSTRA:
795 IsNand = true;
796 AND = Mips::AND;
797 NOR = Mips::NOR;
798 break;
799 case Mips::ATOMIC_SWAP_I32_POSTRA:
800 IsOr = true;
801 break;
802 case Mips::ATOMIC_LOAD_ADD_I64_POSTRA:
803 Opcode = Mips::DADDu;
804 break;
805 case Mips::ATOMIC_LOAD_SUB_I64_POSTRA:
806 Opcode = Mips::DSUBu;
807 break;
808 case Mips::ATOMIC_LOAD_AND_I64_POSTRA:
809 Opcode = Mips::AND64;
810 break;
811 case Mips::ATOMIC_LOAD_OR_I64_POSTRA:
812 Opcode = Mips::OR64;
813 break;
814 case Mips::ATOMIC_LOAD_XOR_I64_POSTRA:
815 Opcode = Mips::XOR64;
816 break;
817 case Mips::ATOMIC_LOAD_NAND_I64_POSTRA:
818 IsNand = true;
819 AND = Mips::AND64;
820 NOR = Mips::NOR64;
821 break;
822 case Mips::ATOMIC_SWAP_I64_POSTRA:
823 IsOr = true;
824 break;
825 case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA:
826 case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA:
827 IsUnsigned = true;
828 [[fallthrough]];
829 case Mips::ATOMIC_LOAD_MIN_I32_POSTRA:
830 case Mips::ATOMIC_LOAD_MIN_I64_POSTRA:
831 IsMin = true;
832 break;
833 case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA:
834 case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA:
835 IsUnsigned = true;
836 [[fallthrough]];
837 case Mips::ATOMIC_LOAD_MAX_I32_POSTRA:
838 case Mips::ATOMIC_LOAD_MAX_I64_POSTRA:
839 IsMax = true;
840 break;
841 default:
842 llvm_unreachable("Unknown pseudo atomic!");
843 }
844
845 bool NoMovnInstr = (IsMin || IsMax) && !STI->hasMips4() && !STI->hasMips32();
846 const BasicBlock *LLVM_BB = BB.getBasicBlock();
847 MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
848 MachineBasicBlock *loop1MBB = nullptr;
849 MachineBasicBlock *loop2MBB = nullptr;
850 if (NoMovnInstr) {
851 loop1MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
852 loop2MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
853 }
854 MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB);
855 MachineFunction::iterator It = ++BB.getIterator();
856 MF->insert(MBBI: It, MBB: loopMBB);
857 if (NoMovnInstr) {
858 MF->insert(MBBI: It, MBB: loop1MBB);
859 MF->insert(MBBI: It, MBB: loop2MBB);
860 }
861 MF->insert(MBBI: It, MBB: exitMBB);
862
863 exitMBB->splice(Where: exitMBB->begin(), Other: &BB, From: std::next(x: I), To: BB.end());
864 exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB);
865
866 BB.addSuccessor(Succ: loopMBB, Prob: BranchProbability::getOne());
867 if (NoMovnInstr) {
868 loopMBB->addSuccessor(Succ: loop1MBB);
869 loopMBB->addSuccessor(Succ: loop2MBB);
870 } else {
871 loopMBB->addSuccessor(Succ: exitMBB);
872 loopMBB->addSuccessor(Succ: loopMBB);
873 }
874 loopMBB->normalizeSuccProbs();
875 if (NoMovnInstr) {
876 loop1MBB->addSuccessor(Succ: loop2MBB);
877 loop2MBB->addSuccessor(Succ: loopMBB);
878 loop2MBB->addSuccessor(Succ: exitMBB);
879 }
880
881 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: OldVal).addReg(RegNo: Ptr).addImm(Val: 0);
882 assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!");
883 assert((OldVal != Incr) && "Clobbered the wrong reg!");
884 if (IsMin || IsMax) {
885
886 assert(I->getNumOperands() == 5 &&
887 "Atomics min|max|umin|umax use an additional register");
888 MCRegister Scratch2 = I->getOperand(i: 4).getReg().asMCReg();
889
890 // On Mips64 result of slt is GPR32.
891 MCRegister Scratch2_32 =
892 (Size == 8) ? STI->getRegisterInfo()->getSubReg(Reg: Scratch2, Idx: Mips::sub_32)
893 : Scratch2;
894
895 unsigned SLTScratch2 = IsUnsigned ? SLTu : SLT;
896 unsigned SELIncr = IsMax ? SELNEZ : SELEQZ;
897 unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ;
898 unsigned MOVIncr = IsMax ? MOVN : MOVZ;
899
900 // unsigned: sltu Scratch2, oldVal, Incr
901 // signed: slt Scratch2, oldVal, Incr
902 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SLTScratch2), DestReg: Scratch2_32)
903 .addReg(RegNo: OldVal)
904 .addReg(RegNo: Incr);
905
906 if (STI->hasMips64r6() || STI->hasMips32r6()) {
907 // max: seleqz Scratch, OldVal, Scratch2
908 // selnez Scratch2, Incr, Scratch2
909 // or Scratch, Scratch, Scratch2
910 // min: selnez Scratch, OldVal, Scratch2
911 // seleqz Scratch2, Incr, Scratch2
912 // or Scratch, Scratch, Scratch2
913 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELOldVal), DestReg: Scratch)
914 .addReg(RegNo: OldVal)
915 .addReg(RegNo: Scratch2);
916 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELIncr), DestReg: Scratch2)
917 .addReg(RegNo: Incr)
918 .addReg(RegNo: Scratch2);
919 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch)
920 .addReg(RegNo: Scratch)
921 .addReg(RegNo: Scratch2);
922 } else if (STI->hasMips4() || STI->hasMips32()) {
923 // max: move Scratch, OldVal
924 // movn Scratch, Incr, Scratch2, Scratch
925 // min: move Scratch, OldVal
926 // movz Scratch, Incr, Scratch2, Scratch
927 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch)
928 .addReg(RegNo: OldVal)
929 .addReg(RegNo: ZERO);
930 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: MOVIncr), DestReg: Scratch)
931 .addReg(RegNo: Incr)
932 .addReg(RegNo: Scratch2)
933 .addReg(RegNo: Scratch);
934 } else {
935 // if min:
936 // loopMBB: move Scratch, OldVal
937 // beq Scratch2_32, 0, loop1MBB
938 // j loop2MBB
939 // loop1MBB: move Scratch, Incr
940 // loop2MBB: sc $2, 0($4)
941 // beqz $2, $BB0_1
942 // nop
943 //
944 // if max:
945 // loopMBB: move Scratch, Incr
946 // beq Scratch2_32, 0, loop1MBB
947 // j loop2MBB
948 // loop1MBB: move Scratch, OldVal
949 // loop2MBB: sc $2, 0($4)
950 // beqz $2, $BB0_1
951 // nop
952 if (IsMin) {
953 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch).addReg(RegNo: OldVal).addReg(RegNo: ZERO);
954 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch).addReg(RegNo: Incr).addReg(RegNo: ZERO);
955 } else {
956 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch).addReg(RegNo: Incr).addReg(RegNo: ZERO);
957 BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch)
958 .addReg(RegNo: OldVal)
959 .addReg(RegNo: ZERO);
960 }
961 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
962 .addReg(RegNo: Scratch2_32)
963 .addReg(RegNo: ZERO)
964 .addMBB(MBB: loop1MBB);
965 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::J)).addMBB(MBB: loop2MBB);
966 }
967
968 } else if (Opcode) {
969 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode), DestReg: Scratch).addReg(RegNo: OldVal).addReg(RegNo: Incr);
970 } else if (IsNand) {
971 assert(AND && NOR &&
972 "Unknown nand instruction for atomic pseudo expansion");
973 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: AND), DestReg: Scratch).addReg(RegNo: OldVal).addReg(RegNo: Incr);
974 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: NOR), DestReg: Scratch).addReg(RegNo: ZERO).addReg(RegNo: Scratch);
975 } else {
976 assert(IsOr && OR && "Unknown instruction for atomic pseudo expansion!");
977 (void)IsOr;
978 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch).addReg(RegNo: Incr).addReg(RegNo: ZERO);
979 }
980
981 if (NoMovnInstr) {
982 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch)
983 .addReg(RegNo: Scratch)
984 .addReg(RegNo: Ptr)
985 .addImm(Val: 0);
986 BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
987 .addReg(RegNo: Scratch)
988 .addReg(RegNo: ZERO)
989 .addMBB(MBB: loopMBB);
990 } else {
991 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch)
992 .addReg(RegNo: Scratch)
993 .addReg(RegNo: Ptr)
994 .addImm(Val: 0);
995 BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ))
996 .addReg(RegNo: Scratch)
997 .addReg(RegNo: ZERO)
998 .addMBB(MBB: loopMBB);
999 }
1000
1001 NMBBI = BB.end();
1002 I->eraseFromParent();
1003
1004 LivePhysRegs LiveRegs;
1005 computeAndAddLiveIns(LiveRegs, MBB&: *loopMBB);
1006 if (loop1MBB) {
1007 assert(loop2MBB && "should have 2 loop blocks");
1008 computeAndAddLiveIns(LiveRegs, MBB&: *loop1MBB);
1009 computeAndAddLiveIns(LiveRegs, MBB&: *loop2MBB);
1010 }
1011 computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB);
1012
1013 return true;
1014}
1015
1016bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB,
1017 MachineBasicBlock::iterator MBBI,
1018 MachineBasicBlock::iterator &NMBB) {
1019
1020 bool Modified = false;
1021
1022 switch (MBBI->getOpcode()) {
1023 case Mips::ATOMIC_CMP_SWAP_I32_POSTRA:
1024 case Mips::ATOMIC_CMP_SWAP_I64_POSTRA:
1025 return expandAtomicCmpSwap(BB&: MBB, I: MBBI, NMBBI&: NMBB);
1026 case Mips::ATOMIC_CMP_SWAP_I8_POSTRA:
1027 case Mips::ATOMIC_CMP_SWAP_I16_POSTRA:
1028 return expandAtomicCmpSwapSubword(BB&: MBB, I: MBBI, NMBBI&: NMBB);
1029 case Mips::ATOMIC_SWAP_I8_POSTRA:
1030 case Mips::ATOMIC_SWAP_I16_POSTRA:
1031 case Mips::ATOMIC_LOAD_NAND_I8_POSTRA:
1032 case Mips::ATOMIC_LOAD_NAND_I16_POSTRA:
1033 case Mips::ATOMIC_LOAD_ADD_I8_POSTRA:
1034 case Mips::ATOMIC_LOAD_ADD_I16_POSTRA:
1035 case Mips::ATOMIC_LOAD_SUB_I8_POSTRA:
1036 case Mips::ATOMIC_LOAD_SUB_I16_POSTRA:
1037 case Mips::ATOMIC_LOAD_AND_I8_POSTRA:
1038 case Mips::ATOMIC_LOAD_AND_I16_POSTRA:
1039 case Mips::ATOMIC_LOAD_OR_I8_POSTRA:
1040 case Mips::ATOMIC_LOAD_OR_I16_POSTRA:
1041 case Mips::ATOMIC_LOAD_XOR_I8_POSTRA:
1042 case Mips::ATOMIC_LOAD_XOR_I16_POSTRA:
1043 case Mips::ATOMIC_LOAD_MIN_I8_POSTRA:
1044 case Mips::ATOMIC_LOAD_MIN_I16_POSTRA:
1045 case Mips::ATOMIC_LOAD_MAX_I8_POSTRA:
1046 case Mips::ATOMIC_LOAD_MAX_I16_POSTRA:
1047 case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA:
1048 case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA:
1049 case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA:
1050 case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA:
1051 return expandAtomicBinOpSubword(BB&: MBB, I: MBBI, NMBBI&: NMBB);
1052 case Mips::ATOMIC_LOAD_ADD_I32_POSTRA:
1053 case Mips::ATOMIC_LOAD_SUB_I32_POSTRA:
1054 case Mips::ATOMIC_LOAD_AND_I32_POSTRA:
1055 case Mips::ATOMIC_LOAD_OR_I32_POSTRA:
1056 case Mips::ATOMIC_LOAD_XOR_I32_POSTRA:
1057 case Mips::ATOMIC_LOAD_NAND_I32_POSTRA:
1058 case Mips::ATOMIC_SWAP_I32_POSTRA:
1059 case Mips::ATOMIC_LOAD_MIN_I32_POSTRA:
1060 case Mips::ATOMIC_LOAD_MAX_I32_POSTRA:
1061 case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA:
1062 case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA:
1063 return expandAtomicBinOp(BB&: MBB, I: MBBI, NMBBI&: NMBB, Size: 4);
1064 case Mips::ATOMIC_LOAD_ADD_I64_POSTRA:
1065 case Mips::ATOMIC_LOAD_SUB_I64_POSTRA:
1066 case Mips::ATOMIC_LOAD_AND_I64_POSTRA:
1067 case Mips::ATOMIC_LOAD_OR_I64_POSTRA:
1068 case Mips::ATOMIC_LOAD_XOR_I64_POSTRA:
1069 case Mips::ATOMIC_LOAD_NAND_I64_POSTRA:
1070 case Mips::ATOMIC_SWAP_I64_POSTRA:
1071 case Mips::ATOMIC_LOAD_MIN_I64_POSTRA:
1072 case Mips::ATOMIC_LOAD_MAX_I64_POSTRA:
1073 case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA:
1074 case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA:
1075 return expandAtomicBinOp(BB&: MBB, I: MBBI, NMBBI&: NMBB, Size: 8);
1076 default:
1077 return Modified;
1078 }
1079}
1080
1081bool MipsExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
1082 bool Modified = false;
1083
1084 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1085 while (MBBI != E) {
1086 MachineBasicBlock::iterator NMBBI = std::next(x: MBBI);
1087 Modified |= expandMI(MBB, MBBI, NMBB&: NMBBI);
1088 MBBI = NMBBI;
1089 }
1090
1091 return Modified;
1092}
1093
1094bool MipsExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
1095 STI = &MF.getSubtarget<MipsSubtarget>();
1096 TII = STI->getInstrInfo();
1097
1098 bool Modified = false;
1099 for (MachineBasicBlock &MBB : MF)
1100 Modified |= expandMBB(MBB);
1101
1102 if (Modified)
1103 MF.RenumberBlocks();
1104
1105 return Modified;
1106}
1107
1108/// createMipsExpandPseudoPass - returns an instance of the pseudo instruction
1109/// expansion pass.
1110FunctionPass *llvm::createMipsExpandPseudoPass() {
1111 return new MipsExpandPseudo();
1112}
1113