@@ -52,6 +52,9 @@ class RISCVExpandPseudo : public MachineFunctionPass {
52
52
MachineBasicBlock::iterator MBBI,
53
53
AtomicRMWInst::BinOp, bool IsMasked, int Width,
54
54
MachineBasicBlock::iterator &NextMBBI);
55
+ bool expandAtomicCmpXchg (MachineBasicBlock &MBB,
56
+ MachineBasicBlock::iterator MBBI, bool IsMasked,
57
+ int Width, MachineBasicBlock::iterator &NextMBBI);
55
58
};
56
59
57
60
char RISCVExpandPseudo::ID = 0 ;
@@ -106,6 +109,10 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
106
109
case RISCV::PseudoMaskedAtomicLoadUMin32:
107
110
return expandAtomicMinMaxOp (MBB, MBBI, AtomicRMWInst::UMin, true , 32 ,
108
111
NextMBBI);
112
+ case RISCV::PseudoCmpXchg32:
113
+ return expandAtomicCmpXchg (MBB, MBBI, false , 32 , NextMBBI);
114
+ case RISCV::PseudoMaskedCmpXchg32:
115
+ return expandAtomicCmpXchg (MBB, MBBI, true , 32 , NextMBBI);
109
116
}
110
117
111
118
return false ;
@@ -441,6 +448,103 @@ bool RISCVExpandPseudo::expandAtomicMinMaxOp(
441
448
return true ;
442
449
}
443
450
451
+ bool RISCVExpandPseudo::expandAtomicCmpXchg (
452
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked,
453
+ int Width, MachineBasicBlock::iterator &NextMBBI) {
454
+ assert (Width == 32 && " RV64 atomic expansion currently unsupported" );
455
+ MachineInstr &MI = *MBBI;
456
+ DebugLoc DL = MI.getDebugLoc ();
457
+ MachineFunction *MF = MBB.getParent ();
458
+ auto LoopHeadMBB = MF->CreateMachineBasicBlock (MBB.getBasicBlock ());
459
+ auto LoopTailMBB = MF->CreateMachineBasicBlock (MBB.getBasicBlock ());
460
+ auto DoneMBB = MF->CreateMachineBasicBlock (MBB.getBasicBlock ());
461
+
462
+ // Insert new MBBs.
463
+ MF->insert (++MBB.getIterator (), LoopHeadMBB);
464
+ MF->insert (++LoopHeadMBB->getIterator (), LoopTailMBB);
465
+ MF->insert (++LoopTailMBB->getIterator (), DoneMBB);
466
+
467
+ // Set up successors and transfer remaining instructions to DoneMBB.
468
+ LoopHeadMBB->addSuccessor (LoopTailMBB);
469
+ LoopHeadMBB->addSuccessor (DoneMBB);
470
+ LoopTailMBB->addSuccessor (DoneMBB);
471
+ LoopTailMBB->addSuccessor (LoopHeadMBB);
472
+ DoneMBB->splice (DoneMBB->end (), &MBB, MI, MBB.end ());
473
+ DoneMBB->transferSuccessors (&MBB);
474
+ MBB.addSuccessor (LoopHeadMBB);
475
+
476
+ unsigned DestReg = MI.getOperand (0 ).getReg ();
477
+ unsigned ScratchReg = MI.getOperand (1 ).getReg ();
478
+ unsigned AddrReg = MI.getOperand (2 ).getReg ();
479
+ unsigned CmpValReg = MI.getOperand (3 ).getReg ();
480
+ unsigned NewValReg = MI.getOperand (4 ).getReg ();
481
+ AtomicOrdering Ordering =
482
+ static_cast <AtomicOrdering>(MI.getOperand (IsMasked ? 6 : 5 ).getImm ());
483
+
484
+ if (!IsMasked) {
485
+ // .loophead:
486
+ // lr.w dest, (addr)
487
+ // bne dest, cmpval, done
488
+ BuildMI (LoopHeadMBB, DL, TII->get (getLRForRMW32 (Ordering)), DestReg)
489
+ .addReg (AddrReg);
490
+ BuildMI (LoopHeadMBB, DL, TII->get (RISCV::BNE))
491
+ .addReg (DestReg)
492
+ .addReg (CmpValReg)
493
+ .addMBB (DoneMBB);
494
+ // .looptail:
495
+ // sc.w scratch, newval, (addr)
496
+ // bnez scratch, loophead
497
+ BuildMI (LoopTailMBB, DL, TII->get (getSCForRMW32 (Ordering)), ScratchReg)
498
+ .addReg (AddrReg)
499
+ .addReg (NewValReg);
500
+ BuildMI (LoopTailMBB, DL, TII->get (RISCV::BNE))
501
+ .addReg (ScratchReg)
502
+ .addReg (RISCV::X0)
503
+ .addMBB (LoopHeadMBB);
504
+ } else {
505
+ // .loophead:
506
+ // lr.w dest, (addr)
507
+ // and scratch, dest, mask
508
+ // bne scratch, cmpval, done
509
+ unsigned MaskReg = MI.getOperand (5 ).getReg ();
510
+ BuildMI (LoopHeadMBB, DL, TII->get (getLRForRMW32 (Ordering)), DestReg)
511
+ .addReg (AddrReg);
512
+ BuildMI (LoopHeadMBB, DL, TII->get (RISCV::AND), ScratchReg)
513
+ .addReg (DestReg)
514
+ .addReg (MaskReg);
515
+ BuildMI (LoopHeadMBB, DL, TII->get (RISCV::BNE))
516
+ .addReg (ScratchReg)
517
+ .addReg (CmpValReg)
518
+ .addMBB (DoneMBB);
519
+
520
+ // .looptail:
521
+ // xor scratch, dest, newval
522
+ // and scratch, scratch, mask
523
+ // xor scratch, dest, scratch
524
+ // sc.w scratch, scratch, (adrr)
525
+ // bnez scratch, loophead
526
+ insertMaskedMerge (TII, DL, LoopTailMBB, ScratchReg, DestReg, NewValReg,
527
+ MaskReg, ScratchReg);
528
+ BuildMI (LoopTailMBB, DL, TII->get (getSCForRMW32 (Ordering)), ScratchReg)
529
+ .addReg (AddrReg)
530
+ .addReg (ScratchReg);
531
+ BuildMI (LoopTailMBB, DL, TII->get (RISCV::BNE))
532
+ .addReg (ScratchReg)
533
+ .addReg (RISCV::X0)
534
+ .addMBB (LoopHeadMBB);
535
+ }
536
+
537
+ NextMBBI = MBB.end ();
538
+ MI.eraseFromParent ();
539
+
540
+ LivePhysRegs LiveRegs;
541
+ computeAndAddLiveIns (LiveRegs, *LoopHeadMBB);
542
+ computeAndAddLiveIns (LiveRegs, *LoopTailMBB);
543
+ computeAndAddLiveIns (LiveRegs, *DoneMBB);
544
+
545
+ return true ;
546
+ }
547
+
444
548
} // end of anonymous namespace
445
549
446
550
INITIALIZE_PASS (RISCVExpandPseudo, " riscv-expand-pseudo" ,
0 commit comments