blob: 55275de50206bab40643805f2c5126f9b88f6aed [file] [log] [blame]
Alex Bradbury21aea512018-09-19 10:54:22 +00001//===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a pass that expands pseudo instructions into target
11// instructions. This pass should be run after register allocation but before
12// the post-regalloc scheduling pass.
13//
14//===----------------------------------------------------------------------===//
15
16#include "RISCV.h"
17#include "RISCVInstrInfo.h"
18#include "RISCVTargetMachine.h"
19
20#include "llvm/CodeGen/LivePhysRegs.h"
21#include "llvm/CodeGen/MachineFunctionPass.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23
24using namespace llvm;
25
26#define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass"
27
28namespace {
29
30class RISCVExpandPseudo : public MachineFunctionPass {
31public:
32 const RISCVInstrInfo *TII;
33 static char ID;
34
35 RISCVExpandPseudo() : MachineFunctionPass(ID) {
36 initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
37 }
38
39 bool runOnMachineFunction(MachineFunction &MF) override;
40
41 StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }
42
43private:
44 bool expandMBB(MachineBasicBlock &MBB);
45 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
46 MachineBasicBlock::iterator &NextMBBI);
47 bool expandAtomicBinOp(MachineBasicBlock &MBB,
48 MachineBasicBlock::iterator MBBI, AtomicRMWInst::BinOp,
49 bool IsMasked, int Width,
50 MachineBasicBlock::iterator &NextMBBI);
51 bool expandAtomicMinMaxOp(MachineBasicBlock &MBB,
52 MachineBasicBlock::iterator MBBI,
53 AtomicRMWInst::BinOp, bool IsMasked, int Width,
54 MachineBasicBlock::iterator &NextMBBI);
Alex Bradbury66d9a752018-11-29 20:43:42 +000055 bool expandAtomicCmpXchg(MachineBasicBlock &MBB,
56 MachineBasicBlock::iterator MBBI, bool IsMasked,
57 int Width, MachineBasicBlock::iterator &NextMBBI);
Alex Bradbury21aea512018-09-19 10:54:22 +000058};
59
60char RISCVExpandPseudo::ID = 0;
61
62bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
63 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
64 bool Modified = false;
65 for (auto &MBB : MF)
66 Modified |= expandMBB(MBB);
67 return Modified;
68}
69
70bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
71 bool Modified = false;
72
73 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
74 while (MBBI != E) {
75 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
76 Modified |= expandMI(MBB, MBBI, NMBBI);
77 MBBI = NMBBI;
78 }
79
80 return Modified;
81}
82
83bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
84 MachineBasicBlock::iterator MBBI,
85 MachineBasicBlock::iterator &NextMBBI) {
86 switch (MBBI->getOpcode()) {
87 case RISCV::PseudoAtomicLoadNand32:
88 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 32,
89 NextMBBI);
Alex Bradbury07f1c622019-01-17 10:04:39 +000090 case RISCV::PseudoAtomicLoadNand64:
91 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 64,
92 NextMBBI);
Alex Bradbury21aea512018-09-19 10:54:22 +000093 case RISCV::PseudoMaskedAtomicSwap32:
94 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, true, 32,
95 NextMBBI);
96 case RISCV::PseudoMaskedAtomicLoadAdd32:
97 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, true, 32, NextMBBI);
98 case RISCV::PseudoMaskedAtomicLoadSub32:
99 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, true, 32, NextMBBI);
100 case RISCV::PseudoMaskedAtomicLoadNand32:
101 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, true, 32,
102 NextMBBI);
103 case RISCV::PseudoMaskedAtomicLoadMax32:
104 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Max, true, 32,
105 NextMBBI);
106 case RISCV::PseudoMaskedAtomicLoadMin32:
107 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Min, true, 32,
108 NextMBBI);
109 case RISCV::PseudoMaskedAtomicLoadUMax32:
110 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMax, true, 32,
111 NextMBBI);
112 case RISCV::PseudoMaskedAtomicLoadUMin32:
113 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMin, true, 32,
114 NextMBBI);
Alex Bradbury66d9a752018-11-29 20:43:42 +0000115 case RISCV::PseudoCmpXchg32:
116 return expandAtomicCmpXchg(MBB, MBBI, false, 32, NextMBBI);
Alex Bradbury07f1c622019-01-17 10:04:39 +0000117 case RISCV::PseudoCmpXchg64:
118 return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI);
Alex Bradbury66d9a752018-11-29 20:43:42 +0000119 case RISCV::PseudoMaskedCmpXchg32:
120 return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI);
Alex Bradbury21aea512018-09-19 10:54:22 +0000121 }
122
123 return false;
124}
125
126static unsigned getLRForRMW32(AtomicOrdering Ordering) {
127 switch (Ordering) {
128 default:
129 llvm_unreachable("Unexpected AtomicOrdering");
130 case AtomicOrdering::Monotonic:
131 return RISCV::LR_W;
132 case AtomicOrdering::Acquire:
133 return RISCV::LR_W_AQ;
134 case AtomicOrdering::Release:
135 return RISCV::LR_W;
136 case AtomicOrdering::AcquireRelease:
137 return RISCV::LR_W_AQ;
138 case AtomicOrdering::SequentiallyConsistent:
139 return RISCV::LR_W_AQ_RL;
140 }
141}
142
143static unsigned getSCForRMW32(AtomicOrdering Ordering) {
144 switch (Ordering) {
145 default:
146 llvm_unreachable("Unexpected AtomicOrdering");
147 case AtomicOrdering::Monotonic:
148 return RISCV::SC_W;
149 case AtomicOrdering::Acquire:
150 return RISCV::SC_W;
151 case AtomicOrdering::Release:
152 return RISCV::SC_W_RL;
153 case AtomicOrdering::AcquireRelease:
154 return RISCV::SC_W_RL;
155 case AtomicOrdering::SequentiallyConsistent:
156 return RISCV::SC_W_AQ_RL;
157 }
158}
159
Alex Bradbury07f1c622019-01-17 10:04:39 +0000160static unsigned getLRForRMW64(AtomicOrdering Ordering) {
161 switch (Ordering) {
162 default:
163 llvm_unreachable("Unexpected AtomicOrdering");
164 case AtomicOrdering::Monotonic:
165 return RISCV::LR_D;
166 case AtomicOrdering::Acquire:
167 return RISCV::LR_D_AQ;
168 case AtomicOrdering::Release:
169 return RISCV::LR_D;
170 case AtomicOrdering::AcquireRelease:
171 return RISCV::LR_D_AQ;
172 case AtomicOrdering::SequentiallyConsistent:
173 return RISCV::LR_D_AQ_RL;
174 }
175}
176
177static unsigned getSCForRMW64(AtomicOrdering Ordering) {
178 switch (Ordering) {
179 default:
180 llvm_unreachable("Unexpected AtomicOrdering");
181 case AtomicOrdering::Monotonic:
182 return RISCV::SC_D;
183 case AtomicOrdering::Acquire:
184 return RISCV::SC_D;
185 case AtomicOrdering::Release:
186 return RISCV::SC_D_RL;
187 case AtomicOrdering::AcquireRelease:
188 return RISCV::SC_D_RL;
189 case AtomicOrdering::SequentiallyConsistent:
190 return RISCV::SC_D_AQ_RL;
191 }
192}
193
194static unsigned getLRForRMW(AtomicOrdering Ordering, int Width) {
195 if (Width == 32)
196 return getLRForRMW32(Ordering);
197 if (Width == 64)
198 return getLRForRMW64(Ordering);
199 llvm_unreachable("Unexpected LR width\n");
200}
201
202static unsigned getSCForRMW(AtomicOrdering Ordering, int Width) {
203 if (Width == 32)
204 return getSCForRMW32(Ordering);
205 if (Width == 64)
206 return getSCForRMW64(Ordering);
207 llvm_unreachable("Unexpected SC width\n");
208}
209
Alex Bradbury21aea512018-09-19 10:54:22 +0000210static void doAtomicBinOpExpansion(const RISCVInstrInfo *TII, MachineInstr &MI,
211 DebugLoc DL, MachineBasicBlock *ThisMBB,
212 MachineBasicBlock *LoopMBB,
213 MachineBasicBlock *DoneMBB,
214 AtomicRMWInst::BinOp BinOp, int Width) {
Alex Bradbury21aea512018-09-19 10:54:22 +0000215 unsigned DestReg = MI.getOperand(0).getReg();
216 unsigned ScratchReg = MI.getOperand(1).getReg();
217 unsigned AddrReg = MI.getOperand(2).getReg();
218 unsigned IncrReg = MI.getOperand(3).getReg();
219 AtomicOrdering Ordering =
220 static_cast<AtomicOrdering>(MI.getOperand(4).getImm());
221
222 // .loop:
Alex Bradbury07f1c622019-01-17 10:04:39 +0000223 // lr.[w|d] dest, (addr)
Alex Bradbury21aea512018-09-19 10:54:22 +0000224 // binop scratch, dest, val
Alex Bradbury07f1c622019-01-17 10:04:39 +0000225 // sc.[w|d] scratch, scratch, (addr)
Alex Bradbury21aea512018-09-19 10:54:22 +0000226 // bnez scratch, loop
Alex Bradbury07f1c622019-01-17 10:04:39 +0000227 BuildMI(LoopMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg)
Alex Bradbury21aea512018-09-19 10:54:22 +0000228 .addReg(AddrReg);
229 switch (BinOp) {
230 default:
231 llvm_unreachable("Unexpected AtomicRMW BinOp");
232 case AtomicRMWInst::Nand:
233 BuildMI(LoopMBB, DL, TII->get(RISCV::AND), ScratchReg)
234 .addReg(DestReg)
235 .addReg(IncrReg);
236 BuildMI(LoopMBB, DL, TII->get(RISCV::XORI), ScratchReg)
237 .addReg(ScratchReg)
238 .addImm(-1);
239 break;
240 }
Alex Bradbury07f1c622019-01-17 10:04:39 +0000241 BuildMI(LoopMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg)
Alex Bradbury21aea512018-09-19 10:54:22 +0000242 .addReg(AddrReg)
243 .addReg(ScratchReg);
244 BuildMI(LoopMBB, DL, TII->get(RISCV::BNE))
245 .addReg(ScratchReg)
246 .addReg(RISCV::X0)
247 .addMBB(LoopMBB);
248}
249
250static void insertMaskedMerge(const RISCVInstrInfo *TII, DebugLoc DL,
251 MachineBasicBlock *MBB, unsigned DestReg,
252 unsigned OldValReg, unsigned NewValReg,
253 unsigned MaskReg, unsigned ScratchReg) {
254 assert(OldValReg != ScratchReg && "OldValReg and ScratchReg must be unique");
255 assert(OldValReg != MaskReg && "OldValReg and MaskReg must be unique");
256 assert(ScratchReg != MaskReg && "ScratchReg and MaskReg must be unique");
257
258 // We select bits from newval and oldval using:
259 // https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
260 // r = oldval ^ ((oldval ^ newval) & masktargetdata);
261 BuildMI(MBB, DL, TII->get(RISCV::XOR), ScratchReg)
262 .addReg(OldValReg)
263 .addReg(NewValReg);
264 BuildMI(MBB, DL, TII->get(RISCV::AND), ScratchReg)
265 .addReg(ScratchReg)
266 .addReg(MaskReg);
267 BuildMI(MBB, DL, TII->get(RISCV::XOR), DestReg)
268 .addReg(OldValReg)
269 .addReg(ScratchReg);
270}
271
272static void doMaskedAtomicBinOpExpansion(
273 const RISCVInstrInfo *TII, MachineInstr &MI, DebugLoc DL,
274 MachineBasicBlock *ThisMBB, MachineBasicBlock *LoopMBB,
275 MachineBasicBlock *DoneMBB, AtomicRMWInst::BinOp BinOp, int Width) {
Alex Bradbury07f1c622019-01-17 10:04:39 +0000276 assert(Width == 32 && "Should never need to expand masked 64-bit operations");
Alex Bradbury21aea512018-09-19 10:54:22 +0000277 unsigned DestReg = MI.getOperand(0).getReg();
278 unsigned ScratchReg = MI.getOperand(1).getReg();
279 unsigned AddrReg = MI.getOperand(2).getReg();
280 unsigned IncrReg = MI.getOperand(3).getReg();
281 unsigned MaskReg = MI.getOperand(4).getReg();
282 AtomicOrdering Ordering =
283 static_cast<AtomicOrdering>(MI.getOperand(5).getImm());
284
285 // .loop:
286 // lr.w destreg, (alignedaddr)
287 // binop scratch, destreg, incr
288 // xor scratch, destreg, scratch
289 // and scratch, scratch, masktargetdata
290 // xor scratch, destreg, scratch
291 // sc.w scratch, scratch, (alignedaddr)
292 // bnez scratch, loop
293 BuildMI(LoopMBB, DL, TII->get(getLRForRMW32(Ordering)), DestReg)
294 .addReg(AddrReg);
295 switch (BinOp) {
296 default:
297 llvm_unreachable("Unexpected AtomicRMW BinOp");
298 case AtomicRMWInst::Xchg:
299 BuildMI(LoopMBB, DL, TII->get(RISCV::ADD), ScratchReg)
300 .addReg(RISCV::X0)
301 .addReg(IncrReg);
302 break;
303 case AtomicRMWInst::Add:
304 BuildMI(LoopMBB, DL, TII->get(RISCV::ADD), ScratchReg)
305 .addReg(DestReg)
306 .addReg(IncrReg);
307 break;
308 case AtomicRMWInst::Sub:
309 BuildMI(LoopMBB, DL, TII->get(RISCV::SUB), ScratchReg)
310 .addReg(DestReg)
311 .addReg(IncrReg);
312 break;
313 case AtomicRMWInst::Nand:
314 BuildMI(LoopMBB, DL, TII->get(RISCV::AND), ScratchReg)
315 .addReg(DestReg)
316 .addReg(IncrReg);
317 BuildMI(LoopMBB, DL, TII->get(RISCV::XORI), ScratchReg)
318 .addReg(ScratchReg)
319 .addImm(-1);
320 break;
321 }
322
323 insertMaskedMerge(TII, DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,
324 ScratchReg);
325
326 BuildMI(LoopMBB, DL, TII->get(getSCForRMW32(Ordering)), ScratchReg)
327 .addReg(AddrReg)
328 .addReg(ScratchReg);
329 BuildMI(LoopMBB, DL, TII->get(RISCV::BNE))
330 .addReg(ScratchReg)
331 .addReg(RISCV::X0)
332 .addMBB(LoopMBB);
333}
334
335bool RISCVExpandPseudo::expandAtomicBinOp(
336 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
337 AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
338 MachineBasicBlock::iterator &NextMBBI) {
339 MachineInstr &MI = *MBBI;
340 DebugLoc DL = MI.getDebugLoc();
341
342 MachineFunction *MF = MBB.getParent();
343 auto LoopMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
344 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
345
346 // Insert new MBBs.
347 MF->insert(++MBB.getIterator(), LoopMBB);
348 MF->insert(++LoopMBB->getIterator(), DoneMBB);
349
350 // Set up successors and transfer remaining instructions to DoneMBB.
351 LoopMBB->addSuccessor(LoopMBB);
352 LoopMBB->addSuccessor(DoneMBB);
353 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
354 DoneMBB->transferSuccessors(&MBB);
355 MBB.addSuccessor(LoopMBB);
356
357 if (!IsMasked)
358 doAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp, Width);
359 else
360 doMaskedAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp,
361 Width);
362
363 NextMBBI = MBB.end();
364 MI.eraseFromParent();
365
366 LivePhysRegs LiveRegs;
367 computeAndAddLiveIns(LiveRegs, *LoopMBB);
368 computeAndAddLiveIns(LiveRegs, *DoneMBB);
369
370 return true;
371}
372
373static void insertSext(const RISCVInstrInfo *TII, DebugLoc DL,
374 MachineBasicBlock *MBB, unsigned ValReg,
375 unsigned ShamtReg) {
376 BuildMI(MBB, DL, TII->get(RISCV::SLL), ValReg)
377 .addReg(ValReg)
378 .addReg(ShamtReg);
379 BuildMI(MBB, DL, TII->get(RISCV::SRA), ValReg)
380 .addReg(ValReg)
381 .addReg(ShamtReg);
382}
383
384bool RISCVExpandPseudo::expandAtomicMinMaxOp(
385 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
386 AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
387 MachineBasicBlock::iterator &NextMBBI) {
388 assert(IsMasked == true &&
389 "Should only need to expand masked atomic max/min");
Alex Bradbury07f1c622019-01-17 10:04:39 +0000390 assert(Width == 32 && "Should never need to expand masked 64-bit operations");
Alex Bradbury21aea512018-09-19 10:54:22 +0000391
392 MachineInstr &MI = *MBBI;
393 DebugLoc DL = MI.getDebugLoc();
394 MachineFunction *MF = MBB.getParent();
395 auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
396 auto LoopIfBodyMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
397 auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
398 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
399
400 // Insert new MBBs.
401 MF->insert(++MBB.getIterator(), LoopHeadMBB);
402 MF->insert(++LoopHeadMBB->getIterator(), LoopIfBodyMBB);
403 MF->insert(++LoopIfBodyMBB->getIterator(), LoopTailMBB);
404 MF->insert(++LoopTailMBB->getIterator(), DoneMBB);
405
406 // Set up successors and transfer remaining instructions to DoneMBB.
407 LoopHeadMBB->addSuccessor(LoopIfBodyMBB);
408 LoopHeadMBB->addSuccessor(LoopTailMBB);
409 LoopIfBodyMBB->addSuccessor(LoopTailMBB);
410 LoopTailMBB->addSuccessor(LoopHeadMBB);
411 LoopTailMBB->addSuccessor(DoneMBB);
412 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
413 DoneMBB->transferSuccessors(&MBB);
414 MBB.addSuccessor(LoopHeadMBB);
415
416 unsigned DestReg = MI.getOperand(0).getReg();
417 unsigned Scratch1Reg = MI.getOperand(1).getReg();
418 unsigned Scratch2Reg = MI.getOperand(2).getReg();
419 unsigned AddrReg = MI.getOperand(3).getReg();
420 unsigned IncrReg = MI.getOperand(4).getReg();
421 unsigned MaskReg = MI.getOperand(5).getReg();
422 bool IsSigned = BinOp == AtomicRMWInst::Min || BinOp == AtomicRMWInst::Max;
423 AtomicOrdering Ordering =
424 static_cast<AtomicOrdering>(MI.getOperand(IsSigned ? 7 : 6).getImm());
425
426 //
427 // .loophead:
428 // lr.w destreg, (alignedaddr)
429 // and scratch2, destreg, mask
430 // mv scratch1, destreg
431 // [sext scratch2 if signed min/max]
432 // ifnochangeneeded scratch2, incr, .looptail
433 BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW32(Ordering)), DestReg)
434 .addReg(AddrReg);
435 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::AND), Scratch2Reg)
436 .addReg(DestReg)
437 .addReg(MaskReg);
438 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::ADDI), Scratch1Reg)
439 .addReg(DestReg)
440 .addImm(0);
441
442 switch (BinOp) {
443 default:
444 llvm_unreachable("Unexpected AtomicRMW BinOp");
445 case AtomicRMWInst::Max: {
446 insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
447 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGE))
448 .addReg(Scratch2Reg)
449 .addReg(IncrReg)
450 .addMBB(LoopTailMBB);
451 break;
452 }
453 case AtomicRMWInst::Min: {
454 insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
455 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGE))
456 .addReg(IncrReg)
457 .addReg(Scratch2Reg)
458 .addMBB(LoopTailMBB);
459 break;
460 }
461 case AtomicRMWInst::UMax:
462 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGEU))
463 .addReg(Scratch2Reg)
464 .addReg(IncrReg)
465 .addMBB(LoopTailMBB);
466 break;
467 case AtomicRMWInst::UMin:
468 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGEU))
469 .addReg(IncrReg)
470 .addReg(Scratch2Reg)
471 .addMBB(LoopTailMBB);
472 break;
473 }
474
475 // .loopifbody:
476 // xor scratch1, destreg, incr
477 // and scratch1, scratch1, mask
478 // xor scratch1, destreg, scratch1
479 insertMaskedMerge(TII, DL, LoopIfBodyMBB, Scratch1Reg, DestReg, IncrReg,
480 MaskReg, Scratch1Reg);
481
482 // .looptail:
483 // sc.w scratch1, scratch1, (addr)
484 // bnez scratch1, loop
485 BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW32(Ordering)), Scratch1Reg)
486 .addReg(AddrReg)
487 .addReg(Scratch1Reg);
488 BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE))
489 .addReg(Scratch1Reg)
490 .addReg(RISCV::X0)
491 .addMBB(LoopHeadMBB);
492
493 NextMBBI = MBB.end();
494 MI.eraseFromParent();
495
496 LivePhysRegs LiveRegs;
497 computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
498 computeAndAddLiveIns(LiveRegs, *LoopIfBodyMBB);
499 computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
500 computeAndAddLiveIns(LiveRegs, *DoneMBB);
501
502 return true;
503}
504
Alex Bradbury66d9a752018-11-29 20:43:42 +0000505bool RISCVExpandPseudo::expandAtomicCmpXchg(
506 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked,
507 int Width, MachineBasicBlock::iterator &NextMBBI) {
Alex Bradbury66d9a752018-11-29 20:43:42 +0000508 MachineInstr &MI = *MBBI;
509 DebugLoc DL = MI.getDebugLoc();
510 MachineFunction *MF = MBB.getParent();
511 auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
512 auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
513 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
514
515 // Insert new MBBs.
516 MF->insert(++MBB.getIterator(), LoopHeadMBB);
517 MF->insert(++LoopHeadMBB->getIterator(), LoopTailMBB);
518 MF->insert(++LoopTailMBB->getIterator(), DoneMBB);
519
520 // Set up successors and transfer remaining instructions to DoneMBB.
521 LoopHeadMBB->addSuccessor(LoopTailMBB);
522 LoopHeadMBB->addSuccessor(DoneMBB);
523 LoopTailMBB->addSuccessor(DoneMBB);
524 LoopTailMBB->addSuccessor(LoopHeadMBB);
525 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
526 DoneMBB->transferSuccessors(&MBB);
527 MBB.addSuccessor(LoopHeadMBB);
528
529 unsigned DestReg = MI.getOperand(0).getReg();
530 unsigned ScratchReg = MI.getOperand(1).getReg();
531 unsigned AddrReg = MI.getOperand(2).getReg();
532 unsigned CmpValReg = MI.getOperand(3).getReg();
533 unsigned NewValReg = MI.getOperand(4).getReg();
534 AtomicOrdering Ordering =
535 static_cast<AtomicOrdering>(MI.getOperand(IsMasked ? 6 : 5).getImm());
536
537 if (!IsMasked) {
538 // .loophead:
Alex Bradbury07f1c622019-01-17 10:04:39 +0000539 // lr.[w|d] dest, (addr)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000540 // bne dest, cmpval, done
Alex Bradbury07f1c622019-01-17 10:04:39 +0000541 BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000542 .addReg(AddrReg);
543 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BNE))
544 .addReg(DestReg)
545 .addReg(CmpValReg)
546 .addMBB(DoneMBB);
547 // .looptail:
Alex Bradbury07f1c622019-01-17 10:04:39 +0000548 // sc.[w|d] scratch, newval, (addr)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000549 // bnez scratch, loophead
Alex Bradbury07f1c622019-01-17 10:04:39 +0000550 BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000551 .addReg(AddrReg)
552 .addReg(NewValReg);
553 BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE))
554 .addReg(ScratchReg)
555 .addReg(RISCV::X0)
556 .addMBB(LoopHeadMBB);
557 } else {
558 // .loophead:
559 // lr.w dest, (addr)
560 // and scratch, dest, mask
561 // bne scratch, cmpval, done
562 unsigned MaskReg = MI.getOperand(5).getReg();
Alex Bradbury07f1c622019-01-17 10:04:39 +0000563 BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000564 .addReg(AddrReg);
565 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::AND), ScratchReg)
566 .addReg(DestReg)
567 .addReg(MaskReg);
568 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BNE))
569 .addReg(ScratchReg)
570 .addReg(CmpValReg)
571 .addMBB(DoneMBB);
572
573 // .looptail:
574 // xor scratch, dest, newval
575 // and scratch, scratch, mask
576 // xor scratch, dest, scratch
577 // sc.w scratch, scratch, (adrr)
578 // bnez scratch, loophead
579 insertMaskedMerge(TII, DL, LoopTailMBB, ScratchReg, DestReg, NewValReg,
580 MaskReg, ScratchReg);
Alex Bradbury07f1c622019-01-17 10:04:39 +0000581 BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000582 .addReg(AddrReg)
583 .addReg(ScratchReg);
584 BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE))
585 .addReg(ScratchReg)
586 .addReg(RISCV::X0)
587 .addMBB(LoopHeadMBB);
588 }
589
590 NextMBBI = MBB.end();
591 MI.eraseFromParent();
592
593 LivePhysRegs LiveRegs;
594 computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
595 computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
596 computeAndAddLiveIns(LiveRegs, *DoneMBB);
597
598 return true;
599}
600
Alex Bradbury21aea512018-09-19 10:54:22 +0000601} // end of anonymous namespace
602
603INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
604 RISCV_EXPAND_PSEUDO_NAME, false, false)
605namespace llvm {
606
607FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
608
609} // end of namespace llvm