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@+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 =
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@+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 =
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits