blob: cfe6d9f4721c7656ca35e8b9d49ea274d5f245bb [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 Bradburyda20f5c2019-04-01 14:42:56 +000057 bool expandLoadLocalAddress(MachineBasicBlock &MBB,
58 MachineBasicBlock::iterator MBBI,
59 MachineBasicBlock::iterator &NextMBBI);
Alex Bradbury21aea512018-09-19 10:54:22 +000060};
61
62char RISCVExpandPseudo::ID = 0;
63
64bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
65 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
66 bool Modified = false;
67 for (auto &MBB : MF)
68 Modified |= expandMBB(MBB);
69 return Modified;
70}
71
72bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
73 bool Modified = false;
74
75 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
76 while (MBBI != E) {
77 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
78 Modified |= expandMI(MBB, MBBI, NMBBI);
79 MBBI = NMBBI;
80 }
81
82 return Modified;
83}
84
85bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
86 MachineBasicBlock::iterator MBBI,
87 MachineBasicBlock::iterator &NextMBBI) {
88 switch (MBBI->getOpcode()) {
89 case RISCV::PseudoAtomicLoadNand32:
90 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 32,
91 NextMBBI);
Alex Bradbury07f1c622019-01-17 10:04:39 +000092 case RISCV::PseudoAtomicLoadNand64:
93 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 64,
94 NextMBBI);
Alex Bradbury21aea512018-09-19 10:54:22 +000095 case RISCV::PseudoMaskedAtomicSwap32:
96 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, true, 32,
97 NextMBBI);
98 case RISCV::PseudoMaskedAtomicLoadAdd32:
99 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, true, 32, NextMBBI);
100 case RISCV::PseudoMaskedAtomicLoadSub32:
101 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, true, 32, NextMBBI);
102 case RISCV::PseudoMaskedAtomicLoadNand32:
103 return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, true, 32,
104 NextMBBI);
105 case RISCV::PseudoMaskedAtomicLoadMax32:
106 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Max, true, 32,
107 NextMBBI);
108 case RISCV::PseudoMaskedAtomicLoadMin32:
109 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Min, true, 32,
110 NextMBBI);
111 case RISCV::PseudoMaskedAtomicLoadUMax32:
112 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMax, true, 32,
113 NextMBBI);
114 case RISCV::PseudoMaskedAtomicLoadUMin32:
115 return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMin, true, 32,
116 NextMBBI);
Alex Bradbury66d9a752018-11-29 20:43:42 +0000117 case RISCV::PseudoCmpXchg32:
118 return expandAtomicCmpXchg(MBB, MBBI, false, 32, NextMBBI);
Alex Bradbury07f1c622019-01-17 10:04:39 +0000119 case RISCV::PseudoCmpXchg64:
120 return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI);
Alex Bradbury66d9a752018-11-29 20:43:42 +0000121 case RISCV::PseudoMaskedCmpXchg32:
122 return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI);
Alex Bradburyda20f5c2019-04-01 14:42:56 +0000123 case RISCV::PseudoLLA:
124 return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
Alex Bradbury21aea512018-09-19 10:54:22 +0000125 }
126
127 return false;
128}
129
130static unsigned getLRForRMW32(AtomicOrdering Ordering) {
131 switch (Ordering) {
132 default:
133 llvm_unreachable("Unexpected AtomicOrdering");
134 case AtomicOrdering::Monotonic:
135 return RISCV::LR_W;
136 case AtomicOrdering::Acquire:
137 return RISCV::LR_W_AQ;
138 case AtomicOrdering::Release:
139 return RISCV::LR_W;
140 case AtomicOrdering::AcquireRelease:
141 return RISCV::LR_W_AQ;
142 case AtomicOrdering::SequentiallyConsistent:
143 return RISCV::LR_W_AQ_RL;
144 }
145}
146
147static unsigned getSCForRMW32(AtomicOrdering Ordering) {
148 switch (Ordering) {
149 default:
150 llvm_unreachable("Unexpected AtomicOrdering");
151 case AtomicOrdering::Monotonic:
152 return RISCV::SC_W;
153 case AtomicOrdering::Acquire:
154 return RISCV::SC_W;
155 case AtomicOrdering::Release:
156 return RISCV::SC_W_RL;
157 case AtomicOrdering::AcquireRelease:
158 return RISCV::SC_W_RL;
159 case AtomicOrdering::SequentiallyConsistent:
160 return RISCV::SC_W_AQ_RL;
161 }
162}
163
Alex Bradbury07f1c622019-01-17 10:04:39 +0000164static unsigned getLRForRMW64(AtomicOrdering Ordering) {
165 switch (Ordering) {
166 default:
167 llvm_unreachable("Unexpected AtomicOrdering");
168 case AtomicOrdering::Monotonic:
169 return RISCV::LR_D;
170 case AtomicOrdering::Acquire:
171 return RISCV::LR_D_AQ;
172 case AtomicOrdering::Release:
173 return RISCV::LR_D;
174 case AtomicOrdering::AcquireRelease:
175 return RISCV::LR_D_AQ;
176 case AtomicOrdering::SequentiallyConsistent:
177 return RISCV::LR_D_AQ_RL;
178 }
179}
180
181static unsigned getSCForRMW64(AtomicOrdering Ordering) {
182 switch (Ordering) {
183 default:
184 llvm_unreachable("Unexpected AtomicOrdering");
185 case AtomicOrdering::Monotonic:
186 return RISCV::SC_D;
187 case AtomicOrdering::Acquire:
188 return RISCV::SC_D;
189 case AtomicOrdering::Release:
190 return RISCV::SC_D_RL;
191 case AtomicOrdering::AcquireRelease:
192 return RISCV::SC_D_RL;
193 case AtomicOrdering::SequentiallyConsistent:
194 return RISCV::SC_D_AQ_RL;
195 }
196}
197
198static unsigned getLRForRMW(AtomicOrdering Ordering, int Width) {
199 if (Width == 32)
200 return getLRForRMW32(Ordering);
201 if (Width == 64)
202 return getLRForRMW64(Ordering);
203 llvm_unreachable("Unexpected LR width\n");
204}
205
206static unsigned getSCForRMW(AtomicOrdering Ordering, int Width) {
207 if (Width == 32)
208 return getSCForRMW32(Ordering);
209 if (Width == 64)
210 return getSCForRMW64(Ordering);
211 llvm_unreachable("Unexpected SC width\n");
212}
213
Alex Bradbury21aea512018-09-19 10:54:22 +0000214static void doAtomicBinOpExpansion(const RISCVInstrInfo *TII, MachineInstr &MI,
215 DebugLoc DL, MachineBasicBlock *ThisMBB,
216 MachineBasicBlock *LoopMBB,
217 MachineBasicBlock *DoneMBB,
218 AtomicRMWInst::BinOp BinOp, int Width) {
Alex Bradbury21aea512018-09-19 10:54:22 +0000219 unsigned DestReg = MI.getOperand(0).getReg();
220 unsigned ScratchReg = MI.getOperand(1).getReg();
221 unsigned AddrReg = MI.getOperand(2).getReg();
222 unsigned IncrReg = MI.getOperand(3).getReg();
223 AtomicOrdering Ordering =
224 static_cast<AtomicOrdering>(MI.getOperand(4).getImm());
225
226 // .loop:
Alex Bradbury07f1c622019-01-17 10:04:39 +0000227 // lr.[w|d] dest, (addr)
Alex Bradbury21aea512018-09-19 10:54:22 +0000228 // binop scratch, dest, val
Alex Bradbury07f1c622019-01-17 10:04:39 +0000229 // sc.[w|d] scratch, scratch, (addr)
Alex Bradbury21aea512018-09-19 10:54:22 +0000230 // bnez scratch, loop
Alex Bradbury07f1c622019-01-17 10:04:39 +0000231 BuildMI(LoopMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg)
Alex Bradbury21aea512018-09-19 10:54:22 +0000232 .addReg(AddrReg);
233 switch (BinOp) {
234 default:
235 llvm_unreachable("Unexpected AtomicRMW BinOp");
236 case AtomicRMWInst::Nand:
237 BuildMI(LoopMBB, DL, TII->get(RISCV::AND), ScratchReg)
238 .addReg(DestReg)
239 .addReg(IncrReg);
240 BuildMI(LoopMBB, DL, TII->get(RISCV::XORI), ScratchReg)
241 .addReg(ScratchReg)
242 .addImm(-1);
243 break;
244 }
Alex Bradbury07f1c622019-01-17 10:04:39 +0000245 BuildMI(LoopMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg)
Alex Bradbury21aea512018-09-19 10:54:22 +0000246 .addReg(AddrReg)
247 .addReg(ScratchReg);
248 BuildMI(LoopMBB, DL, TII->get(RISCV::BNE))
249 .addReg(ScratchReg)
250 .addReg(RISCV::X0)
251 .addMBB(LoopMBB);
252}
253
254static void insertMaskedMerge(const RISCVInstrInfo *TII, DebugLoc DL,
255 MachineBasicBlock *MBB, unsigned DestReg,
256 unsigned OldValReg, unsigned NewValReg,
257 unsigned MaskReg, unsigned ScratchReg) {
258 assert(OldValReg != ScratchReg && "OldValReg and ScratchReg must be unique");
259 assert(OldValReg != MaskReg && "OldValReg and MaskReg must be unique");
260 assert(ScratchReg != MaskReg && "ScratchReg and MaskReg must be unique");
261
262 // We select bits from newval and oldval using:
263 // https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
264 // r = oldval ^ ((oldval ^ newval) & masktargetdata);
265 BuildMI(MBB, DL, TII->get(RISCV::XOR), ScratchReg)
266 .addReg(OldValReg)
267 .addReg(NewValReg);
268 BuildMI(MBB, DL, TII->get(RISCV::AND), ScratchReg)
269 .addReg(ScratchReg)
270 .addReg(MaskReg);
271 BuildMI(MBB, DL, TII->get(RISCV::XOR), DestReg)
272 .addReg(OldValReg)
273 .addReg(ScratchReg);
274}
275
276static void doMaskedAtomicBinOpExpansion(
277 const RISCVInstrInfo *TII, MachineInstr &MI, DebugLoc DL,
278 MachineBasicBlock *ThisMBB, MachineBasicBlock *LoopMBB,
279 MachineBasicBlock *DoneMBB, AtomicRMWInst::BinOp BinOp, int Width) {
Alex Bradbury07f1c622019-01-17 10:04:39 +0000280 assert(Width == 32 && "Should never need to expand masked 64-bit operations");
Alex Bradbury21aea512018-09-19 10:54:22 +0000281 unsigned DestReg = MI.getOperand(0).getReg();
282 unsigned ScratchReg = MI.getOperand(1).getReg();
283 unsigned AddrReg = MI.getOperand(2).getReg();
284 unsigned IncrReg = MI.getOperand(3).getReg();
285 unsigned MaskReg = MI.getOperand(4).getReg();
286 AtomicOrdering Ordering =
287 static_cast<AtomicOrdering>(MI.getOperand(5).getImm());
288
289 // .loop:
290 // lr.w destreg, (alignedaddr)
291 // binop scratch, destreg, incr
292 // xor scratch, destreg, scratch
293 // and scratch, scratch, masktargetdata
294 // xor scratch, destreg, scratch
295 // sc.w scratch, scratch, (alignedaddr)
296 // bnez scratch, loop
297 BuildMI(LoopMBB, DL, TII->get(getLRForRMW32(Ordering)), DestReg)
298 .addReg(AddrReg);
299 switch (BinOp) {
300 default:
301 llvm_unreachable("Unexpected AtomicRMW BinOp");
302 case AtomicRMWInst::Xchg:
303 BuildMI(LoopMBB, DL, TII->get(RISCV::ADD), ScratchReg)
304 .addReg(RISCV::X0)
305 .addReg(IncrReg);
306 break;
307 case AtomicRMWInst::Add:
308 BuildMI(LoopMBB, DL, TII->get(RISCV::ADD), ScratchReg)
309 .addReg(DestReg)
310 .addReg(IncrReg);
311 break;
312 case AtomicRMWInst::Sub:
313 BuildMI(LoopMBB, DL, TII->get(RISCV::SUB), ScratchReg)
314 .addReg(DestReg)
315 .addReg(IncrReg);
316 break;
317 case AtomicRMWInst::Nand:
318 BuildMI(LoopMBB, DL, TII->get(RISCV::AND), ScratchReg)
319 .addReg(DestReg)
320 .addReg(IncrReg);
321 BuildMI(LoopMBB, DL, TII->get(RISCV::XORI), ScratchReg)
322 .addReg(ScratchReg)
323 .addImm(-1);
324 break;
325 }
326
327 insertMaskedMerge(TII, DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,
328 ScratchReg);
329
330 BuildMI(LoopMBB, DL, TII->get(getSCForRMW32(Ordering)), ScratchReg)
331 .addReg(AddrReg)
332 .addReg(ScratchReg);
333 BuildMI(LoopMBB, DL, TII->get(RISCV::BNE))
334 .addReg(ScratchReg)
335 .addReg(RISCV::X0)
336 .addMBB(LoopMBB);
337}
338
339bool RISCVExpandPseudo::expandAtomicBinOp(
340 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
341 AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
342 MachineBasicBlock::iterator &NextMBBI) {
343 MachineInstr &MI = *MBBI;
344 DebugLoc DL = MI.getDebugLoc();
345
346 MachineFunction *MF = MBB.getParent();
347 auto LoopMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
348 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
349
350 // Insert new MBBs.
351 MF->insert(++MBB.getIterator(), LoopMBB);
352 MF->insert(++LoopMBB->getIterator(), DoneMBB);
353
354 // Set up successors and transfer remaining instructions to DoneMBB.
355 LoopMBB->addSuccessor(LoopMBB);
356 LoopMBB->addSuccessor(DoneMBB);
357 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
358 DoneMBB->transferSuccessors(&MBB);
359 MBB.addSuccessor(LoopMBB);
360
361 if (!IsMasked)
362 doAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp, Width);
363 else
364 doMaskedAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp,
365 Width);
366
367 NextMBBI = MBB.end();
368 MI.eraseFromParent();
369
370 LivePhysRegs LiveRegs;
371 computeAndAddLiveIns(LiveRegs, *LoopMBB);
372 computeAndAddLiveIns(LiveRegs, *DoneMBB);
373
374 return true;
375}
376
377static void insertSext(const RISCVInstrInfo *TII, DebugLoc DL,
378 MachineBasicBlock *MBB, unsigned ValReg,
379 unsigned ShamtReg) {
380 BuildMI(MBB, DL, TII->get(RISCV::SLL), ValReg)
381 .addReg(ValReg)
382 .addReg(ShamtReg);
383 BuildMI(MBB, DL, TII->get(RISCV::SRA), ValReg)
384 .addReg(ValReg)
385 .addReg(ShamtReg);
386}
387
388bool RISCVExpandPseudo::expandAtomicMinMaxOp(
389 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
390 AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
391 MachineBasicBlock::iterator &NextMBBI) {
392 assert(IsMasked == true &&
393 "Should only need to expand masked atomic max/min");
Alex Bradbury07f1c622019-01-17 10:04:39 +0000394 assert(Width == 32 && "Should never need to expand masked 64-bit operations");
Alex Bradbury21aea512018-09-19 10:54:22 +0000395
396 MachineInstr &MI = *MBBI;
397 DebugLoc DL = MI.getDebugLoc();
398 MachineFunction *MF = MBB.getParent();
399 auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
400 auto LoopIfBodyMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
401 auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
402 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
403
404 // Insert new MBBs.
405 MF->insert(++MBB.getIterator(), LoopHeadMBB);
406 MF->insert(++LoopHeadMBB->getIterator(), LoopIfBodyMBB);
407 MF->insert(++LoopIfBodyMBB->getIterator(), LoopTailMBB);
408 MF->insert(++LoopTailMBB->getIterator(), DoneMBB);
409
410 // Set up successors and transfer remaining instructions to DoneMBB.
411 LoopHeadMBB->addSuccessor(LoopIfBodyMBB);
412 LoopHeadMBB->addSuccessor(LoopTailMBB);
413 LoopIfBodyMBB->addSuccessor(LoopTailMBB);
414 LoopTailMBB->addSuccessor(LoopHeadMBB);
415 LoopTailMBB->addSuccessor(DoneMBB);
416 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
417 DoneMBB->transferSuccessors(&MBB);
418 MBB.addSuccessor(LoopHeadMBB);
419
420 unsigned DestReg = MI.getOperand(0).getReg();
421 unsigned Scratch1Reg = MI.getOperand(1).getReg();
422 unsigned Scratch2Reg = MI.getOperand(2).getReg();
423 unsigned AddrReg = MI.getOperand(3).getReg();
424 unsigned IncrReg = MI.getOperand(4).getReg();
425 unsigned MaskReg = MI.getOperand(5).getReg();
426 bool IsSigned = BinOp == AtomicRMWInst::Min || BinOp == AtomicRMWInst::Max;
427 AtomicOrdering Ordering =
428 static_cast<AtomicOrdering>(MI.getOperand(IsSigned ? 7 : 6).getImm());
429
430 //
431 // .loophead:
432 // lr.w destreg, (alignedaddr)
433 // and scratch2, destreg, mask
434 // mv scratch1, destreg
435 // [sext scratch2 if signed min/max]
436 // ifnochangeneeded scratch2, incr, .looptail
437 BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW32(Ordering)), DestReg)
438 .addReg(AddrReg);
439 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::AND), Scratch2Reg)
440 .addReg(DestReg)
441 .addReg(MaskReg);
442 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::ADDI), Scratch1Reg)
443 .addReg(DestReg)
444 .addImm(0);
445
446 switch (BinOp) {
447 default:
448 llvm_unreachable("Unexpected AtomicRMW BinOp");
449 case AtomicRMWInst::Max: {
450 insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
451 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGE))
452 .addReg(Scratch2Reg)
453 .addReg(IncrReg)
454 .addMBB(LoopTailMBB);
455 break;
456 }
457 case AtomicRMWInst::Min: {
458 insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
459 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGE))
460 .addReg(IncrReg)
461 .addReg(Scratch2Reg)
462 .addMBB(LoopTailMBB);
463 break;
464 }
465 case AtomicRMWInst::UMax:
466 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGEU))
467 .addReg(Scratch2Reg)
468 .addReg(IncrReg)
469 .addMBB(LoopTailMBB);
470 break;
471 case AtomicRMWInst::UMin:
472 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGEU))
473 .addReg(IncrReg)
474 .addReg(Scratch2Reg)
475 .addMBB(LoopTailMBB);
476 break;
477 }
478
479 // .loopifbody:
480 // xor scratch1, destreg, incr
481 // and scratch1, scratch1, mask
482 // xor scratch1, destreg, scratch1
483 insertMaskedMerge(TII, DL, LoopIfBodyMBB, Scratch1Reg, DestReg, IncrReg,
484 MaskReg, Scratch1Reg);
485
486 // .looptail:
487 // sc.w scratch1, scratch1, (addr)
488 // bnez scratch1, loop
489 BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW32(Ordering)), Scratch1Reg)
490 .addReg(AddrReg)
491 .addReg(Scratch1Reg);
492 BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE))
493 .addReg(Scratch1Reg)
494 .addReg(RISCV::X0)
495 .addMBB(LoopHeadMBB);
496
497 NextMBBI = MBB.end();
498 MI.eraseFromParent();
499
500 LivePhysRegs LiveRegs;
501 computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
502 computeAndAddLiveIns(LiveRegs, *LoopIfBodyMBB);
503 computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
504 computeAndAddLiveIns(LiveRegs, *DoneMBB);
505
506 return true;
507}
508
Alex Bradbury66d9a752018-11-29 20:43:42 +0000509bool RISCVExpandPseudo::expandAtomicCmpXchg(
510 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked,
511 int Width, MachineBasicBlock::iterator &NextMBBI) {
Alex Bradbury66d9a752018-11-29 20:43:42 +0000512 MachineInstr &MI = *MBBI;
513 DebugLoc DL = MI.getDebugLoc();
514 MachineFunction *MF = MBB.getParent();
515 auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
516 auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
517 auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
518
519 // Insert new MBBs.
520 MF->insert(++MBB.getIterator(), LoopHeadMBB);
521 MF->insert(++LoopHeadMBB->getIterator(), LoopTailMBB);
522 MF->insert(++LoopTailMBB->getIterator(), DoneMBB);
523
524 // Set up successors and transfer remaining instructions to DoneMBB.
525 LoopHeadMBB->addSuccessor(LoopTailMBB);
526 LoopHeadMBB->addSuccessor(DoneMBB);
527 LoopTailMBB->addSuccessor(DoneMBB);
528 LoopTailMBB->addSuccessor(LoopHeadMBB);
529 DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
530 DoneMBB->transferSuccessors(&MBB);
531 MBB.addSuccessor(LoopHeadMBB);
532
533 unsigned DestReg = MI.getOperand(0).getReg();
534 unsigned ScratchReg = MI.getOperand(1).getReg();
535 unsigned AddrReg = MI.getOperand(2).getReg();
536 unsigned CmpValReg = MI.getOperand(3).getReg();
537 unsigned NewValReg = MI.getOperand(4).getReg();
538 AtomicOrdering Ordering =
539 static_cast<AtomicOrdering>(MI.getOperand(IsMasked ? 6 : 5).getImm());
540
541 if (!IsMasked) {
542 // .loophead:
Alex Bradbury07f1c622019-01-17 10:04:39 +0000543 // lr.[w|d] dest, (addr)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000544 // bne dest, cmpval, done
Alex Bradbury07f1c622019-01-17 10:04:39 +0000545 BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000546 .addReg(AddrReg);
547 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BNE))
548 .addReg(DestReg)
549 .addReg(CmpValReg)
550 .addMBB(DoneMBB);
551 // .looptail:
Alex Bradbury07f1c622019-01-17 10:04:39 +0000552 // sc.[w|d] scratch, newval, (addr)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000553 // bnez scratch, loophead
Alex Bradbury07f1c622019-01-17 10:04:39 +0000554 BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000555 .addReg(AddrReg)
556 .addReg(NewValReg);
557 BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE))
558 .addReg(ScratchReg)
559 .addReg(RISCV::X0)
560 .addMBB(LoopHeadMBB);
561 } else {
562 // .loophead:
563 // lr.w dest, (addr)
564 // and scratch, dest, mask
565 // bne scratch, cmpval, done
566 unsigned MaskReg = MI.getOperand(5).getReg();
Alex Bradbury07f1c622019-01-17 10:04:39 +0000567 BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000568 .addReg(AddrReg);
569 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::AND), ScratchReg)
570 .addReg(DestReg)
571 .addReg(MaskReg);
572 BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BNE))
573 .addReg(ScratchReg)
574 .addReg(CmpValReg)
575 .addMBB(DoneMBB);
576
577 // .looptail:
578 // xor scratch, dest, newval
579 // and scratch, scratch, mask
580 // xor scratch, dest, scratch
581 // sc.w scratch, scratch, (adrr)
582 // bnez scratch, loophead
583 insertMaskedMerge(TII, DL, LoopTailMBB, ScratchReg, DestReg, NewValReg,
584 MaskReg, ScratchReg);
Alex Bradbury07f1c622019-01-17 10:04:39 +0000585 BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg)
Alex Bradbury66d9a752018-11-29 20:43:42 +0000586 .addReg(AddrReg)
587 .addReg(ScratchReg);
588 BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE))
589 .addReg(ScratchReg)
590 .addReg(RISCV::X0)
591 .addMBB(LoopHeadMBB);
592 }
593
594 NextMBBI = MBB.end();
595 MI.eraseFromParent();
596
597 LivePhysRegs LiveRegs;
598 computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
599 computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
600 computeAndAddLiveIns(LiveRegs, *DoneMBB);
601
602 return true;
603}
604
Alex Bradburyda20f5c2019-04-01 14:42:56 +0000605bool RISCVExpandPseudo::expandLoadLocalAddress(
606 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
607 MachineBasicBlock::iterator &NextMBBI) {
608 MachineFunction *MF = MBB.getParent();
609 MachineInstr &MI = *MBBI;
610 DebugLoc DL = MI.getDebugLoc();
611
612 unsigned DestReg = MI.getOperand(0).getReg();
613 const MachineOperand &Symbol = MI.getOperand(1);
614
615 MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
616
617 // Tell AsmPrinter that we unconditionally want the symbol of this label to be
618 // emitted.
619 NewMBB->setLabelMustBeEmitted();
620
621 MF->insert(++MBB.getIterator(), NewMBB);
622
623 BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg)
624 .addDisp(Symbol, 0, RISCVII::MO_PCREL_HI);
625 BuildMI(NewMBB, DL, TII->get(RISCV::ADDI), DestReg)
626 .addReg(DestReg)
627 .addMBB(NewMBB, RISCVII::MO_PCREL_LO);
628
629 // Move all the rest of the instructions to NewMBB.
630 NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end());
631 // Update machine-CFG edges.
632 NewMBB->transferSuccessorsAndUpdatePHIs(&MBB);
633 // Make the original basic block fall-through to the new.
634 MBB.addSuccessor(NewMBB);
635
636 // Make sure live-ins are correctly attached to this new basic block.
637 LivePhysRegs LiveRegs;
638 computeAndAddLiveIns(LiveRegs, *NewMBB);
639
640 NextMBBI = MBB.end();
641 MI.eraseFromParent();
642 return true;
643}
644
Alex Bradbury21aea512018-09-19 10:54:22 +0000645} // end of anonymous namespace
646
647INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
648 RISCV_EXPAND_PSEUDO_NAME, false, false)
649namespace llvm {
650
651FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
652
653} // end of namespace llvm