[PATCH] D72579: Evaluate __{c11_,}atomic_is_lock_free to 0 (avoid libcall) if larger than MaxAtomicPromoteWidth

Fangrui Song via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 12 17:28:00 PST 2020


MaskRay created this revision.
MaskRay added reviewers: adalava, dim, nemanjai, jfb, rsmith.
Herald added subscribers: cfe-commits, steven.zhang, dexonsmith, krytarowski, arichardson, emaste.
Herald added a project: clang.

MaxAtomicPromoteWidth is defined as "the maximum width lock-free atomic
operation which will ever be supported for the given target", so an
oversized __c11_atomic_is_lock_free() or __atomic_is_lock_free() can be
evaluated to 0. This is advantageous in some scenarios (e.g. FreeBSD
powerpc, see D71600 <https://reviews.llvm.org/D71600>) to avoid the dependency on libatomic.

The behavior of __atomic_is_lock_free() will diverge from GCC as GCC
never evaluates it to 0 (`gcc/builtins.c:fold_builtin_atomic_always_lock_free`).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72579

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/CodeGen/atomic-ops.c
  clang/test/CodeGen/big-atomic-ops.c
  clang/test/Sema/atomic-ops.c


Index: clang/test/Sema/atomic-ops.c
===================================================================
--- clang/test/Sema/atomic-ops.c
+++ clang/test/Sema/atomic-ops.c
@@ -36,23 +36,23 @@
 _Static_assert(__c11_atomic_is_lock_free(3), ""); // expected-error {{not an integral constant expression}}
 _Static_assert(__c11_atomic_is_lock_free(4), "");
 _Static_assert(__c11_atomic_is_lock_free(8), "");
-_Static_assert(__c11_atomic_is_lock_free(16), ""); // expected-error {{not an integral constant expression}}
-_Static_assert(__c11_atomic_is_lock_free(17), ""); // expected-error {{not an integral constant expression}}
+_Static_assert(!__c11_atomic_is_lock_free(16), "");
+_Static_assert(!__c11_atomic_is_lock_free(17), "");
 
 _Static_assert(__atomic_is_lock_free(1, 0), "");
 _Static_assert(__atomic_is_lock_free(2, 0), "");
 _Static_assert(__atomic_is_lock_free(3, 0), ""); // expected-error {{not an integral constant expression}}
 _Static_assert(__atomic_is_lock_free(4, 0), "");
 _Static_assert(__atomic_is_lock_free(8, 0), "");
-_Static_assert(__atomic_is_lock_free(16, 0), ""); // expected-error {{not an integral constant expression}}
-_Static_assert(__atomic_is_lock_free(17, 0), ""); // expected-error {{not an integral constant expression}}
+_Static_assert(!__atomic_is_lock_free(16, 0), "");
+_Static_assert(!__atomic_is_lock_free(17, 0), "");
 
 _Static_assert(atomic_is_lock_free((atomic_char*)0), "");
 _Static_assert(atomic_is_lock_free((atomic_short*)0), "");
 _Static_assert(atomic_is_lock_free((atomic_int*)0), "");
 _Static_assert(atomic_is_lock_free((atomic_long*)0), "");
 // expected-error at +1 {{__int128 is not supported on this target}}
-_Static_assert(atomic_is_lock_free((_Atomic(__int128)*)0), ""); // expected-error {{not an integral constant expression}}
+_Static_assert(!atomic_is_lock_free((_Atomic(__int128)*)0), "");
 _Static_assert(atomic_is_lock_free(0 + (atomic_char*)0), "");
 
 char i8;
Index: clang/test/CodeGen/big-atomic-ops.c
===================================================================
--- clang/test/CodeGen/big-atomic-ops.c
+++ clang/test/CodeGen/big-atomic-ops.c
@@ -204,9 +204,6 @@
   // CHECK: call i32 @__atomic_is_lock_free(i64 16, i8* {{.*}}@sixteen{{.*}})
   __atomic_is_lock_free(16, &sixteen);
 
-  // CHECK: call i32 @__atomic_is_lock_free(i64 17, i8* {{.*}}@seventeen{{.*}})
-  __atomic_is_lock_free(17, &seventeen);
-
   // CHECK: call i32 @__atomic_is_lock_free(i64 4, {{.*}})
   __atomic_is_lock_free(4, incomplete);
 
@@ -215,6 +212,8 @@
   __atomic_is_lock_free(4, cs+1);
 
   // CHECK-NOT: call
+  __atomic_is_lock_free(17, &seventeen);
+  __atomic_is_lock_free(32, 0);
   __atomic_always_lock_free(3, 0);
   __atomic_always_lock_free(16, 0);
   __atomic_always_lock_free(17, 0);
Index: clang/test/CodeGen/atomic-ops.c
===================================================================
--- clang/test/CodeGen/atomic-ops.c
+++ clang/test/CodeGen/atomic-ops.c
@@ -346,11 +346,8 @@
   // CHECK: call i32 @__atomic_is_lock_free(i32 3, i8* null)
   __c11_atomic_is_lock_free(3);
 
-  // CHECK: call i32 @__atomic_is_lock_free(i32 16, i8* {{.*}}@sixteen{{.*}})
-  __atomic_is_lock_free(16, &sixteen);
-
-  // CHECK: call i32 @__atomic_is_lock_free(i32 17, i8* {{.*}}@seventeen{{.*}})
-  __atomic_is_lock_free(17, &seventeen);
+  // CHECK: call i32 @__atomic_is_lock_free(i32 8, i8* {{.*}}@seventeen{{.*}})
+  __atomic_is_lock_free(8, &seventeen);
 
   // CHECK: call i32 @__atomic_is_lock_free(i32 4, {{.*}})
   __atomic_is_lock_free(4, incomplete);
@@ -360,6 +357,8 @@
   __atomic_is_lock_free(4, cs+1);
 
   // CHECK-NOT: call
+  __atomic_is_lock_free(9, &sixteen);
+  __atomic_is_lock_free(16, 0);
   __atomic_always_lock_free(3, 0);
   __atomic_always_lock_free(16, 0);
   __atomic_always_lock_free(17, 0);
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -11152,6 +11152,9 @@
 
     // Check power-of-two.
     CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
+    if (Size > Info.Ctx.toCharUnitsFromBits(
+                   Info.Ctx.getTargetInfo().getMaxAtomicPromoteWidth()))
+      return Success(0, E);
     if (Size.isPowerOfTwo()) {
       // Check against inlining width.
       unsigned InlineWidthBits =


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D72579.237567.patch
Type: text/x-patch
Size: 4334 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200113/5d2d769c/attachment-0001.bin>


More information about the cfe-commits mailing list