@@ -48,6 +48,9 @@ class RISCVExpandAtomicPseudo : public MachineFunctionPass {
4848 bool expandMBB (MachineBasicBlock &MBB);
4949 bool expandMI (MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
5050 MachineBasicBlock::iterator &NextMBBI);
51+ bool expandAtomicLoadStore (MachineBasicBlock &MBB,
52+ MachineBasicBlock::iterator MBBI,
53+ unsigned int Opcode, bool IsLoad);
5154 bool expandAtomicBinOp (MachineBasicBlock &MBB,
5255 MachineBasicBlock::iterator MBBI, AtomicRMWInst::BinOp,
5356 bool IsMasked, int Width,
@@ -111,6 +114,22 @@ bool RISCVExpandAtomicPseudo::expandMI(MachineBasicBlock &MBB,
111114 // expanded instructions for each pseudo is correct in the Size field of the
112115 // tablegen definition for the pseudo.
113116 switch (MBBI->getOpcode ()) {
117+ case RISCV::PseudoAtomicLB:
118+ return expandAtomicLoadStore (MBB, MBBI, RISCV::LB, true );
119+ case RISCV::PseudoAtomicLH:
120+ return expandAtomicLoadStore (MBB, MBBI, RISCV::LH, true );
121+ case RISCV::PseudoAtomicLW:
122+ return expandAtomicLoadStore (MBB, MBBI, RISCV::LW, true );
123+ case RISCV::PseudoAtomicLD:
124+ return expandAtomicLoadStore (MBB, MBBI, RISCV::LD, true );
125+ case RISCV::PseudoAtomicSB:
126+ return expandAtomicLoadStore (MBB, MBBI, RISCV::SB, false );
127+ case RISCV::PseudoAtomicSH:
128+ return expandAtomicLoadStore (MBB, MBBI, RISCV::SH, false );
129+ case RISCV::PseudoAtomicSW:
130+ return expandAtomicLoadStore (MBB, MBBI, RISCV::SW, false );
131+ case RISCV::PseudoAtomicSD:
132+ return expandAtomicLoadStore (MBB, MBBI, RISCV::SD, false );
114133 case RISCV::PseudoAtomicLoadNand32:
115134 return expandAtomicBinOp (MBB, MBBI, AtomicRMWInst::Nand, false , 32 ,
116135 NextMBBI);
@@ -385,6 +404,91 @@ static void doMaskedAtomicBinOpExpansion(const RISCVInstrInfo *TII,
385404 .addMBB (LoopMBB);
386405}
387406
407+ static void insertFence (const RISCVInstrInfo *TII, MachineBasicBlock &MBB,
408+ MachineBasicBlock::iterator MBBI, DebugLoc DL,
409+ AtomicOrdering Ordering) {
410+ // fence acq_rel -> fence.tso
411+ if (Ordering == AtomicOrdering::AcquireRelease) {
412+ BuildMI (MBB, MBBI, DL, TII->get (RISCV::FENCE_TSO));
413+ } else {
414+ int Pred, Succ;
415+ switch (Ordering) {
416+ default :
417+ llvm_unreachable (" Unsupported AtomicOrdering" );
418+ case AtomicOrdering::Acquire:
419+ // fence acquire -> fence r, rw
420+ Pred = 0b10 ;
421+ Succ = 0b11 ;
422+ break ;
423+ case AtomicOrdering::Release:
424+ // fence release -> fence rw, w
425+ Pred = 0b11 ;
426+ Succ = 0b01 ;
427+ break ;
428+ case AtomicOrdering::SequentiallyConsistent:
429+ // fence seq_cst -> fence rw, rw
430+ Pred = 0b11 ;
431+ Succ = 0b11 ;
432+ break ;
433+ }
434+ BuildMI (MBB, MBBI, DL, TII->get (RISCV::FENCE)).addImm (Pred).addImm (Succ);
435+ }
436+ }
437+
438+ static void emitLeadingFence (const RISCVSubtarget *Subtarget,
439+ const RISCVInstrInfo *TII, MachineBasicBlock &MBB,
440+ MachineBasicBlock::iterator MBBI, DebugLoc DL,
441+ AtomicOrdering Ordering, bool IsLoad) {
442+ if (Subtarget->hasStdExtZtso ()) {
443+ if (IsLoad && Ordering == AtomicOrdering::SequentiallyConsistent)
444+ insertFence (TII, MBB, MBBI, DL, Ordering);
445+ return ;
446+ }
447+
448+ if (IsLoad && Ordering == AtomicOrdering::SequentiallyConsistent) {
449+ insertFence (TII, MBB, MBBI, DL, Ordering);
450+ return ;
451+ }
452+
453+ if (!IsLoad && isReleaseOrStronger (Ordering))
454+ insertFence (TII, MBB, MBBI, DL, AtomicOrdering::Release);
455+ }
456+
457+ static void emitTrailingFence (const RISCVSubtarget *Subtarget,
458+ const RISCVInstrInfo *TII, MachineBasicBlock &MBB,
459+ MachineBasicBlock::iterator MBBI, DebugLoc DL,
460+ AtomicOrdering Ordering, bool IsLoad) {
461+ if (Subtarget->hasStdExtZtso ()) {
462+ if (!IsLoad && Ordering == AtomicOrdering::SequentiallyConsistent)
463+ insertFence (TII, MBB, MBBI, DL, Ordering);
464+ return ;
465+ }
466+
467+ if (IsLoad && isAcquireOrStronger (Ordering)) {
468+ insertFence (TII, MBB, MBBI, DL, AtomicOrdering::Acquire);
469+ return ;
470+ }
471+
472+ if (Subtarget->enableSeqCstTrailingFence () && !IsLoad &&
473+ Ordering == AtomicOrdering::SequentiallyConsistent)
474+ insertFence (TII, MBB, MBBI, DL, AtomicOrdering::SequentiallyConsistent);
475+ }
476+
477+ bool RISCVExpandAtomicPseudo::expandAtomicLoadStore (
478+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
479+ unsigned int Opcode, bool IsLoad) {
480+ auto Ordering = static_cast <AtomicOrdering>(MBBI->getOperand (3 ).getImm ());
481+ DebugLoc DL = MBBI->getDebugLoc ();
482+ emitLeadingFence (STI, TII, MBB, MBBI, DL, Ordering, IsLoad);
483+ BuildMI (MBB, MBBI, DL, TII->get (Opcode))
484+ .add (MBBI->getOperand (0 ))
485+ .add (MBBI->getOperand (1 ))
486+ .add (MBBI->getOperand (2 ));
487+ emitTrailingFence (STI, TII, MBB, MBBI, DL, Ordering, IsLoad);
488+ MBBI->eraseFromParent ();
489+ return true ;
490+ }
491+
388492bool RISCVExpandAtomicPseudo::expandAtomicBinOp (
389493 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
390494 AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
@@ -554,7 +658,7 @@ bool RISCVExpandAtomicPseudo::expandAtomicMinMaxOp(
554658 computeAndAddLiveIns (LiveRegs, *DoneMBB);
555659
556660 return true ;
557- }
661+ }
558662
559663// If a BNE on the cmpxchg comparison result immediately follows the cmpxchg
560664// operation, it can be folded into the cmpxchg expansion by
0 commit comments