[PATCH] ARM: allow inline atomics on Cortex M

Jonathan Roelofs jonathan at codesourcery.com
Tue Jun 17 08:29:42 PDT 2014



On 6/17/14, 2:11 AM, Renato Golin wrote:
> On 16 June 2014 23:59, Jonathan Roelofs <jonathan at codesourcery.com> wrote:
>>     if ( windows ) return true;
>>     else if ( arch >= v6 ) {
>>       version = whatever;
>>     } else if ( !linux && !freebsd && !netbsd && !bitrig ) {
>>       return false;
>>     }
>>
>>     if ( Profile == "M" && MaxAtomicInlineWidth) {
>>        MaxAtomicPromoteWidth = 32;
>>        MaxAtomicInlineWidth = 32;
>>     }
>>     return true;
>
> This sequence sounds correct to me, too.
After having slept on this, I don't think I was correct with that
snippet, and here is why:

In order for the atomic inlining to be safe here, we must satisfy
two conditions:
   1)  The architecture supports ldrex/strex
   2)  The platform provided builtins (read: libgcc), if any
       (read: baremetal), implements them using the same primitives
       (i.e. not a swp-based kernel-provided cmpxchg, or otherwise)

In the case of baremetal, we really only care about #1.  But when
there is a platform involved, we have to be more careful that we
do using the same primitives that the libcalls are implemented
with, being conservative when we don't know that it is safe... That
means emitting libcalls both when we know we have to, and when
we're not sure.

The original code before Phoebe's patch almost gets that right, but is a little 
too conservative in the baremetal cases on both M-class cpus and non M-class cpus.

Attached is what I now think the patch ought to be.

Cheers,
Jon

P.S. Phoebe, sorry for adding to the confusion :)
>
> cheers,
> -renato
>

-- 
Jon Roelofs
jonathan at codesourcery.com
CodeSourcery / Mentor Embedded
-------------- next part --------------
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp	(revision 209242)
+++ lib/Basic/Targets.cpp	(working copy)
@@ -3751,7 +3751,8 @@
     if (!T.isOSLinux() &&
         T.getOS() != llvm::Triple::FreeBSD &&
         T.getOS() != llvm::Triple::NetBSD &&
-        T.getOS() != llvm::Triple::Bitrig)
+        T.getOS() != llvm::Triple::Bitrig &&
+        T.getOS() != llvm::Triple::UnknownOS) // A 'None' OSType would be more appropriate
       return false;
     StringRef ArchName = T.getArchName();
     if (T.getArch() == llvm::Triple::arm ||
@@ -3758,9 +3759,9 @@
         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;
@@ -3772,9 +3773,9 @@
            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;
@@ -4118,6 +4119,13 @@
     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;
   }


More information about the cfe-commits mailing list