@@ -59,6 +59,9 @@ class RISCVExpandAtomicPseudo : public MachineFunctionPass {
59
59
bool expandAtomicCmpXchg (MachineBasicBlock &MBB,
60
60
MachineBasicBlock::iterator MBBI, bool IsMasked,
61
61
int Width, MachineBasicBlock::iterator &NextMBBI);
62
+ bool expandAMOCAS (MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
63
+ bool IsPaired, int Width,
64
+ MachineBasicBlock::iterator &NextMBBI);
62
65
#ifndef NDEBUG
63
66
unsigned getInstSizeInBytes (const MachineFunction &MF) const {
64
67
unsigned Size = 0 ;
@@ -145,6 +148,14 @@ bool RISCVExpandAtomicPseudo::expandMI(MachineBasicBlock &MBB,
145
148
return expandAtomicCmpXchg (MBB, MBBI, false , 64 , NextMBBI);
146
149
case RISCV::PseudoMaskedCmpXchg32:
147
150
return expandAtomicCmpXchg (MBB, MBBI, true , 32 , NextMBBI);
151
+ case RISCV::PseudoAMOCAS_W:
152
+ return expandAMOCAS (MBB, MBBI, false , 32 , NextMBBI);
153
+ case RISCV::PseudoAMOCAS_D_RV64:
154
+ return expandAMOCAS (MBB, MBBI, false , 64 , NextMBBI);
155
+ case RISCV::PseudoAMOCAS_D_RV32:
156
+ return expandAMOCAS (MBB, MBBI, true , 64 , NextMBBI);
157
+ case RISCV::PseudoAMOCAS_Q:
158
+ return expandAMOCAS (MBB, MBBI, true , 128 , NextMBBI);
148
159
}
149
160
150
161
return false ;
@@ -256,6 +267,74 @@ static unsigned getSCForRMW(AtomicOrdering Ordering, int Width,
256
267
llvm_unreachable (" Unexpected SC width\n " );
257
268
}
258
269
270
+ static unsigned getAMOCASForRMW32 (AtomicOrdering Ordering,
271
+ const RISCVSubtarget *Subtarget) {
272
+ if (Subtarget->hasStdExtZtso ())
273
+ return RISCV::AMOCAS_W;
274
+ switch (Ordering) {
275
+ default :
276
+ llvm_unreachable (" Unexpected AtomicOrdering" );
277
+ case AtomicOrdering::Monotonic:
278
+ return RISCV::AMOCAS_W;
279
+ case AtomicOrdering::Acquire:
280
+ return RISCV::AMOCAS_W_AQ;
281
+ case AtomicOrdering::Release:
282
+ return RISCV::AMOCAS_W_RL;
283
+ case AtomicOrdering::AcquireRelease:
284
+ case AtomicOrdering::SequentiallyConsistent:
285
+ return RISCV::AMOCAS_W_AQ_RL;
286
+ }
287
+ }
288
+
289
+ static unsigned getAMOCASForRMW64 (AtomicOrdering Ordering,
290
+ const RISCVSubtarget *Subtarget) {
291
+ if (Subtarget->hasStdExtZtso ())
292
+ return RISCV::AMOCAS_D;
293
+ switch (Ordering) {
294
+ default :
295
+ llvm_unreachable (" Unexpected AtomicOrdering" );
296
+ case AtomicOrdering::Monotonic:
297
+ return RISCV::AMOCAS_D;
298
+ case AtomicOrdering::Acquire:
299
+ return RISCV::AMOCAS_D_AQ;
300
+ case AtomicOrdering::Release:
301
+ return RISCV::AMOCAS_D_RL;
302
+ case AtomicOrdering::AcquireRelease:
303
+ case AtomicOrdering::SequentiallyConsistent:
304
+ return RISCV::AMOCAS_D_AQ_RL;
305
+ }
306
+ }
307
+
308
+ static unsigned getAMOCASForRMW128 (AtomicOrdering Ordering,
309
+ const RISCVSubtarget *Subtarget) {
310
+ if (Subtarget->hasStdExtZtso ())
311
+ return RISCV::AMOCAS_Q;
312
+ switch (Ordering) {
313
+ default :
314
+ llvm_unreachable (" Unexpected AtomicOrdering" );
315
+ case AtomicOrdering::Monotonic:
316
+ return RISCV::AMOCAS_Q;
317
+ case AtomicOrdering::Acquire:
318
+ return RISCV::AMOCAS_Q_AQ;
319
+ case AtomicOrdering::Release:
320
+ return RISCV::AMOCAS_Q_RL;
321
+ case AtomicOrdering::AcquireRelease:
322
+ case AtomicOrdering::SequentiallyConsistent:
323
+ return RISCV::AMOCAS_Q_AQ_RL;
324
+ }
325
+ }
326
+
327
+ static unsigned getAMOCASForRMW (AtomicOrdering Ordering, int Width,
328
+ const RISCVSubtarget *Subtarget) {
329
+ if (Width == 32 )
330
+ return getAMOCASForRMW32 (Ordering, Subtarget);
331
+ if (Width == 64 )
332
+ return getAMOCASForRMW64 (Ordering, Subtarget);
333
+ if (Width == 128 )
334
+ return getAMOCASForRMW128 (Ordering, Subtarget);
335
+ llvm_unreachable (" Unexpected AMOCAS width\n " );
336
+ }
337
+
259
338
static void doAtomicBinOpExpansion (const RISCVInstrInfo *TII, MachineInstr &MI,
260
339
DebugLoc DL, MachineBasicBlock *ThisMBB,
261
340
MachineBasicBlock *LoopMBB,
@@ -728,6 +807,38 @@ bool RISCVExpandAtomicPseudo::expandAtomicCmpXchg(
728
807
return true ;
729
808
}
730
809
810
+ static Register getGPRPairEvenReg (Register PairedReg) {
811
+ assert (PairedReg >= RISCV::X0_PD && PairedReg <= RISCV::X30_PD &&
812
+ " Invalid GPR pair" );
813
+ return (PairedReg - RISCV::X0_PD) * 2 + RISCV::X0;
814
+ }
815
+
816
+ bool RISCVExpandAtomicPseudo::expandAMOCAS (
817
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsPaired,
818
+ int Width, MachineBasicBlock::iterator &NextMBBI) {
819
+ MachineInstr &MI = *MBBI;
820
+ DebugLoc DL = MI.getDebugLoc ();
821
+
822
+ Register DestReg = MI.getOperand (0 ).getReg ();
823
+ if (IsPaired)
824
+ DestReg = getGPRPairEvenReg (DestReg);
825
+ Register AddrReg = MI.getOperand (1 ).getReg ();
826
+ Register NewValReg = MI.getOperand (3 ).getReg ();
827
+ if (IsPaired)
828
+ NewValReg = getGPRPairEvenReg (NewValReg);
829
+ AtomicOrdering Ordering =
830
+ static_cast <AtomicOrdering>(MI.getOperand (4 ).getImm ());
831
+
832
+ MachineInstr *NewMI =
833
+ BuildMI (MBB, MBBI, DL, TII->get (getAMOCASForRMW (Ordering, Width, STI)))
834
+ .addReg (DestReg, RegState::Define)
835
+ .addReg (AddrReg)
836
+ .addReg (NewValReg);
837
+
838
+ MI.eraseFromParent ();
839
+ return true ;
840
+ }
841
+
731
842
} // end of anonymous namespace
732
843
733
844
INITIALIZE_PASS (RISCVExpandAtomicPseudo, " riscv-expand-atomic-pseudo" ,
0 commit comments