Index: llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -117,6 +117,10 @@ LowerHWASAN_CHECK_MEMACCESS(*MI); return; } + if (MI->getOpcode() == RISCV::Int_MemBarrier) { + OutStreamer->emitRawComment("MEMBARRIER"); + return; + } if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this)) EmitToStreamer(*OutStreamer, TmpInst); Index: llvm/lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.h +++ llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -320,6 +320,9 @@ // the value read before the modification and the new chain pointer. SWAP_CSR, + // Compiler barrier only; generate a no-op. + MEMBARRIER, + // FP to 32 bit int conversions for RV64. These are used to keep track of the // result being sign extended to 64 bit. These saturate out of range inputs. STRICT_FCVT_W_RV64 = ISD::FIRST_TARGET_STRICTFP_OPCODE, Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ 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,29 @@ 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 handles 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(RISCVISD::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: @@ -13158,6 +13178,7 @@ NODE_NAME_CASE(READ_CSR) NODE_NAME_CASE(WRITE_CSR) NODE_NAME_CASE(SWAP_CSR) + NODE_NAME_CASE(MEMBARRIER) } // clang-format on return nullptr; Index: llvm/lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1841,6 +1841,14 @@ (AddiPairImmSmall AddiPair:$rs2))>; } +def SDT_RISCVMEMBARRIER : SDTypeProfile<0, 0, []>; +def RISCVMemBarrier : SDNode<"RISCVISD::MEMBARRIER", SDT_RISCVMEMBARRIER, + [SDNPHasChain,SDNPSideEffect]>; + +let hasSideEffects = 1, isMeta = 1 in +def Int_MemBarrier : Pseudo<(outs), (ins), + [(RISCVMemBarrier)]>; + //===----------------------------------------------------------------------===// // Standard extensions //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/RISCV/atomic-fence.ll =================================================================== --- llvm/test/CodeGen/RISCV/atomic-fence.ll +++ llvm/test/CodeGen/RISCV/atomic-fence.ll @@ -47,7 +47,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 @@ -56,7 +56,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 @@ -65,7 +65,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 @@ -74,7 +74,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