Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandAtomicPseudoInsts.cpp
35269 views
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.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "LoongArch.h"
17
#include "LoongArchInstrInfo.h"
18
#include "LoongArchTargetMachine.h"
19
20
#include "llvm/CodeGen/LivePhysRegs.h"
21
#include "llvm/CodeGen/MachineFunctionPass.h"
22
#include "llvm/CodeGen/MachineInstrBuilder.h"
23
24
using namespace llvm;
25
26
#define LoongArch_EXPAND_ATOMIC_PSEUDO_NAME \
27
"LoongArch atomic pseudo instruction expansion pass"
28
29
namespace {
30
31
class LoongArchExpandAtomicPseudo : public MachineFunctionPass {
32
public:
33
const LoongArchInstrInfo *TII;
34
static char ID;
35
36
LoongArchExpandAtomicPseudo() : MachineFunctionPass(ID) {
37
initializeLoongArchExpandAtomicPseudoPass(*PassRegistry::getPassRegistry());
38
}
39
40
bool runOnMachineFunction(MachineFunction &MF) override;
41
42
StringRef getPassName() const override {
43
return LoongArch_EXPAND_ATOMIC_PSEUDO_NAME;
44
}
45
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);
61
};
62
63
char LoongArchExpandAtomicPseudo::ID = 0;
64
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;
72
}
73
74
bool LoongArchExpandAtomicPseudo::expandMBB(MachineBasicBlock &MBB) {
75
bool Modified = false;
76
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;
82
}
83
84
return Modified;
85
}
86
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);
142
}
143
return false;
144
}
145
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();
156
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;
207
}
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);
216
}
217
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");
225
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);
236
}
237
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();
248
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.
286
}
287
288
insertMaskedMerge(TII, DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,
289
ScratchReg);
290
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);
298
}
299
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();
306
307
MachineFunction *MF = MBB.getParent();
308
auto LoopMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
309
auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
310
311
// Insert new MBBs.
312
MF->insert(++MBB.getIterator(), LoopMBB);
313
MF->insert(++LoopMBB->getIterator(), DoneMBB);
314
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);
321
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);
327
328
NextMBBI = MBB.end();
329
MI.eraseFromParent();
330
331
LivePhysRegs LiveRegs;
332
computeAndAddLiveIns(LiveRegs, *LoopMBB);
333
computeAndAddLiveIns(LiveRegs, *DoneMBB);
334
335
return true;
336
}
337
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);
347
}
348
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");
356
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());
364
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);
370
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);
380
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();
387
388
//
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);
402
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.
437
}
438
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);
445
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);
456
457
NextMBBI = MBB.end();
458
MI.eraseFromParent();
459
460
LivePhysRegs LiveRegs;
461
computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
462
computeAndAddLiveIns(LiveRegs, *LoopIfBodyMBB);
463
computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
464
computeAndAddLiveIns(LiveRegs, *DoneMBB);
465
466
return true;
467
}
468
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());
479
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);
485
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);
495
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();
501
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);
549
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);
572
}
573
574
AtomicOrdering FailureOrdering =
575
static_cast<AtomicOrdering>(MI.getOperand(IsMasked ? 6 : 5).getImm());
576
int hint;
577
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;
587
}
588
589
// .tail:
590
// dbar 0x700 | acquire
591
BuildMI(TailMBB, DL, TII->get(LoongArch::DBAR)).addImm(hint);
592
593
NextMBBI = MBB.end();
594
MI.eraseFromParent();
595
596
LivePhysRegs LiveRegs;
597
computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
598
computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
599
computeAndAddLiveIns(LiveRegs, *TailMBB);
600
computeAndAddLiveIns(LiveRegs, *DoneMBB);
601
602
return true;
603
}
604
605
} // end namespace
606
607
INITIALIZE_PASS(LoongArchExpandAtomicPseudo, "loongarch-expand-atomic-pseudo",
608
LoongArch_EXPAND_ATOMIC_PSEUDO_NAME, false, false)
609
610
namespace llvm {
611
612
FunctionPass *createLoongArchExpandAtomicPseudoPass() {
613
return new LoongArchExpandAtomicPseudo();
614
}
615
616
} // end namespace llvm
617
618