From ed372d194f938b750855ad1297517d26f1102250 Mon Sep 17 00:00:00 2001 From: Min-Yih Hsu Date: Mon, 27 Mar 2023 10:27:27 -0700 Subject: [PATCH] [M68k] Add support for lowering atomic fence Ideally we want to lower ATOMIC_FENCE into `__sync_synchronize`. However, libgcc doesn't implement that builtin as GCC simply generates an inline assembly barrier whenever there needs to be a fence. We use a similar way to lower ATOMIC_FENCE. Differential Revision: https://reviews.llvm.org/D146996 --- llvm/lib/Target/M68k/M68kISelLowering.cpp | 26 ++++++++++++++++++++++++++ llvm/lib/Target/M68k/M68kISelLowering.h | 2 ++ llvm/test/CodeGen/M68k/Atomics/fence.ll | 27 +++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 llvm/test/CodeGen/M68k/Atomics/fence.ll diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp index c49b83f..d261be6 100644 --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -163,6 +163,8 @@ M68kTargetLowering::M68kTargetLowering(const M68kTargetMachine &TM, 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 @@ SDValue M68kTargetLowering::LowerOperation(SDValue Op, 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 @@ SDValue M68kTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { 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 diff --git a/llvm/lib/Target/M68k/M68kISelLowering.h b/llvm/lib/Target/M68k/M68kISelLowering.h index f998f60..bffb119 100644 --- a/llvm/lib/Target/M68k/M68kISelLowering.h +++ b/llvm/lib/Target/M68k/M68kISelLowering.h @@ -238,6 +238,8 @@ private: 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, diff --git a/llvm/test/CodeGen/M68k/Atomics/fence.ll b/llvm/test/CodeGen/M68k/Atomics/fence.ll new file mode 100644 index 0000000..23318ac --- /dev/null +++ b/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 +} + -- 2.7.4