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