Index: llvm/lib/Target/M68k/M68kISelLowering.h =================================================================== --- llvm/lib/Target/M68k/M68kISelLowering.h +++ llvm/lib/Target/M68k/M68kISelLowering.h @@ -238,6 +238,8 @@ SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; + SDValue LowerATOMICFENCE(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl &Ins, Index: llvm/lib/Target/M68k/M68kISelLowering.cpp =================================================================== --- llvm/lib/Target/M68k/M68kISelLowering.cpp +++ llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -163,6 +163,8 @@ setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i8, MVT::i16, MVT::i32}, Subtarget.atLeastM68020() ? Legal : LibCall); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + // M68k does not have native read-modify-write support, so expand all of them // to `__sync_fetch_*` for target < M68020, otherwise expand to CmpxChg. // See `shouldExpandAtomicRMWInIR` below. @@ -1408,6 +1410,8 @@ return LowerShiftRightParts(Op, DAG, true); case ISD::SRL_PARTS: return LowerShiftRightParts(Op, DAG, false); + case ISD::ATOMIC_FENCE: + return LowerATOMICFENCE(Op, DAG); } } @@ -3240,6 +3244,28 @@ MachinePointerInfo(SV)); } +SDValue M68kTargetLowering::LowerATOMICFENCE(SDValue Op, + SelectionDAG &DAG) const { + // Lower to a memory barrier created from inline asm. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + LLVMContext &Ctx = *DAG.getContext(); + + const unsigned Flags = InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore | + InlineAsm::Extra_HasSideEffects; + const SDValue AsmOperands[4] = { + Op.getOperand(0), // Input chain + DAG.getTargetExternalSymbol( + "", TLI.getProgramPointerTy( + DAG.getDataLayout())), // Empty inline asm string + DAG.getMDNode(MDNode::get(Ctx, {})), // (empty) srcloc + DAG.getTargetConstant(Flags, SDLoc(Op), + TLI.getPointerTy(DAG.getDataLayout())), // Flags + }; + + return DAG.getNode(ISD::INLINEASM, SDLoc(Op), + DAG.getVTList(MVT::Other, MVT::Glue), AsmOperands); +} + // Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets. // Calls to _alloca are needed to probe the stack when allocating more than 4k // bytes in one go. Touching the stack at 4K increments is necessary to ensure Index: llvm/test/CodeGen/M68k/Atomics/fence.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/Atomics/fence.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=m68k-linux-gnu < %s | FileCheck %s + +; M68k's libgcc does NOT have __sync_synchronize so we shouldn't +; lower to that. + +define void @atomic_fence() { +; CHECK-LABEL: atomic_fence: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: ; %entry +; CHECK-NEXT: ;APP +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: ;APP +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: ;APP +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: ;APP +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: rts +entry: + fence acquire + fence release + fence acq_rel + fence seq_cst + ret void +} +