diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -116,6 +116,9 @@ case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES: LowerHWASAN_CHECK_MEMACCESS(*MI); return; + case RISCV::PseudoMemBarrier: + OutStreamer->emitRawComment("MEMBARRIER"); + return; } MCInst TmpInst; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -461,6 +461,8 @@ setMaxAtomicSizeInBitsSupported(0); } + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + setBooleanContents(ZeroOrOneBooleanContent); if (Subtarget.hasVInstructions()) { @@ -3667,11 +3669,28 @@ return SDValue(); } +static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) { + SDLoc dl(Op); + SyncScope::ID FenceSSID = + static_cast(Op.getConstantOperandVal(2)); + + // singlethread fences only synchronize with signal handlers on the same + // thread and thus only need to preserve instruction order, not actually + // enforce memory ordering. + if (FenceSSID == SyncScope::SingleThread) + // MEMBARRIER is a compiler barrier; it codegens to a no-op. + return DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0)); + + return Op; +} + SDValue RISCVTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { default: report_fatal_error("unimplemented operand"); + case ISD::ATOMIC_FENCE: + return LowerATOMIC_FENCE(Op, DAG); case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG); case ISD::BlockAddress: diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1843,6 +1843,9 @@ (AddiPairImmSmall AddiPair:$rs2))>; } +let hasSideEffects = 1, isMeta = 1 in +def PseudoMemBarrier : Pseudo<(outs), (ins), [(membarrier)]>; + //===----------------------------------------------------------------------===// // Standard extensions //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/RISCV/atomic-fence.ll b/llvm/test/CodeGen/RISCV/atomic-fence.ll --- a/llvm/test/CodeGen/RISCV/atomic-fence.ll +++ b/llvm/test/CodeGen/RISCV/atomic-fence.ll @@ -51,7 +51,7 @@ define void @fence_singlethread_acquire() nounwind { ; CHECK-LABEL: fence_singlethread_acquire: ; CHECK: # %bb.0: -; CHECK-NEXT: fence r, rw +; CHECK-NEXT: #MEMBARRIER ; CHECK-NEXT: ret fence syncscope("singlethread") acquire ret void @@ -60,7 +60,7 @@ define void @fence_singlethread_release() nounwind { ; CHECK-LABEL: fence_singlethread_release: ; CHECK: # %bb.0: -; CHECK-NEXT: fence rw, w +; CHECK-NEXT: #MEMBARRIER ; CHECK-NEXT: ret fence syncscope("singlethread") release ret void @@ -69,7 +69,7 @@ define void @fence_singlethread_acq_rel() nounwind { ; CHECK-LABEL: fence_singlethread_acq_rel: ; CHECK: # %bb.0: -; CHECK-NEXT: fence.tso +; CHECK-NEXT: #MEMBARRIER ; CHECK-NEXT: ret fence syncscope("singlethread") acq_rel ret void @@ -78,7 +78,7 @@ define void @fence_singlethread_seq_cst() nounwind { ; CHECK-LABEL: fence_singlethread_seq_cst: ; CHECK: # %bb.0: -; CHECK-NEXT: fence rw, rw +; CHECK-NEXT: #MEMBARRIER ; CHECK-NEXT: ret fence syncscope("singlethread") seq_cst ret void