Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / lib / Target / LoongArch / LoongArchExpandAtomicPseudoInsts.cpp
blob18a532b55ee5a924f13a9b3af5d3f514aea64563
1 //==- LoongArchExpandAtomicPseudoInsts.cpp - Expand atomic pseudo instrs. -===//
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 atomic pseudo instructions into
10 // target instructions. This pass should be run at the last possible moment,
11 // avoiding the possibility for other passes to break the requirements for
12 // forward progress in the LL/SC block.
14 //===----------------------------------------------------------------------===//
16 #include "LoongArch.h"
17 #include "LoongArchInstrInfo.h"
18 #include "LoongArchTargetMachine.h"
20 #include "llvm/CodeGen/LivePhysRegs.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 using namespace llvm;
26 #define LoongArch_EXPAND_ATOMIC_PSEUDO_NAME \
27 "LoongArch atomic pseudo instruction expansion pass"
29 namespace {
31 class LoongArchExpandAtomicPseudo : public MachineFunctionPass {
32 public:
33 const LoongArchInstrInfo *TII;
34 static char ID;
36 LoongArchExpandAtomicPseudo() : MachineFunctionPass(ID) {
37 initializeLoongArchExpandAtomicPseudoPass(*PassRegistry::getPassRegistry());
40 bool runOnMachineFunction(MachineFunction &MF) override;
42 StringRef getPassName() const override {
43 return LoongArch_EXPAND_ATOMIC_PSEUDO_NAME;
46 private:
47 bool expandMBB(MachineBasicBlock &MBB);
48 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
49 MachineBasicBlock::iterator &NextMBBI);
50 bool expandAtomicBinOp(MachineBasicBlock &MBB,
51 MachineBasicBlock::iterator MBBI, AtomicRMWInst::BinOp,
52 bool IsMasked, int Width,
53 MachineBasicBlock::iterator &NextMBBI);
54 bool expandAtomicMinMaxOp(MachineBasicBlock &MBB,
55 MachineBasicBlock::iterator MBBI,
56 AtomicRMWInst::BinOp, bool IsMasked, int Width,
57 MachineBasicBlock::iterator &NextMBBI);
58 bool expandAtomicCmpXchg(MachineBasicBlock &MBB,
59 MachineBasicBlock::iterator MBBI, bool IsMasked,
60 int Width, MachineBasicBlock::iterator &NextMBBI);
63 char LoongArchExpandAtomicPseudo::ID = 0;
65 bool LoongArchExpandAtomicPseudo::runOnMachineFunction(MachineFunction &MF) {
66 TII =
67 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
68 bool Modified = false;
69 for (auto &MBB : MF)
70 Modified |= expandMBB(MBB);
71 return Modified;
74 bool LoongArchExpandAtomicPseudo::expandMBB(MachineBasicBlock &MBB) {
75 bool Modified = false;
77 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
78 while (MBBI != E) {
79 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
80 Modified |= expandMI(MBB, MBBI, NMBBI);
81 MBBI = NMBBI;
84 return Modified;
87 bool LoongArchExpandAtomicPseudo::expandMI(
88 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
89 MachineBasicBlock::iterator &NextMBBI) {
90 switch (MBBI->getOpcode()) {
91 case LoongArch::PseudoMaskedAtomicSwap32:
92 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, true, 32,
93 NextMBBI);
94 case LoongArch::PseudoAtomicSwap32:
95 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, false, 32,
96 NextMBBI);
97 case LoongArch::PseudoMaskedAtomicLoadAdd32:
98 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, true, 32, NextMBBI);
99 case LoongArch::PseudoMaskedAtomicLoadSub32:
100 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, true, 32, NextMBBI);
101 case LoongArch::PseudoAtomicLoadNand32:
102 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 32,
103 NextMBBI);
104 case LoongArch::PseudoAtomicLoadNand64:
105 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 64,
106 NextMBBI);
107 case LoongArch::PseudoMaskedAtomicLoadNand32:
108 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, true, 32,
109 NextMBBI);
110 case LoongArch::PseudoAtomicLoadAdd32:
111 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, false, 32,
112 NextMBBI);
113 case LoongArch::PseudoAtomicLoadSub32:
114 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, false, 32,
115 NextMBBI);
116 case LoongArch::PseudoAtomicLoadAnd32:
117 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::And, false, 32,
118 NextMBBI);
119 case LoongArch::PseudoAtomicLoadOr32:
120 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Or, false, 32, NextMBBI);
121 case LoongArch::PseudoAtomicLoadXor32:
122 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xor, false, 32,
123 NextMBBI);
124 case LoongArch::PseudoMaskedAtomicLoadUMax32:
125 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMax, true, 32,
126 NextMBBI);
127 case LoongArch::PseudoMaskedAtomicLoadUMin32:
128 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMin, true, 32,
129 NextMBBI);
130 case LoongArch::PseudoCmpXchg32:
131 return expandAtomicCmpXchg(MBB, MBBI, false, 32, NextMBBI);
132 case LoongArch::PseudoCmpXchg64:
133 return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI);
134 case LoongArch::PseudoMaskedCmpXchg32:
135 return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI);
136 case LoongArch::PseudoMaskedAtomicLoadMax32:
137 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Max, true, 32,
138 NextMBBI);
139 case LoongArch::PseudoMaskedAtomicLoadMin32:
140 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Min, true, 32,
141 NextMBBI);
143 return false;
146 static void doAtomicBinOpExpansion(const LoongArchInstrInfo *TII,
147 MachineInstr &MI, DebugLoc DL,
148 MachineBasicBlock *ThisMBB,
149 MachineBasicBlock *LoopMBB,
150 MachineBasicBlock *DoneMBB,
151 AtomicRMWInst::BinOp BinOp, int Width) {
152 Register DestReg = MI.getOperand(0).getReg();
153 Register ScratchReg = MI.getOperand(1).getReg();
154 Register AddrReg = MI.getOperand(2).getReg();
155 Register IncrReg = MI.getOperand(3).getReg();
157 // .loop:
158 // ll.[w|d] dest, (addr)
159 // binop scratch, dest, val
160 // sc.[w|d] scratch, scratch, (addr)
161 // beqz scratch, loop
162 BuildMI(LoopMBB, DL,
163 TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
164 .addReg(AddrReg)
165 .addImm(0);
166 switch (BinOp) {
167 default:
168 llvm_unreachable("Unexpected AtomicRMW BinOp");
169 case AtomicRMWInst::Xchg:
170 BuildMI(LoopMBB, DL, TII->get(LoongArch::OR), ScratchReg)
171 .addReg(IncrReg)
172 .addReg(LoongArch::R0);
173 break;
174 case AtomicRMWInst::Nand:
175 BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)
176 .addReg(DestReg)
177 .addReg(IncrReg);
178 BuildMI(LoopMBB, DL, TII->get(LoongArch::NOR), ScratchReg)
179 .addReg(ScratchReg)
180 .addReg(LoongArch::R0);
181 break;
182 case AtomicRMWInst::Add:
183 BuildMI(LoopMBB, DL, TII->get(LoongArch::ADD_W), ScratchReg)
184 .addReg(DestReg)
185 .addReg(IncrReg);
186 break;
187 case AtomicRMWInst::Sub:
188 BuildMI(LoopMBB, DL, TII->get(LoongArch::SUB_W), ScratchReg)
189 .addReg(DestReg)
190 .addReg(IncrReg);
191 break;
192 case AtomicRMWInst::And:
193 BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)
194 .addReg(DestReg)
195 .addReg(IncrReg);
196 break;
197 case AtomicRMWInst::Or:
198 BuildMI(LoopMBB, DL, TII->get(LoongArch::OR), ScratchReg)
199 .addReg(DestReg)
200 .addReg(IncrReg);
201 break;
202 case AtomicRMWInst::Xor:
203 BuildMI(LoopMBB, DL, TII->get(LoongArch::XOR), ScratchReg)
204 .addReg(DestReg)
205 .addReg(IncrReg);
206 break;
208 BuildMI(LoopMBB, DL,
209 TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D), ScratchReg)
210 .addReg(ScratchReg)
211 .addReg(AddrReg)
212 .addImm(0);
213 BuildMI(LoopMBB, DL, TII->get(LoongArch::BEQZ))
214 .addReg(ScratchReg)
215 .addMBB(LoopMBB);
218 static void insertMaskedMerge(const LoongArchInstrInfo *TII, DebugLoc DL,
219 MachineBasicBlock *MBB, Register DestReg,
220 Register OldValReg, Register NewValReg,
221 Register MaskReg, Register ScratchReg) {
222 assert(OldValReg != ScratchReg && "OldValReg and ScratchReg must be unique");
223 assert(OldValReg != MaskReg && "OldValReg and MaskReg must be unique");
224 assert(ScratchReg != MaskReg && "ScratchReg and MaskReg must be unique");
226 // res = oldval ^ ((oldval ^ newval) & masktargetdata);
227 BuildMI(MBB, DL, TII->get(LoongArch::XOR), ScratchReg)
228 .addReg(OldValReg)
229 .addReg(NewValReg);
230 BuildMI(MBB, DL, TII->get(LoongArch::AND), ScratchReg)
231 .addReg(ScratchReg)
232 .addReg(MaskReg);
233 BuildMI(MBB, DL, TII->get(LoongArch::XOR), DestReg)
234 .addReg(OldValReg)
235 .addReg(ScratchReg);
238 static void doMaskedAtomicBinOpExpansion(
239 const LoongArchInstrInfo *TII, MachineInstr &MI, DebugLoc DL,
240 MachineBasicBlock *ThisMBB, MachineBasicBlock *LoopMBB,
241 MachineBasicBlock *DoneMBB, AtomicRMWInst::BinOp BinOp, int Width) {
242 assert(Width == 32 && "Should never need to expand masked 64-bit operations");
243 Register DestReg = MI.getOperand(0).getReg();
244 Register ScratchReg = MI.getOperand(1).getReg();
245 Register AddrReg = MI.getOperand(2).getReg();
246 Register IncrReg = MI.getOperand(3).getReg();
247 Register MaskReg = MI.getOperand(4).getReg();
249 // .loop:
250 // ll.w destreg, (alignedaddr)
251 // binop scratch, destreg, incr
252 // xor scratch, destreg, scratch
253 // and scratch, scratch, masktargetdata
254 // xor scratch, destreg, scratch
255 // sc.w scratch, scratch, (alignedaddr)
256 // beqz scratch, loop
257 BuildMI(LoopMBB, DL, TII->get(LoongArch::LL_W), DestReg)
258 .addReg(AddrReg)
259 .addImm(0);
260 switch (BinOp) {
261 default:
262 llvm_unreachable("Unexpected AtomicRMW BinOp");
263 case AtomicRMWInst::Xchg:
264 BuildMI(LoopMBB, DL, TII->get(LoongArch::ADDI_W), ScratchReg)
265 .addReg(IncrReg)
266 .addImm(0);
267 break;
268 case AtomicRMWInst::Add:
269 BuildMI(LoopMBB, DL, TII->get(LoongArch::ADD_W), ScratchReg)
270 .addReg(DestReg)
271 .addReg(IncrReg);
272 break;
273 case AtomicRMWInst::Sub:
274 BuildMI(LoopMBB, DL, TII->get(LoongArch::SUB_W), ScratchReg)
275 .addReg(DestReg)
276 .addReg(IncrReg);
277 break;
278 case AtomicRMWInst::Nand:
279 BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)
280 .addReg(DestReg)
281 .addReg(IncrReg);
282 BuildMI(LoopMBB, DL, TII->get(LoongArch::NOR), ScratchReg)
283 .addReg(ScratchReg)
284 .addReg(LoongArch::R0);
285 // TODO: support other AtomicRMWInst.
288 insertMaskedMerge(TII, DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,
289 ScratchReg);
291 BuildMI(LoopMBB, DL, TII->get(LoongArch::SC_W), ScratchReg)
292 .addReg(ScratchReg)
293 .addReg(AddrReg)
294 .addImm(0);
295 BuildMI(LoopMBB, DL, TII->get(LoongArch::BEQZ))
296 .addReg(ScratchReg)
297 .addMBB(LoopMBB);
300 bool LoongArchExpandAtomicPseudo::expandAtomicBinOp(
301 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
302 AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
303 MachineBasicBlock::iterator &NextMBBI) {
304 MachineInstr &MI = *MBBI;
305 DebugLoc DL = MI.getDebugLoc();
307 MachineFunction *MF = MBB.getParent();
308 auto LoopMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
309 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
311 // Insert new MBBs.
312 MF->insert(++MBB.getIterator(), LoopMBB);
313 MF->insert(++LoopMBB->getIterator(), DoneMBB);
315 // Set up successors and transfer remaining instructions to DoneMBB.
316 LoopMBB->addSuccessor(LoopMBB);
317 LoopMBB->addSuccessor(DoneMBB);
318 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
319 DoneMBB->transferSuccessors(&MBB);
320 MBB.addSuccessor(LoopMBB);
322 if (IsMasked)
323 doMaskedAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp,
324 Width);
325 else
326 doAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp, Width);
328 NextMBBI = MBB.end();
329 MI.eraseFromParent();
331 LivePhysRegs LiveRegs;
332 computeAndAddLiveIns(LiveRegs, *LoopMBB);
333 computeAndAddLiveIns(LiveRegs, *DoneMBB);
335 return true;
338 static void insertSext(const LoongArchInstrInfo *TII, DebugLoc DL,
339 MachineBasicBlock *MBB, Register ValReg,
340 Register ShamtReg) {
341 BuildMI(MBB, DL, TII->get(LoongArch::SLL_W), ValReg)
342 .addReg(ValReg)
343 .addReg(ShamtReg);
344 BuildMI(MBB, DL, TII->get(LoongArch::SRA_W), ValReg)
345 .addReg(ValReg)
346 .addReg(ShamtReg);
349 bool LoongArchExpandAtomicPseudo::expandAtomicMinMaxOp(
350 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
351 AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
352 MachineBasicBlock::iterator &NextMBBI) {
353 assert(IsMasked == true &&
354 "Should only need to expand masked atomic max/min");
355 assert(Width == 32 && "Should never need to expand masked 64-bit operations");
357 MachineInstr &MI = *MBBI;
358 DebugLoc DL = MI.getDebugLoc();
359 MachineFunction *MF = MBB.getParent();
360 auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
361 auto LoopIfBodyMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
362 auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
363 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
365 // Insert new MBBs.
366 MF->insert(++MBB.getIterator(), LoopHeadMBB);
367 MF->insert(++LoopHeadMBB->getIterator(), LoopIfBodyMBB);
368 MF->insert(++LoopIfBodyMBB->getIterator(), LoopTailMBB);
369 MF->insert(++LoopTailMBB->getIterator(), DoneMBB);
371 // Set up successors and transfer remaining instructions to DoneMBB.
372 LoopHeadMBB->addSuccessor(LoopIfBodyMBB);
373 LoopHeadMBB->addSuccessor(LoopTailMBB);
374 LoopIfBodyMBB->addSuccessor(LoopTailMBB);
375 LoopTailMBB->addSuccessor(LoopHeadMBB);
376 LoopTailMBB->addSuccessor(DoneMBB);
377 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
378 DoneMBB->transferSuccessors(&MBB);
379 MBB.addSuccessor(LoopHeadMBB);
381 Register DestReg = MI.getOperand(0).getReg();
382 Register Scratch1Reg = MI.getOperand(1).getReg();
383 Register Scratch2Reg = MI.getOperand(2).getReg();
384 Register AddrReg = MI.getOperand(3).getReg();
385 Register IncrReg = MI.getOperand(4).getReg();
386 Register MaskReg = MI.getOperand(5).getReg();
389 // .loophead:
390 // ll.w destreg, (alignedaddr)
391 // and scratch2, destreg, mask
392 // move scratch1, destreg
393 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::LL_W), DestReg)
394 .addReg(AddrReg)
395 .addImm(0);
396 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::AND), Scratch2Reg)
397 .addReg(DestReg)
398 .addReg(MaskReg);
399 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::OR), Scratch1Reg)
400 .addReg(DestReg)
401 .addReg(LoongArch::R0);
403 switch (BinOp) {
404 default:
405 llvm_unreachable("Unexpected AtomicRMW BinOp");
406 // bgeu scratch2, incr, .looptail
407 case AtomicRMWInst::UMax:
408 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGEU))
409 .addReg(Scratch2Reg)
410 .addReg(IncrReg)
411 .addMBB(LoopTailMBB);
412 break;
413 // bgeu incr, scratch2, .looptail
414 case AtomicRMWInst::UMin:
415 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGEU))
416 .addReg(IncrReg)
417 .addReg(Scratch2Reg)
418 .addMBB(LoopTailMBB);
419 break;
420 case AtomicRMWInst::Max:
421 insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
422 // bge scratch2, incr, .looptail
423 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGE))
424 .addReg(Scratch2Reg)
425 .addReg(IncrReg)
426 .addMBB(LoopTailMBB);
427 break;
428 case AtomicRMWInst::Min:
429 insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
430 // bge incr, scratch2, .looptail
431 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGE))
432 .addReg(IncrReg)
433 .addReg(Scratch2Reg)
434 .addMBB(LoopTailMBB);
435 break;
436 // TODO: support other AtomicRMWInst.
439 // .loopifbody:
440 // xor scratch1, destreg, incr
441 // and scratch1, scratch1, mask
442 // xor scratch1, destreg, scratch1
443 insertMaskedMerge(TII, DL, LoopIfBodyMBB, Scratch1Reg, DestReg, IncrReg,
444 MaskReg, Scratch1Reg);
446 // .looptail:
447 // sc.w scratch1, scratch1, (addr)
448 // beqz scratch1, loop
449 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::SC_W), Scratch1Reg)
450 .addReg(Scratch1Reg)
451 .addReg(AddrReg)
452 .addImm(0);
453 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))
454 .addReg(Scratch1Reg)
455 .addMBB(LoopHeadMBB);
457 NextMBBI = MBB.end();
458 MI.eraseFromParent();
460 LivePhysRegs LiveRegs;
461 computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
462 computeAndAddLiveIns(LiveRegs, *LoopIfBodyMBB);
463 computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
464 computeAndAddLiveIns(LiveRegs, *DoneMBB);
466 return true;
469 bool LoongArchExpandAtomicPseudo::expandAtomicCmpXchg(
470 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked,
471 int Width, MachineBasicBlock::iterator &NextMBBI) {
472 MachineInstr &MI = *MBBI;
473 DebugLoc DL = MI.getDebugLoc();
474 MachineFunction *MF = MBB.getParent();
475 auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
476 auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
477 auto TailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
478 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
480 // Insert new MBBs.
481 MF->insert(++MBB.getIterator(), LoopHeadMBB);
482 MF->insert(++LoopHeadMBB->getIterator(), LoopTailMBB);
483 MF->insert(++LoopTailMBB->getIterator(), TailMBB);
484 MF->insert(++TailMBB->getIterator(), DoneMBB);
486 // Set up successors and transfer remaining instructions to DoneMBB.
487 LoopHeadMBB->addSuccessor(LoopTailMBB);
488 LoopHeadMBB->addSuccessor(TailMBB);
489 LoopTailMBB->addSuccessor(DoneMBB);
490 LoopTailMBB->addSuccessor(LoopHeadMBB);
491 TailMBB->addSuccessor(DoneMBB);
492 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
493 DoneMBB->transferSuccessors(&MBB);
494 MBB.addSuccessor(LoopHeadMBB);
496 Register DestReg = MI.getOperand(0).getReg();
497 Register ScratchReg = MI.getOperand(1).getReg();
498 Register AddrReg = MI.getOperand(2).getReg();
499 Register CmpValReg = MI.getOperand(3).getReg();
500 Register NewValReg = MI.getOperand(4).getReg();
502 if (!IsMasked) {
503 // .loophead:
504 // ll.[w|d] dest, (addr)
505 // bne dest, cmpval, tail
506 BuildMI(LoopHeadMBB, DL,
507 TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
508 .addReg(AddrReg)
509 .addImm(0);
510 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BNE))
511 .addReg(DestReg)
512 .addReg(CmpValReg)
513 .addMBB(TailMBB);
514 // .looptail:
515 // move scratch, newval
516 // sc.[w|d] scratch, scratch, (addr)
517 // beqz scratch, loophead
518 // b done
519 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::OR), ScratchReg)
520 .addReg(NewValReg)
521 .addReg(LoongArch::R0);
522 BuildMI(LoopTailMBB, DL,
523 TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),
524 ScratchReg)
525 .addReg(ScratchReg)
526 .addReg(AddrReg)
527 .addImm(0);
528 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))
529 .addReg(ScratchReg)
530 .addMBB(LoopHeadMBB);
531 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::B)).addMBB(DoneMBB);
532 } else {
533 // .loophead:
534 // ll.[w|d] dest, (addr)
535 // and scratch, dest, mask
536 // bne scratch, cmpval, tail
537 Register MaskReg = MI.getOperand(5).getReg();
538 BuildMI(LoopHeadMBB, DL,
539 TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
540 .addReg(AddrReg)
541 .addImm(0);
542 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::AND), ScratchReg)
543 .addReg(DestReg)
544 .addReg(MaskReg);
545 BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BNE))
546 .addReg(ScratchReg)
547 .addReg(CmpValReg)
548 .addMBB(TailMBB);
550 // .looptail:
551 // andn scratch, dest, mask
552 // or scratch, scratch, newval
553 // sc.[w|d] scratch, scratch, (addr)
554 // beqz scratch, loophead
555 // b done
556 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::ANDN), ScratchReg)
557 .addReg(DestReg)
558 .addReg(MaskReg);
559 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::OR), ScratchReg)
560 .addReg(ScratchReg)
561 .addReg(NewValReg);
562 BuildMI(LoopTailMBB, DL,
563 TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),
564 ScratchReg)
565 .addReg(ScratchReg)
566 .addReg(AddrReg)
567 .addImm(0);
568 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))
569 .addReg(ScratchReg)
570 .addMBB(LoopHeadMBB);
571 BuildMI(LoopTailMBB, DL, TII->get(LoongArch::B)).addMBB(DoneMBB);
574 AtomicOrdering FailureOrdering =
575 static_cast<AtomicOrdering>(MI.getOperand(IsMasked ? 6 : 5).getImm());
576 int hint;
578 switch (FailureOrdering) {
579 case AtomicOrdering::Acquire:
580 case AtomicOrdering::AcquireRelease:
581 case AtomicOrdering::SequentiallyConsistent:
582 // acquire
583 hint = 0b10100;
584 break;
585 default:
586 hint = 0x700;
589 // .tail:
590 // dbar 0x700 | acquire
591 BuildMI(TailMBB, DL, TII->get(LoongArch::DBAR)).addImm(hint);
593 NextMBBI = MBB.end();
594 MI.eraseFromParent();
596 LivePhysRegs LiveRegs;
597 computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
598 computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
599 computeAndAddLiveIns(LiveRegs, *TailMBB);
600 computeAndAddLiveIns(LiveRegs, *DoneMBB);
602 return true;
605 } // end namespace
607 INITIALIZE_PASS(LoongArchExpandAtomicPseudo, "loongarch-expand-atomic-pseudo",
608 LoongArch_EXPAND_ATOMIC_PSEUDO_NAME, false, false)
610 namespace llvm {
612 FunctionPass *createLoongArchExpandAtomicPseudoPass() {
613 return new LoongArchExpandAtomicPseudo();
616 } // end namespace llvm