[compiler-rt] 910a642 - [compiler-rt] Implement ARM atomic operations for architectures without SMP support

Pavel Kosov via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 16 23:11:47 PST 2022


Author: Pavel Kosov
Date: 2022-02-17T10:11:25+03:00
New Revision: 910a642c0a5b66a8d2517026b890a1acdc447f19

URL: https://github.com/llvm/llvm-project/commit/910a642c0a5b66a8d2517026b890a1acdc447f19
DIFF: https://github.com/llvm/llvm-project/commit/910a642c0a5b66a8d2517026b890a1acdc447f19.diff

LOG: [compiler-rt] Implement  ARM atomic operations for architectures without SMP support

ARMv5 and older architectures don’t  support SMP and do not have atomic instructions. Still they’re in use in IoT world, where one has to stick to libgcc.

Reviewed By: mstorsjo

Differential Revision: https://reviews.llvm.org/D116088

Added: 
    

Modified: 
    compiler-rt/cmake/Modules/CompilerRTUtils.cmake
    compiler-rt/cmake/config-ix.cmake
    compiler-rt/lib/builtins/CMakeLists.txt
    compiler-rt/lib/builtins/arm/sync-ops.h

Removed: 
    


################################################################################
diff  --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
index 052095801aaed..557fa96eea5eb 100644
--- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
+++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
@@ -110,6 +110,16 @@ function(check_compile_definition def argstring out_var)
   cmake_pop_check_state()
 endfunction()
 
+macro(test_arm_smp_support arch cflags_var)
+  if (${arch} STREQUAL "arm")
+    try_compile(HAS_${arch}_SMP ${CMAKE_BINARY_DIR}
+	    ${ARM_SMP_CHECK_SRC} COMPILE_DEFINITIONS "${CMAKE_C_FLAGS} ${_TARGET_${arch}_CFLAGS}")
+    if (HAS_${arch}_SMP)
+      list(APPEND ${cflags_var} -DCOMPILER_RT_HAS_SMP_SUPPORT)
+    endif()
+  endif()
+endmacro()
+
 # test_target_arch(<arch> <def> <target flags...>)
 # Checks if architecture is supported: runs host compiler with provided
 # flags to verify that:

diff  --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index 4299a0589a7b7..ccf57009fd43f 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -200,6 +200,11 @@ set(COMPILER_RT_SUPPORTED_ARCH)
 set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc)
 file(WRITE ${SIMPLE_SOURCE} "#include <stdlib.h>\n#include <stdio.h>\nint main() { printf(\"hello, world\"); }\n")
 
+# Check if we have SMP support for particular ARM architecture
+# If not use stubs instead of real atomic operations - see sync-ops.h
+set(ARM_SMP_CHECK_SRC ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/arm-barrier.cc)
+file(WRITE ${ARM_SMP_CHECK_SRC} "int main() { asm(\"dmb\"); return 0; }")
+
 # Detect whether the current target platform is 32-bit or 64-bit, and setup
 # the correct commandline flags needed to attempt to target 32-bit and 64-bit.
 if (NOT CMAKE_SIZEOF_VOID_P EQUAL 4 AND

diff  --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index ea5ad9cdb8643..12268dc1ce63d 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -740,6 +740,7 @@ else ()
         list(APPEND BUILTIN_CFLAGS_${arch} -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET)
       endif()
 
+      test_arm_smp_support(${arch} BUILTIN_CFLAGS_${arch})
       # For RISCV32, we must force enable int128 for compiling long
       # double routines.
       if("${arch}" STREQUAL "riscv32")

diff  --git a/compiler-rt/lib/builtins/arm/sync-ops.h b/compiler-rt/lib/builtins/arm/sync-ops.h
index c9623249e5d20..b924b33f80eb3 100644
--- a/compiler-rt/lib/builtins/arm/sync-ops.h
+++ b/compiler-rt/lib/builtins/arm/sync-ops.h
@@ -14,6 +14,8 @@
 
 #include "../assembly.h"
 
+#ifdef COMPILER_RT_HAS_SMP_SUPPORT
+
 #define SYNC_OP_4(op)                                                          \
   .p2align 2;                                                                  \
   .thumb;                                                                      \
@@ -45,6 +47,37 @@
   dmb;                                                                         \
   pop { r4, r5, r6, pc }
 
+#else
+
+#define SYNC_OP_4(op)                                                          \
+  .p2align 2;                                                                  \
+  DEFINE_COMPILERRT_THUMB_FUNCTION(__sync_fetch_and_##op)                      \
+  LOCAL_LABEL(tryatomic_##op) :                                                \
+  mov r12, r0;                                                                 \
+  op(r2, r0, r1);                                                              \
+  str r2, [r12];                                                               \
+  ldr r12, [r12];                                                              \
+  cmp r12, r2;                                                                 \
+  bne LOCAL_LABEL(tryatomic_##op);                                             \
+  bx lr
+
+#define SYNC_OP_8(op)                                                          \
+  .p2align 2;                                                                  \
+  DEFINE_COMPILERRT_THUMB_FUNCTION(__sync_fetch_and_##op)                      \
+  push {r4, r5, r6, lr};                                                       \
+  LOCAL_LABEL(tryatomic_##op) :                                                \
+  mov r12, r0;                                                                 \
+  op(r4, r5, r0, r1, r2, r3);                                                  \
+  stm r12, {r4, r5};                                                           \
+  ldm r12, {r6, r12};                                                          \
+  cmp r6, r4;                                                                  \
+  bne LOCAL_LABEL(tryatomic_##op);                                             \
+  cmp r12, r5;                                                                 \
+  bne LOCAL_LABEL(tryatomic_##op);                                             \
+  pop { r4, r5, r6, pc }
+
+#endif
+
 #define MINMAX_4(rD, rN, rM, cmp_kind)                                         \
   cmp rN, rM;                                                                  \
   mov rD, rM;                                                                  \


        


More information about the llvm-commits mailing list