Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -1057,6 +1057,9 @@ } else { // If there's anything we can use as a barrier, go through custom lowering // for ATOMIC_FENCE. + if (Subtarget->isARMv6m()) + InsertFencesForAtomic = true; + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Subtarget->hasAnyDataBarrier() ? Custom : Expand); @@ -1075,8 +1078,10 @@ setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Expand); // Mark ATOMIC_LOAD and ATOMIC_STORE custom so we can handle the // Unordered/Monotonic case. - setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); - setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); + if (!InsertFencesForAtomic) { + setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); + } } setOperationAction(ISD::PREFETCH, MVT::Other, Custom); @@ -12871,7 +12876,7 @@ TargetLowering::AtomicExpansionKind ARMTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { unsigned Size = AI->getType()->getPrimitiveSizeInBits(); - return (Size <= (Subtarget->isMClass() ? 32U : 64U)) + return (Size <= (Subtarget->isMClass() ? 32U : 64U) && !Subtarget->isARMv6m()) ? AtomicExpansionKind::LLSC : AtomicExpansionKind::None; } @@ -12883,7 +12888,7 @@ // on the stack and close enough to the spill slot, this can lead to a // situation where the monitor always gets cleared and the atomic operation // can never succeed. So at -O0 we need a late-expanded pseudo-inst instead. - return getTargetMachine().getOptLevel() != 0; + return getTargetMachine().getOptLevel() != 0 && !Subtarget->isARMv6m(); } bool ARMTargetLowering::shouldInsertFencesForAtomic( Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -421,6 +421,7 @@ bool isLikeA9() const { return isCortexA9() || isCortexA15() || isKrait(); } bool isCortexR5() const { return ARMProcFamily == CortexR5; } bool isKrait() const { return ARMProcFamily == Krait; } + bool isARMv6m() const { return ARMArch == ARMv6m; } /// @} bool hasARMOps() const { return !NoARM; } Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -320,7 +320,8 @@ } bool ARMSubtarget::enableAtomicExpand() const { - return hasAnyDataBarrier() && (!isThumb() || hasV8MBaselineOps()); + return hasAnyDataBarrier() && + (!isThumb() || hasV8MBaselineOps() || ARMArch == ARMv6m); } bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const { Index: test/CodeGen/ARM/atomic-op.ll =================================================================== --- test/CodeGen/ARM/atomic-op.ll +++ test/CodeGen/ARM/atomic-op.ll @@ -1,7 +1,7 @@ ; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix CHECK-ARMV7 ; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-T2 ; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-T1 -; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefix=CHECK-T1 +; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefix=CHECK-T1-M0 ; RUN: llc < %s -mtriple=thumbv7--none-eabi -thread-model single -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-BAREMETAL target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" @@ -319,6 +319,11 @@ ; CHECK: dmb ; CHECK: add r0, +; CHECK-T1-M0: ldr {{r[0-9]}}, [r0] +; CHECK-T1-M0: dmb +; CHECK-T1-M0: ldr {{r[0-9]}}, [r1] +; CHECK-T1-M0: dmb + ; CHECK-T1: ___sync_val_compare_and_swap_4 ; CHECK-T1: ___sync_val_compare_and_swap_4 @@ -344,6 +349,11 @@ ; CHECK-T1: ___sync_lock_test_and_set ; CHECK-T1: ___sync_lock_test_and_set +; CHECK-T1-M0: dmb +; CHECK-T1-M0: str r1, [r0] +; CHECK-T1-M0: dmb +; CHECK-T1-M0: str r3, [r2] + ; CHECK-BAREMETAL-NOT: dmb ; CHECK-BAREMTEAL: str r1, [r0] ; CHECK-BAREMETAL-NOT: dmb @@ -362,6 +372,10 @@ ; CHECK: dmb ; CHECK: str [[R0]], [r1] +; CHECK-T1-M0: ldr [[R0:r[0-9]]], [r0] +; CHECK-T1-M0: dmb +; CHECK-T1-M0: str [[R0]], [r1] + ; CHECK-T1: ldr [[R0:r[0-9]]], [{{r[0-9]+}}] ; CHECK-T1: {{dmb|bl ___sync_synchronize}} ; CHECK-T1: str [[R0]], [{{r[0-9]+}}]