[clang] [clang][CodeGen] Emit atomic IR in place of optimized libcalls. (PR #73176)
James Y Knight via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 10 12:00:04 PST 2024
================
@@ -1047,122 +1019,19 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
Dest = Atomics.castToAtomicIntPointer(Dest);
}
- // Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary .
- if (UseLibcall) {
- bool UseOptimizedLibcall = false;
- switch (E->getOp()) {
- case AtomicExpr::AO__c11_atomic_init:
- case AtomicExpr::AO__opencl_atomic_init:
- llvm_unreachable("Already handled above with EmitAtomicInit!");
-
- case AtomicExpr::AO__atomic_fetch_add:
- case AtomicExpr::AO__atomic_fetch_and:
- case AtomicExpr::AO__atomic_fetch_max:
- case AtomicExpr::AO__atomic_fetch_min:
- case AtomicExpr::AO__atomic_fetch_nand:
- case AtomicExpr::AO__atomic_fetch_or:
- case AtomicExpr::AO__atomic_fetch_sub:
- case AtomicExpr::AO__atomic_fetch_xor:
- case AtomicExpr::AO__atomic_add_fetch:
- case AtomicExpr::AO__atomic_and_fetch:
- case AtomicExpr::AO__atomic_max_fetch:
- case AtomicExpr::AO__atomic_min_fetch:
- case AtomicExpr::AO__atomic_nand_fetch:
- case AtomicExpr::AO__atomic_or_fetch:
- case AtomicExpr::AO__atomic_sub_fetch:
- case AtomicExpr::AO__atomic_xor_fetch:
- case AtomicExpr::AO__c11_atomic_fetch_add:
- case AtomicExpr::AO__c11_atomic_fetch_and:
- case AtomicExpr::AO__c11_atomic_fetch_max:
- case AtomicExpr::AO__c11_atomic_fetch_min:
- case AtomicExpr::AO__c11_atomic_fetch_nand:
- case AtomicExpr::AO__c11_atomic_fetch_or:
- case AtomicExpr::AO__c11_atomic_fetch_sub:
- case AtomicExpr::AO__c11_atomic_fetch_xor:
- case AtomicExpr::AO__hip_atomic_fetch_add:
- case AtomicExpr::AO__hip_atomic_fetch_and:
- case AtomicExpr::AO__hip_atomic_fetch_max:
- case AtomicExpr::AO__hip_atomic_fetch_min:
- case AtomicExpr::AO__hip_atomic_fetch_or:
- case AtomicExpr::AO__hip_atomic_fetch_sub:
- case AtomicExpr::AO__hip_atomic_fetch_xor:
- case AtomicExpr::AO__opencl_atomic_fetch_add:
- case AtomicExpr::AO__opencl_atomic_fetch_and:
- case AtomicExpr::AO__opencl_atomic_fetch_max:
- case AtomicExpr::AO__opencl_atomic_fetch_min:
- case AtomicExpr::AO__opencl_atomic_fetch_or:
- case AtomicExpr::AO__opencl_atomic_fetch_sub:
- case AtomicExpr::AO__opencl_atomic_fetch_xor:
- case AtomicExpr::AO__scoped_atomic_fetch_add:
- case AtomicExpr::AO__scoped_atomic_fetch_and:
- case AtomicExpr::AO__scoped_atomic_fetch_max:
- case AtomicExpr::AO__scoped_atomic_fetch_min:
- case AtomicExpr::AO__scoped_atomic_fetch_nand:
- case AtomicExpr::AO__scoped_atomic_fetch_or:
- case AtomicExpr::AO__scoped_atomic_fetch_sub:
- case AtomicExpr::AO__scoped_atomic_fetch_xor:
- case AtomicExpr::AO__scoped_atomic_add_fetch:
- case AtomicExpr::AO__scoped_atomic_and_fetch:
- case AtomicExpr::AO__scoped_atomic_max_fetch:
- case AtomicExpr::AO__scoped_atomic_min_fetch:
- case AtomicExpr::AO__scoped_atomic_nand_fetch:
- case AtomicExpr::AO__scoped_atomic_or_fetch:
- case AtomicExpr::AO__scoped_atomic_sub_fetch:
- case AtomicExpr::AO__scoped_atomic_xor_fetch:
- // For these, only library calls for certain sizes exist.
- UseOptimizedLibcall = true;
- break;
-
- case AtomicExpr::AO__atomic_load:
- case AtomicExpr::AO__atomic_store:
- case AtomicExpr::AO__atomic_exchange:
- case AtomicExpr::AO__atomic_compare_exchange:
- case AtomicExpr::AO__scoped_atomic_load:
- case AtomicExpr::AO__scoped_atomic_store:
- case AtomicExpr::AO__scoped_atomic_exchange:
- case AtomicExpr::AO__scoped_atomic_compare_exchange:
- // Use the generic version if we don't know that the operand will be
- // suitably aligned for the optimized version.
- if (Misaligned)
- break;
- [[fallthrough]];
- case AtomicExpr::AO__atomic_load_n:
- case AtomicExpr::AO__atomic_store_n:
- case AtomicExpr::AO__atomic_exchange_n:
- case AtomicExpr::AO__atomic_compare_exchange_n:
- case AtomicExpr::AO__c11_atomic_load:
- case AtomicExpr::AO__c11_atomic_store:
- case AtomicExpr::AO__c11_atomic_exchange:
- case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
- case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
- case AtomicExpr::AO__hip_atomic_load:
- case AtomicExpr::AO__hip_atomic_store:
- case AtomicExpr::AO__hip_atomic_exchange:
- case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
- case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
- case AtomicExpr::AO__opencl_atomic_load:
- case AtomicExpr::AO__opencl_atomic_store:
- case AtomicExpr::AO__opencl_atomic_exchange:
- case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
- case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
- case AtomicExpr::AO__scoped_atomic_load_n:
- case AtomicExpr::AO__scoped_atomic_store_n:
- case AtomicExpr::AO__scoped_atomic_exchange_n:
- case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
- // Only use optimized library calls for sizes for which they exist.
- // FIXME: Size == 16 optimized library functions exist too.
- if (Size == 1 || Size == 2 || Size == 4 || Size == 8)
- UseOptimizedLibcall = true;
- break;
- }
+ bool PowerOf2Size = (Size & (Size - 1)) == 0;
+ bool UseLibcall = !PowerOf2Size | (Size > 16);
+ // Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/Library.
----------------
jyknight wrote:
Suggestion for updated comment:
> For atomics larger than 16 bytes, emit a libcall from the frontend. This avoids the overhead of dealing with excessively-large value types in IR. Non-power-of-2 values also lower to libcall here, as they are not currently permitted in IR instructions (although that constraint could be relaxed in the future). For other cases where a libcall is required on a given platform, we let the backend handle it (this includes handling for all of the size-optimized libcall variants, which are only valid up to 16 bytes.)
>
> See: https://llvm.org/docs/Atomics.html#libcalls-atomic
https://github.com/llvm/llvm-project/pull/73176
More information about the cfe-commits
mailing list