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