r212598 - ARM: use LLVM's atomicrmw instructions when ldrex/strex are available.
Tim Northover
tnorthover at apple.com
Wed Jul 9 02:24:43 PDT 2014
Author: tnorthover
Date: Wed Jul 9 04:24:43 2014
New Revision: 212598
URL: http://llvm.org/viewvc/llvm-project?rev=212598&view=rev
Log:
ARM: use LLVM's atomicrmw instructions when ldrex/strex are available.
Having some kind of weird kernel-assisted ABI for these when the
native instructions are available appears to be (and should be) the
exception; OSs have been gradually opting in for years and the code
was getting silly.
So let LLVM decide whether it's possible/profitable to inline them by
default.
Patch by Phoebe Buckheister.
Added:
cfe/trunk/test/CodeGen/arm-atomics-m.c
cfe/trunk/test/CodeGen/arm-atomics-m0.c
cfe/trunk/test/CodeGen/arm-atomics.c
Modified:
cfe/trunk/lib/Basic/Targets.cpp
Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=212598&r1=212597&r2=212598&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Wed Jul 9 04:24:43 2014
@@ -3475,27 +3475,14 @@ class ARMTargetInfo : public TargetInfo
static const Builtin::Info BuiltinInfo[];
static bool shouldUseInlineAtomic(const llvm::Triple &T) {
- if (T.isOSWindows())
- return true;
-
- // On linux, binaries targeting old cpus call functions in libgcc to
- // perform atomic operations. The implementation in libgcc then calls into
- // the kernel which on armv6 and newer uses ldrex and strex. The net result
- // is that if we assume the kernel is at least as recent as the hardware,
- // it is safe to use atomic instructions on armv6 and newer.
- if (!T.isOSLinux() &&
- T.getOS() != llvm::Triple::FreeBSD &&
- T.getOS() != llvm::Triple::NetBSD &&
- T.getOS() != llvm::Triple::Bitrig)
- return false;
StringRef ArchName = T.getArchName();
if (T.getArch() == llvm::Triple::arm ||
T.getArch() == llvm::Triple::armeb) {
StringRef VersionStr;
if (ArchName.startswith("armv"))
- VersionStr = ArchName.substr(4);
+ VersionStr = ArchName.substr(4, 1);
else if (ArchName.startswith("armebv"))
- VersionStr = ArchName.substr(6);
+ VersionStr = ArchName.substr(6, 1);
else
return false;
unsigned Version;
@@ -3507,9 +3494,9 @@ class ARMTargetInfo : public TargetInfo
T.getArch() == llvm::Triple::thumbeb);
StringRef VersionStr;
if (ArchName.startswith("thumbv"))
- VersionStr = ArchName.substr(6);
+ VersionStr = ArchName.substr(6, 1);
else if (ArchName.startswith("thumbebv"))
- VersionStr = ArchName.substr(8);
+ VersionStr = ArchName.substr(8, 1);
else
return false;
unsigned Version;
@@ -3854,6 +3841,13 @@ public:
if (!getCPUDefineSuffix(Name))
return false;
+ // Cortex M does not support 8 byte atomics, while general Thumb2 does.
+ StringRef Profile = getCPUProfile(Name);
+ if (Profile == "M" && MaxAtomicInlineWidth) {
+ MaxAtomicPromoteWidth = 32;
+ MaxAtomicInlineWidth = 32;
+ }
+
CPU = Name;
return true;
}
Added: cfe/trunk/test/CodeGen/arm-atomics-m.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-atomics-m.c?rev=212598&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/arm-atomics-m.c (added)
+++ cfe/trunk/test/CodeGen/arm-atomics-m.c Wed Jul 9 04:24:43 2014
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7m-none--eabi -target-cpu cortex-m3 | FileCheck %s
+
+int i;
+long long l;
+
+typedef enum memory_order {
+ memory_order_relaxed, memory_order_consume, memory_order_acquire,
+ memory_order_release, memory_order_acq_rel, memory_order_seq_cst
+} memory_order;
+
+void test_presence(void)
+{
+ // CHECK-LABEL: @test_presence
+ // CHECK: atomicrmw add i32* {{.*}} seq_cst
+ __atomic_fetch_add(&i, 1, memory_order_seq_cst);
+ // CHECK: atomicrmw sub i32* {{.*}} seq_cst
+ __atomic_fetch_sub(&i, 1, memory_order_seq_cst);
+ // CHECK: load atomic i32* {{.*}} seq_cst
+ int r;
+ __atomic_load(&i, &r, memory_order_seq_cst);
+ // CHECK: store atomic i32 {{.*}} seq_cst
+ r = 0;
+ __atomic_store(&i, &r, memory_order_seq_cst);
+
+ // CHECK: __atomic_fetch_add_8
+ __atomic_fetch_add(&l, 1, memory_order_seq_cst);
+ // CHECK: __atomic_fetch_sub_8
+ __atomic_fetch_sub(&l, 1, memory_order_seq_cst);
+ // CHECK: __atomic_load_8
+ long long rl;
+ __atomic_load(&l, &rl, memory_order_seq_cst);
+ // CHECK: __atomic_store_8
+ rl = 0;
+ __atomic_store(&l, &rl, memory_order_seq_cst);
+}
Added: cfe/trunk/test/CodeGen/arm-atomics-m0.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-atomics-m0.c?rev=212598&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/arm-atomics-m0.c (added)
+++ cfe/trunk/test/CodeGen/arm-atomics-m0.c Wed Jul 9 04:24:43 2014
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv6m-none--eabi -target-cpu cortex-m0 | FileCheck %s
+
+int i;
+long long l;
+
+typedef enum memory_order {
+ memory_order_relaxed, memory_order_consume, memory_order_acquire,
+ memory_order_release, memory_order_acq_rel, memory_order_seq_cst
+} memory_order;
+
+void test_presence(void)
+{
+ // CHECK-LABEL: @test_presence
+ // CHECK: __atomic_fetch_add_4
+ __atomic_fetch_add(&i, 1, memory_order_seq_cst);
+ // CHECK: __atomic_fetch_sub_4
+ __atomic_fetch_sub(&i, 1, memory_order_seq_cst);
+ // CHECK: __atomic_load_4
+ int r;
+ __atomic_load(&i, &r, memory_order_seq_cst);
+ // CHECK: __atomic_store_4
+ r = 0;
+ __atomic_store(&i, &r, memory_order_seq_cst);
+
+ // CHECK: __atomic_fetch_add_8
+ __atomic_fetch_add(&l, 1, memory_order_seq_cst);
+ // CHECK: __atomic_fetch_sub_8
+ __atomic_fetch_sub(&l, 1, memory_order_seq_cst);
+ // CHECK: __atomic_load_8
+ long long rl;
+ __atomic_load(&l, &rl, memory_order_seq_cst);
+ // CHECK: __atomic_store_8
+ rl = 0;
+ __atomic_store(&l, &rl, memory_order_seq_cst);
+}
Added: cfe/trunk/test/CodeGen/arm-atomics.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-atomics.c?rev=212598&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/arm-atomics.c (added)
+++ cfe/trunk/test/CodeGen/arm-atomics.c Wed Jul 9 04:24:43 2014
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-none--eabi | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv6-none--eabi | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-openbsd | FileCheck %s
+
+int i;
+long long l;
+
+typedef enum memory_order {
+ memory_order_relaxed, memory_order_consume, memory_order_acquire,
+ memory_order_release, memory_order_acq_rel, memory_order_seq_cst
+} memory_order;
+
+void test_presence(void)
+{
+ // CHECK-LABEL: @test_presence
+ // CHECK: atomicrmw add i32* {{.*}} seq_cst
+ __atomic_fetch_add(&i, 1, memory_order_seq_cst);
+ // CHECK: atomicrmw sub i32* {{.*}} seq_cst
+ __atomic_fetch_sub(&i, 1, memory_order_seq_cst);
+ // CHECK: load atomic i32* {{.*}} seq_cst
+ int r;
+ __atomic_load(&i, &r, memory_order_seq_cst);
+ // CHECK: store atomic i32 {{.*}} seq_cst
+ r = 0;
+ __atomic_store(&i, &r, memory_order_seq_cst);
+
+ // CHECK: atomicrmw add i64* {{.*}} seq_cst
+ __atomic_fetch_add(&l, 1, memory_order_seq_cst);
+ // CHECK: atomicrmw sub i64* {{.*}} seq_cst
+ __atomic_fetch_sub(&l, 1, memory_order_seq_cst);
+ // CHECK: load atomic i64* {{.*}} seq_cst
+ long long rl;
+ __atomic_load(&l, &rl, memory_order_seq_cst);
+ // CHECK: store atomic i64 {{.*}} seq_cst
+ rl = 0;
+ __atomic_store(&l, &rl, memory_order_seq_cst);
+}
More information about the cfe-commits
mailing list