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