/* * kmp_atomic.cpp -- ATOMIC implementation routines */ //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "kmp_atomic.h" #include "kmp.h" // TRUE, asm routines prototypes uchar; ushort; /*! @defgroup ATOMIC_OPS Atomic Operations These functions are used for implementing the many different varieties of atomic operations. The compiler is at liberty to inline atomic operations that are naturally supported by the target architecture. For instance on IA-32 architecture an atomic like this can be inlined @code static int s = 0; #pragma omp atomic s++; @endcode using the single instruction: `lock; incl s` However the runtime does provide entrypoints for these operations to support compilers that choose not to inline them. (For instance, `__kmpc_atomic_fixed4_add` could be used to perform the increment above.) The names of the functions are encoded by using the data type name and the operation name, as in these tables. Data Type | Data type encoding -----------|--------------- int8_t | `fixed1` uint8_t | `fixed1u` int16_t | `fixed2` uint16_t | `fixed2u` int32_t | `fixed4` uint32_t | `fixed4u` int32_t | `fixed8` uint32_t | `fixed8u` float | `float4` double | `float8` float 10 (8087 eighty bit float) | `float10` complex<float> | `cmplx4` complex<double> | `cmplx8` complex<float10> | `cmplx10` <br> Operation | Operation encoding ----------|------------------- + | add - | sub \* | mul / | div & | andb << | shl \>\> | shr \| | orb ^ | xor && | andl \|\| | orl maximum | max minimum | min .eqv. | eqv .neqv. | neqv <br> For non-commutative operations, `_rev` can also be added for the reversed operation. For the functions that capture the result, the suffix `_cpt` is added. Update Functions ================ The general form of an atomic function that just performs an update (without a `capture`) @code void __kmpc_atomic_<datatype>_<operation>( ident_t *id_ref, int gtid, TYPE * lhs, TYPE rhs ); @endcode @param ident_t a pointer to source location @param gtid the global thread id @param lhs a pointer to the left operand @param rhs the right operand `capture` functions =================== The capture functions perform an atomic update and return a result, which is either the value before the capture, or that after. They take an additional argument to determine which result is returned. Their general form is therefore @code TYPE __kmpc_atomic_<datatype>_<operation>_cpt( ident_t *id_ref, int gtid, TYPE * lhs, TYPE rhs, int flag ); @endcode @param ident_t a pointer to source location @param gtid the global thread id @param lhs a pointer to the left operand @param rhs the right operand @param flag one if the result is to be captured *after* the operation, zero if captured *before*. The one set of exceptions to this is the `complex<float>` type where the value is not returned, rather an extra argument pointer is passed. They look like @code void __kmpc_atomic_cmplx4_<op>_cpt( ident_t *id_ref, int gtid, kmp_cmplx32 * lhs, kmp_cmplx32 rhs, kmp_cmplx32 * out, int flag ); @endcode Read and Write Operations ========================= The OpenMP<sup>*</sup> standard now supports atomic operations that simply ensure that the value is read or written atomically, with no modification performed. In many cases on IA-32 architecture these operations can be inlined since the architecture guarantees that no tearing occurs on aligned objects accessed with a single memory operation of up to 64 bits in size. The general form of the read operations is @code TYPE __kmpc_atomic_<type>_rd ( ident_t *id_ref, int gtid, TYPE * loc ); @endcode For the write operations the form is @code void __kmpc_atomic_<type>_wr ( ident_t *id_ref, int gtid, TYPE * lhs, TYPE rhs ); @endcode Full list of functions ====================== This leads to the generation of 376 atomic functions, as follows. Functions for integers --------------------- There are versions here for integers of size 1,2,4 and 8 bytes both signed and unsigned (where that matters). @code __kmpc_atomic_fixed1_add __kmpc_atomic_fixed1_add_cpt __kmpc_atomic_fixed1_add_fp __kmpc_atomic_fixed1_andb __kmpc_atomic_fixed1_andb_cpt __kmpc_atomic_fixed1_andl __kmpc_atomic_fixed1_andl_cpt __kmpc_atomic_fixed1_div __kmpc_atomic_fixed1_div_cpt __kmpc_atomic_fixed1_div_cpt_rev __kmpc_atomic_fixed1_div_float8 __kmpc_atomic_fixed1_div_fp __kmpc_atomic_fixed1_div_rev __kmpc_atomic_fixed1_eqv __kmpc_atomic_fixed1_eqv_cpt __kmpc_atomic_fixed1_max __kmpc_atomic_fixed1_max_cpt __kmpc_atomic_fixed1_min __kmpc_atomic_fixed1_min_cpt __kmpc_atomic_fixed1_mul __kmpc_atomic_fixed1_mul_cpt __kmpc_atomic_fixed1_mul_float8 __kmpc_atomic_fixed1_mul_fp __kmpc_atomic_fixed1_neqv __kmpc_atomic_fixed1_neqv_cpt __kmpc_atomic_fixed1_orb __kmpc_atomic_fixed1_orb_cpt __kmpc_atomic_fixed1_orl __kmpc_atomic_fixed1_orl_cpt __kmpc_atomic_fixed1_rd __kmpc_atomic_fixed1_shl __kmpc_atomic_fixed1_shl_cpt __kmpc_atomic_fixed1_shl_cpt_rev __kmpc_atomic_fixed1_shl_rev __kmpc_atomic_fixed1_shr __kmpc_atomic_fixed1_shr_cpt __kmpc_atomic_fixed1_shr_cpt_rev __kmpc_atomic_fixed1_shr_rev __kmpc_atomic_fixed1_sub __kmpc_atomic_fixed1_sub_cpt __kmpc_atomic_fixed1_sub_cpt_rev __kmpc_atomic_fixed1_sub_fp __kmpc_atomic_fixed1_sub_rev __kmpc_atomic_fixed1_swp __kmpc_atomic_fixed1_wr __kmpc_atomic_fixed1_xor __kmpc_atomic_fixed1_xor_cpt __kmpc_atomic_fixed1u_add_fp __kmpc_atomic_fixed1u_sub_fp __kmpc_atomic_fixed1u_mul_fp __kmpc_atomic_fixed1u_div __kmpc_atomic_fixed1u_div_cpt __kmpc_atomic_fixed1u_div_cpt_rev __kmpc_atomic_fixed1u_div_fp __kmpc_atomic_fixed1u_div_rev __kmpc_atomic_fixed1u_shr __kmpc_atomic_fixed1u_shr_cpt __kmpc_atomic_fixed1u_shr_cpt_rev __kmpc_atomic_fixed1u_shr_rev __kmpc_atomic_fixed2_add __kmpc_atomic_fixed2_add_cpt __kmpc_atomic_fixed2_add_fp __kmpc_atomic_fixed2_andb __kmpc_atomic_fixed2_andb_cpt __kmpc_atomic_fixed2_andl __kmpc_atomic_fixed2_andl_cpt __kmpc_atomic_fixed2_div __kmpc_atomic_fixed2_div_cpt __kmpc_atomic_fixed2_div_cpt_rev __kmpc_atomic_fixed2_div_float8 __kmpc_atomic_fixed2_div_fp __kmpc_atomic_fixed2_div_rev __kmpc_atomic_fixed2_eqv __kmpc_atomic_fixed2_eqv_cpt __kmpc_atomic_fixed2_max __kmpc_atomic_fixed2_max_cpt __kmpc_atomic_fixed2_min __kmpc_atomic_fixed2_min_cpt __kmpc_atomic_fixed2_mul __kmpc_atomic_fixed2_mul_cpt __kmpc_atomic_fixed2_mul_float8 __kmpc_atomic_fixed2_mul_fp __kmpc_atomic_fixed2_neqv __kmpc_atomic_fixed2_neqv_cpt __kmpc_atomic_fixed2_orb __kmpc_atomic_fixed2_orb_cpt __kmpc_atomic_fixed2_orl __kmpc_atomic_fixed2_orl_cpt __kmpc_atomic_fixed2_rd __kmpc_atomic_fixed2_shl __kmpc_atomic_fixed2_shl_cpt __kmpc_atomic_fixed2_shl_cpt_rev __kmpc_atomic_fixed2_shl_rev __kmpc_atomic_fixed2_shr __kmpc_atomic_fixed2_shr_cpt __kmpc_atomic_fixed2_shr_cpt_rev __kmpc_atomic_fixed2_shr_rev __kmpc_atomic_fixed2_sub __kmpc_atomic_fixed2_sub_cpt __kmpc_atomic_fixed2_sub_cpt_rev __kmpc_atomic_fixed2_sub_fp __kmpc_atomic_fixed2_sub_rev __kmpc_atomic_fixed2_swp __kmpc_atomic_fixed2_wr __kmpc_atomic_fixed2_xor __kmpc_atomic_fixed2_xor_cpt __kmpc_atomic_fixed2u_add_fp __kmpc_atomic_fixed2u_sub_fp __kmpc_atomic_fixed2u_mul_fp __kmpc_atomic_fixed2u_div __kmpc_atomic_fixed2u_div_cpt __kmpc_atomic_fixed2u_div_cpt_rev __kmpc_atomic_fixed2u_div_fp __kmpc_atomic_fixed2u_div_rev __kmpc_atomic_fixed2u_shr __kmpc_atomic_fixed2u_shr_cpt __kmpc_atomic_fixed2u_shr_cpt_rev __kmpc_atomic_fixed2u_shr_rev __kmpc_atomic_fixed4_add __kmpc_atomic_fixed4_add_cpt __kmpc_atomic_fixed4_add_fp __kmpc_atomic_fixed4_andb __kmpc_atomic_fixed4_andb_cpt __kmpc_atomic_fixed4_andl __kmpc_atomic_fixed4_andl_cpt __kmpc_atomic_fixed4_div __kmpc_atomic_fixed4_div_cpt __kmpc_atomic_fixed4_div_cpt_rev __kmpc_atomic_fixed4_div_float8 __kmpc_atomic_fixed4_div_fp __kmpc_atomic_fixed4_div_rev __kmpc_atomic_fixed4_eqv __kmpc_atomic_fixed4_eqv_cpt __kmpc_atomic_fixed4_max __kmpc_atomic_fixed4_max_cpt __kmpc_atomic_fixed4_min __kmpc_atomic_fixed4_min_cpt __kmpc_atomic_fixed4_mul __kmpc_atomic_fixed4_mul_cpt __kmpc_atomic_fixed4_mul_float8 __kmpc_atomic_fixed4_mul_fp __kmpc_atomic_fixed4_neqv __kmpc_atomic_fixed4_neqv_cpt __kmpc_atomic_fixed4_orb __kmpc_atomic_fixed4_orb_cpt __kmpc_atomic_fixed4_orl __kmpc_atomic_fixed4_orl_cpt __kmpc_atomic_fixed4_rd __kmpc_atomic_fixed4_shl __kmpc_atomic_fixed4_shl_cpt __kmpc_atomic_fixed4_shl_cpt_rev __kmpc_atomic_fixed4_shl_rev __kmpc_atomic_fixed4_shr __kmpc_atomic_fixed4_shr_cpt __kmpc_atomic_fixed4_shr_cpt_rev __kmpc_atomic_fixed4_shr_rev __kmpc_atomic_fixed4_sub __kmpc_atomic_fixed4_sub_cpt __kmpc_atomic_fixed4_sub_cpt_rev __kmpc_atomic_fixed4_sub_fp __kmpc_atomic_fixed4_sub_rev __kmpc_atomic_fixed4_swp __kmpc_atomic_fixed4_wr __kmpc_atomic_fixed4_xor __kmpc_atomic_fixed4_xor_cpt __kmpc_atomic_fixed4u_add_fp __kmpc_atomic_fixed4u_sub_fp __kmpc_atomic_fixed4u_mul_fp __kmpc_atomic_fixed4u_div __kmpc_atomic_fixed4u_div_cpt __kmpc_atomic_fixed4u_div_cpt_rev __kmpc_atomic_fixed4u_div_fp __kmpc_atomic_fixed4u_div_rev __kmpc_atomic_fixed4u_shr __kmpc_atomic_fixed4u_shr_cpt __kmpc_atomic_fixed4u_shr_cpt_rev __kmpc_atomic_fixed4u_shr_rev __kmpc_atomic_fixed8_add __kmpc_atomic_fixed8_add_cpt __kmpc_atomic_fixed8_add_fp __kmpc_atomic_fixed8_andb __kmpc_atomic_fixed8_andb_cpt __kmpc_atomic_fixed8_andl __kmpc_atomic_fixed8_andl_cpt __kmpc_atomic_fixed8_div __kmpc_atomic_fixed8_div_cpt __kmpc_atomic_fixed8_div_cpt_rev __kmpc_atomic_fixed8_div_float8 __kmpc_atomic_fixed8_div_fp __kmpc_atomic_fixed8_div_rev __kmpc_atomic_fixed8_eqv __kmpc_atomic_fixed8_eqv_cpt __kmpc_atomic_fixed8_max __kmpc_atomic_fixed8_max_cpt __kmpc_atomic_fixed8_min __kmpc_atomic_fixed8_min_cpt __kmpc_atomic_fixed8_mul __kmpc_atomic_fixed8_mul_cpt __kmpc_atomic_fixed8_mul_float8 __kmpc_atomic_fixed8_mul_fp __kmpc_atomic_fixed8_neqv __kmpc_atomic_fixed8_neqv_cpt __kmpc_atomic_fixed8_orb __kmpc_atomic_fixed8_orb_cpt __kmpc_atomic_fixed8_orl __kmpc_atomic_fixed8_orl_cpt __kmpc_atomic_fixed8_rd __kmpc_atomic_fixed8_shl __kmpc_atomic_fixed8_shl_cpt __kmpc_atomic_fixed8_shl_cpt_rev __kmpc_atomic_fixed8_shl_rev __kmpc_atomic_fixed8_shr __kmpc_atomic_fixed8_shr_cpt __kmpc_atomic_fixed8_shr_cpt_rev __kmpc_atomic_fixed8_shr_rev __kmpc_atomic_fixed8_sub __kmpc_atomic_fixed8_sub_cpt __kmpc_atomic_fixed8_sub_cpt_rev __kmpc_atomic_fixed8_sub_fp __kmpc_atomic_fixed8_sub_rev __kmpc_atomic_fixed8_swp __kmpc_atomic_fixed8_wr __kmpc_atomic_fixed8_xor __kmpc_atomic_fixed8_xor_cpt __kmpc_atomic_fixed8u_add_fp __kmpc_atomic_fixed8u_sub_fp __kmpc_atomic_fixed8u_mul_fp __kmpc_atomic_fixed8u_div __kmpc_atomic_fixed8u_div_cpt __kmpc_atomic_fixed8u_div_cpt_rev __kmpc_atomic_fixed8u_div_fp __kmpc_atomic_fixed8u_div_rev __kmpc_atomic_fixed8u_shr __kmpc_atomic_fixed8u_shr_cpt __kmpc_atomic_fixed8u_shr_cpt_rev __kmpc_atomic_fixed8u_shr_rev @endcode Functions for floating point ---------------------------- There are versions here for floating point numbers of size 4, 8, 10 and 16 bytes. (Ten byte floats are used by X87, but are now rare). @code __kmpc_atomic_float4_add __kmpc_atomic_float4_add_cpt __kmpc_atomic_float4_add_float8 __kmpc_atomic_float4_add_fp __kmpc_atomic_float4_div __kmpc_atomic_float4_div_cpt __kmpc_atomic_float4_div_cpt_rev __kmpc_atomic_float4_div_float8 __kmpc_atomic_float4_div_fp __kmpc_atomic_float4_div_rev __kmpc_atomic_float4_max __kmpc_atomic_float4_max_cpt __kmpc_atomic_float4_min __kmpc_atomic_float4_min_cpt __kmpc_atomic_float4_mul __kmpc_atomic_float4_mul_cpt __kmpc_atomic_float4_mul_float8 __kmpc_atomic_float4_mul_fp __kmpc_atomic_float4_rd __kmpc_atomic_float4_sub __kmpc_atomic_float4_sub_cpt __kmpc_atomic_float4_sub_cpt_rev __kmpc_atomic_float4_sub_float8 __kmpc_atomic_float4_sub_fp __kmpc_atomic_float4_sub_rev __kmpc_atomic_float4_swp __kmpc_atomic_float4_wr __kmpc_atomic_float8_add __kmpc_atomic_float8_add_cpt __kmpc_atomic_float8_add_fp __kmpc_atomic_float8_div __kmpc_atomic_float8_div_cpt __kmpc_atomic_float8_div_cpt_rev __kmpc_atomic_float8_div_fp __kmpc_atomic_float8_div_rev __kmpc_atomic_float8_max __kmpc_atomic_float8_max_cpt __kmpc_atomic_float8_min __kmpc_atomic_float8_min_cpt __kmpc_atomic_float8_mul __kmpc_atomic_float8_mul_cpt __kmpc_atomic_float8_mul_fp __kmpc_atomic_float8_rd __kmpc_atomic_float8_sub __kmpc_atomic_float8_sub_cpt __kmpc_atomic_float8_sub_cpt_rev __kmpc_atomic_float8_sub_fp __kmpc_atomic_float8_sub_rev __kmpc_atomic_float8_swp __kmpc_atomic_float8_wr __kmpc_atomic_float10_add __kmpc_atomic_float10_add_cpt __kmpc_atomic_float10_add_fp __kmpc_atomic_float10_div __kmpc_atomic_float10_div_cpt __kmpc_atomic_float10_div_cpt_rev __kmpc_atomic_float10_div_fp __kmpc_atomic_float10_div_rev __kmpc_atomic_float10_mul __kmpc_atomic_float10_mul_cpt __kmpc_atomic_float10_mul_fp __kmpc_atomic_float10_rd __kmpc_atomic_float10_sub __kmpc_atomic_float10_sub_cpt __kmpc_atomic_float10_sub_cpt_rev __kmpc_atomic_float10_sub_fp __kmpc_atomic_float10_sub_rev __kmpc_atomic_float10_swp __kmpc_atomic_float10_wr __kmpc_atomic_float16_add __kmpc_atomic_float16_add_cpt __kmpc_atomic_float16_div __kmpc_atomic_float16_div_cpt __kmpc_atomic_float16_div_cpt_rev __kmpc_atomic_float16_div_rev __kmpc_atomic_float16_max __kmpc_atomic_float16_max_cpt __kmpc_atomic_float16_min __kmpc_atomic_float16_min_cpt __kmpc_atomic_float16_mul __kmpc_atomic_float16_mul_cpt __kmpc_atomic_float16_rd __kmpc_atomic_float16_sub __kmpc_atomic_float16_sub_cpt __kmpc_atomic_float16_sub_cpt_rev __kmpc_atomic_float16_sub_rev __kmpc_atomic_float16_swp __kmpc_atomic_float16_wr @endcode Functions for Complex types --------------------------- Functions for complex types whose component floating point variables are of size 4,8,10 or 16 bytes. The names here are based on the size of the component float, *not* the size of the complex type. So `__kmpc_atomic_cmplx8_add` is an operation on a `complex<double>` or `complex(kind=8)`, *not* `complex<float>`. @code __kmpc_atomic_cmplx4_add __kmpc_atomic_cmplx4_add_cmplx8 __kmpc_atomic_cmplx4_add_cpt __kmpc_atomic_cmplx4_div __kmpc_atomic_cmplx4_div_cmplx8 __kmpc_atomic_cmplx4_div_cpt __kmpc_atomic_cmplx4_div_cpt_rev __kmpc_atomic_cmplx4_div_rev __kmpc_atomic_cmplx4_mul __kmpc_atomic_cmplx4_mul_cmplx8 __kmpc_atomic_cmplx4_mul_cpt __kmpc_atomic_cmplx4_rd __kmpc_atomic_cmplx4_sub __kmpc_atomic_cmplx4_sub_cmplx8 __kmpc_atomic_cmplx4_sub_cpt __kmpc_atomic_cmplx4_sub_cpt_rev __kmpc_atomic_cmplx4_sub_rev __kmpc_atomic_cmplx4_swp __kmpc_atomic_cmplx4_wr __kmpc_atomic_cmplx8_add __kmpc_atomic_cmplx8_add_cpt __kmpc_atomic_cmplx8_div __kmpc_atomic_cmplx8_div_cpt __kmpc_atomic_cmplx8_div_cpt_rev __kmpc_atomic_cmplx8_div_rev __kmpc_atomic_cmplx8_mul __kmpc_atomic_cmplx8_mul_cpt __kmpc_atomic_cmplx8_rd __kmpc_atomic_cmplx8_sub __kmpc_atomic_cmplx8_sub_cpt __kmpc_atomic_cmplx8_sub_cpt_rev __kmpc_atomic_cmplx8_sub_rev __kmpc_atomic_cmplx8_swp __kmpc_atomic_cmplx8_wr __kmpc_atomic_cmplx10_add __kmpc_atomic_cmplx10_add_cpt __kmpc_atomic_cmplx10_div __kmpc_atomic_cmplx10_div_cpt __kmpc_atomic_cmplx10_div_cpt_rev __kmpc_atomic_cmplx10_div_rev __kmpc_atomic_cmplx10_mul __kmpc_atomic_cmplx10_mul_cpt __kmpc_atomic_cmplx10_rd __kmpc_atomic_cmplx10_sub __kmpc_atomic_cmplx10_sub_cpt __kmpc_atomic_cmplx10_sub_cpt_rev __kmpc_atomic_cmplx10_sub_rev __kmpc_atomic_cmplx10_swp __kmpc_atomic_cmplx10_wr __kmpc_atomic_cmplx16_add __kmpc_atomic_cmplx16_add_cpt __kmpc_atomic_cmplx16_div __kmpc_atomic_cmplx16_div_cpt __kmpc_atomic_cmplx16_div_cpt_rev __kmpc_atomic_cmplx16_div_rev __kmpc_atomic_cmplx16_mul __kmpc_atomic_cmplx16_mul_cpt __kmpc_atomic_cmplx16_rd __kmpc_atomic_cmplx16_sub __kmpc_atomic_cmplx16_sub_cpt __kmpc_atomic_cmplx16_sub_cpt_rev __kmpc_atomic_cmplx16_swp __kmpc_atomic_cmplx16_wr @endcode */ /*! @ingroup ATOMIC_OPS @{ */ /* * Global vars */ #ifndef KMP_GOMP_COMPAT int __kmp_atomic_mode = 1; // Intel perf #else int __kmp_atomic_mode = …; // GOMP compatibility #endif /* KMP_GOMP_COMPAT */ KMP_ALIGN(128) // Control access to all user coded atomics in Gnu compat mode kmp_atomic_lock_t __kmp_atomic_lock; // Control access to all user coded atomics for 1-byte fixed data types kmp_atomic_lock_t __kmp_atomic_lock_1i; // Control access to all user coded atomics for 2-byte fixed data types kmp_atomic_lock_t __kmp_atomic_lock_2i; // Control access to all user coded atomics for 4-byte fixed data types kmp_atomic_lock_t __kmp_atomic_lock_4i; // Control access to all user coded atomics for kmp_real32 data type kmp_atomic_lock_t __kmp_atomic_lock_4r; // Control access to all user coded atomics for 8-byte fixed data types kmp_atomic_lock_t __kmp_atomic_lock_8i; // Control access to all user coded atomics for kmp_real64 data type kmp_atomic_lock_t __kmp_atomic_lock_8r; // Control access to all user coded atomics for complex byte data type kmp_atomic_lock_t __kmp_atomic_lock_8c; // Control access to all user coded atomics for long double data type kmp_atomic_lock_t __kmp_atomic_lock_10r; // Control access to all user coded atomics for _Quad data type kmp_atomic_lock_t __kmp_atomic_lock_16r; // Control access to all user coded atomics for double complex data type kmp_atomic_lock_t __kmp_atomic_lock_16c; // Control access to all user coded atomics for long double complex type kmp_atomic_lock_t __kmp_atomic_lock_20c; // Control access to all user coded atomics for _Quad complex data type kmp_atomic_lock_t __kmp_atomic_lock_32c; /* 2007-03-02: Without "volatile" specifier in OP_CMPXCHG and MIN_MAX_CMPXCHG we have a bug on *_32 and *_32e. This is just a temporary workaround for the problem. It seems the right solution is writing OP_CMPXCHG and MIN_MAX_CMPXCHG routines in assembler language. */ #define KMP_ATOMIC_VOLATILE … #if (KMP_ARCH_X86) && KMP_HAVE_QUAD static inline Quad_a4_t operator+(Quad_a4_t &lhs, Quad_a4_t &rhs) { return lhs.q + rhs.q; } static inline Quad_a4_t operator-(Quad_a4_t &lhs, Quad_a4_t &rhs) { return lhs.q - rhs.q; } static inline Quad_a4_t operator*(Quad_a4_t &lhs, Quad_a4_t &rhs) { return lhs.q * rhs.q; } static inline Quad_a4_t operator/(Quad_a4_t &lhs, Quad_a4_t &rhs) { return lhs.q / rhs.q; } static inline bool operator<(Quad_a4_t &lhs, Quad_a4_t &rhs) { return lhs.q < rhs.q; } static inline bool operator>(Quad_a4_t &lhs, Quad_a4_t &rhs) { return lhs.q > rhs.q; } static inline Quad_a16_t operator+(Quad_a16_t &lhs, Quad_a16_t &rhs) { return lhs.q + rhs.q; } static inline Quad_a16_t operator-(Quad_a16_t &lhs, Quad_a16_t &rhs) { return lhs.q - rhs.q; } static inline Quad_a16_t operator*(Quad_a16_t &lhs, Quad_a16_t &rhs) { return lhs.q * rhs.q; } static inline Quad_a16_t operator/(Quad_a16_t &lhs, Quad_a16_t &rhs) { return lhs.q / rhs.q; } static inline bool operator<(Quad_a16_t &lhs, Quad_a16_t &rhs) { return lhs.q < rhs.q; } static inline bool operator>(Quad_a16_t &lhs, Quad_a16_t &rhs) { return lhs.q > rhs.q; } static inline kmp_cmplx128_a4_t operator+(kmp_cmplx128_a4_t &lhs, kmp_cmplx128_a4_t &rhs) { return lhs.q + rhs.q; } static inline kmp_cmplx128_a4_t operator-(kmp_cmplx128_a4_t &lhs, kmp_cmplx128_a4_t &rhs) { return lhs.q - rhs.q; } static inline kmp_cmplx128_a4_t operator*(kmp_cmplx128_a4_t &lhs, kmp_cmplx128_a4_t &rhs) { return lhs.q * rhs.q; } static inline kmp_cmplx128_a4_t operator/(kmp_cmplx128_a4_t &lhs, kmp_cmplx128_a4_t &rhs) { return lhs.q / rhs.q; } static inline kmp_cmplx128_a16_t operator+(kmp_cmplx128_a16_t &lhs, kmp_cmplx128_a16_t &rhs) { return lhs.q + rhs.q; } static inline kmp_cmplx128_a16_t operator-(kmp_cmplx128_a16_t &lhs, kmp_cmplx128_a16_t &rhs) { return lhs.q - rhs.q; } static inline kmp_cmplx128_a16_t operator*(kmp_cmplx128_a16_t &lhs, kmp_cmplx128_a16_t &rhs) { return lhs.q * rhs.q; } static inline kmp_cmplx128_a16_t operator/(kmp_cmplx128_a16_t &lhs, kmp_cmplx128_a16_t &rhs) { return lhs.q / rhs.q; } #endif // (KMP_ARCH_X86) && KMP_HAVE_QUAD // ATOMIC implementation routines ----------------------------------------- // One routine for each operation and operand type. // All routines declarations looks like // void __kmpc_atomic_RTYPE_OP( ident_t*, int, TYPE *lhs, TYPE rhs ); #define KMP_CHECK_GTID … // Beginning of a definition (provides name, parameters, gebug trace) // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned // fixed) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operands' type #define ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, RET_TYPE) … // ------------------------------------------------------------------------ // Lock variables used for critical sections for various size operands #define ATOMIC_LOCK0 … #define ATOMIC_LOCK1i … #define ATOMIC_LOCK2i … #define ATOMIC_LOCK4i … #define ATOMIC_LOCK4r … #define ATOMIC_LOCK8i … #define ATOMIC_LOCK8r … #define ATOMIC_LOCK8c … #define ATOMIC_LOCK10r … #define ATOMIC_LOCK16r … #define ATOMIC_LOCK16c … #define ATOMIC_LOCK20c … #define ATOMIC_LOCK32c … // ------------------------------------------------------------------------ // Operation on *lhs, rhs bound by critical section // OP - operator (it's supposed to contain an assignment) // LCK_ID - lock identifier // Note: don't check gtid as it should always be valid // 1, 2-byte - expect valid parameter, other - check before this macro #define OP_CRITICAL … #define OP_UPDATE_CRITICAL(TYPE, OP, LCK_ID) … // ------------------------------------------------------------------------ // For GNU compatibility, we may need to use a critical section, // even though it is not required by the ISA. // // On IA-32 architecture, all atomic operations except for fixed 4 byte add, // sub, and bitwise logical ops, and 1 & 2 byte logical ops use a common // critical section. On Intel(R) 64, all atomic operations are done with fetch // and add or compare and exchange. Therefore, the FLAG parameter to this // macro is either KMP_ARCH_X86 or 0 (or 1, for Intel-specific extension which // require a critical section, where we predict that they will be implemented // in the Gnu codegen by calling GOMP_atomic_start() / GOMP_atomic_end()). // // When the OP_GOMP_CRITICAL macro is used in a *CRITICAL* macro construct, // the FLAG parameter should always be 1. If we know that we will be using // a critical section, then we want to make certain that we use the generic // lock __kmp_atomic_lock to protect the atomic update, and not of of the // locks that are specialized based upon the size or type of the data. // // If FLAG is 0, then we are relying on dead code elimination by the build // compiler to get rid of the useless block of code, and save a needless // branch at runtime. #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL(OP, FLAG) … #define OP_UPDATE_GOMP_CRITICAL(TYPE, OP, FLAG) … #else #define OP_GOMP_CRITICAL … #define OP_UPDATE_GOMP_CRITICAL … #endif /* KMP_GOMP_COMPAT */ #if KMP_MIC #define KMP_DO_PAUSE … #else #define KMP_DO_PAUSE #endif /* KMP_MIC */ // ------------------------------------------------------------------------ // Operation on *lhs, rhs using "compare_and_store" routine // TYPE - operands' type // BITS - size in bits, used to distinguish low level calls // OP - operator #define OP_CMPXCHG(TYPE, BITS, OP) … #if USE_CMPXCHG_FIX // 2007-06-25: // workaround for C78287 (complex(kind=4) data type). lin_32, lin_32e, win_32 // and win_32e are affected (I verified the asm). Compiler ignores the volatile // qualifier of the temp_val in the OP_CMPXCHG macro. This is a problem of the // compiler. Related tracker is C76005, targeted to 11.0. I verified the asm of // the workaround. #define OP_CMPXCHG_WORKAROUND(TYPE, BITS, OP) … // end of the first part of the workaround for C78287 #endif // USE_CMPXCHG_FIX #if KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM) // Undo explicit type casts to get MSVC ARM64 to build. Uses // OP_CMPXCHG_WORKAROUND definition for OP_CMPXCHG #undef OP_CMPXCHG #define OP_CMPXCHG … #undef OP_UPDATE_CRITICAL #define OP_UPDATE_CRITICAL … #endif // KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM) #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------ // X86 or X86_64: no alignment problems ==================================== #define ATOMIC_FIXED_ADD(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \ GOMP_FLAG) … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \ GOMP_FLAG) … #if USE_CMPXCHG_FIX // ------------------------------------------------------------------------- // workaround for C78287 (complex(kind=4) data type) #define ATOMIC_CMPXCHG_WORKAROUND(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, \ MASK, GOMP_FLAG) … // end of the second part of the workaround for C78287 #endif // USE_CMPXCHG_FIX #else // ------------------------------------------------------------------------- // Code for other architectures that don't handle unaligned accesses. #define ATOMIC_FIXED_ADD … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG … #if USE_CMPXCHG_FIX // ------------------------------------------------------------------------- // workaround for C78287 (complex(kind=4) data type) #define ATOMIC_CMPXCHG_WORKAROUND … // end of the second part of the workaround for C78287 #endif // USE_CMPXCHG_FIX #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ // Routines for ATOMIC 4-byte operands addition and subtraction ATOMIC_FIXED_ADD(…) // __kmpc_atomic_fixed4_add ATOMIC_FIXED_ADD(…) // __kmpc_atomic_fixed4_sub ATOMIC_CMPXCHG(…) // __kmpc_atomic_float4_add ATOMIC_CMPXCHG(…) // __kmpc_atomic_float4_sub // Routines for ATOMIC 8-byte operands addition and subtraction ATOMIC_FIXED_ADD(…) // __kmpc_atomic_fixed8_add ATOMIC_FIXED_ADD(…) // __kmpc_atomic_fixed8_sub ATOMIC_CMPXCHG(…) // __kmpc_atomic_float8_add ATOMIC_CMPXCHG(…) // __kmpc_atomic_float8_sub // ------------------------------------------------------------------------ // Entries definition for integer operands // TYPE_ID - operands type and size (fixed4, float4) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operand type // BITS - size in bits, used to distinguish low level calls // OP - operator (used in critical section) // LCK_ID - lock identifier, used to possibly distinguish lock variable // MASK - used for alignment check // TYPE_ID,OP_ID, TYPE, BITS,OP,LCK_ID,MASK,GOMP_FLAG // ------------------------------------------------------------------------ // Routines for ATOMIC integer operands, other operators // ------------------------------------------------------------------------ // TYPE_ID,OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_add ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_andb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1u_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_mul ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_orb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_shl ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1u_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_sub ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_xor ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_add ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_andb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2u_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_mul ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_orb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_shl ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2u_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_sub ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_xor ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_andb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4u_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_mul ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_orb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_shl ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4u_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_xor ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_andb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8u_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_mul ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_orb ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_shl ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8u_shr ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_xor ATOMIC_CMPXCHG(…) // __kmpc_atomic_float4_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_float4_mul ATOMIC_CMPXCHG(…) // __kmpc_atomic_float8_div ATOMIC_CMPXCHG(…) // __kmpc_atomic_float8_mul // TYPE_ID,OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG /* ------------------------------------------------------------------------ */ /* Routines for C/C++ Reduction operators && and || */ // ------------------------------------------------------------------------ // Need separate macros for &&, || because there is no combined assignment // TODO: eliminate ATOMIC_CRIT_{L,EQV} macros as not used #define ATOMIC_CRIT_L(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------ // X86 or X86_64: no alignment problems =================================== #define ATOMIC_CMPX_L(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, GOMP_FLAG) … #else // ------------------------------------------------------------------------ // Code for other architectures that don't handle unaligned accesses. #define ATOMIC_CMPX_L … #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed1_andl ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed1_orl ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed2_andl ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed2_orl ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed4_andl ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed4_orl ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed8_andl ATOMIC_CMPX_L(…) // __kmpc_atomic_fixed8_orl /* ------------------------------------------------------------------------- */ /* Routines for Fortran operators that matched no one in C: */ /* MAX, MIN, .EQV., .NEQV. */ /* Operators .AND., .OR. are covered by __kmpc_atomic_*_{andl,orl} */ /* Intrinsics IAND, IOR, IEOR are covered by __kmpc_atomic_*_{andb,orb,xor} */ // ------------------------------------------------------------------------- // MIN and MAX need separate macros // OP - operator to check if we need any actions? #define MIN_MAX_CRITSECT(OP, LCK_ID) … // ------------------------------------------------------------------------- #ifdef KMP_GOMP_COMPAT #define GOMP_MIN_MAX_CRITSECT(OP, FLAG) … #else #define GOMP_MIN_MAX_CRITSECT … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------- #define MIN_MAX_CMPXCHG(TYPE, BITS, OP) … // ------------------------------------------------------------------------- // 1-byte, 2-byte operands - use critical section #define MIN_MAX_CRITICAL(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------- // X86 or X86_64: no alignment problems ==================================== #define MIN_MAX_COMPXCHG(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \ GOMP_FLAG) … #else // ------------------------------------------------------------------------- // Code for other architectures that don't handle unaligned accesses. #define MIN_MAX_COMPXCHG … #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed1_max MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed1_min MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed2_max MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed2_min MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed4_max MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed4_min MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed8_max MIN_MAX_COMPXCHG(…) // __kmpc_atomic_fixed8_min MIN_MAX_COMPXCHG(…) // __kmpc_atomic_float4_max MIN_MAX_COMPXCHG(…) // __kmpc_atomic_float4_min MIN_MAX_COMPXCHG(…) // __kmpc_atomic_float8_max MIN_MAX_COMPXCHG(…) // __kmpc_atomic_float8_min #if KMP_ARCH_X86 || KMP_ARCH_X86_64 MIN_MAX_CRITICAL(…) // __kmpc_atomic_float10_max MIN_MAX_CRITICAL(…) // __kmpc_atomic_float10_min #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 #if KMP_HAVE_QUAD MIN_MAX_CRITICAL(float16, max, QUAD_LEGACY, <, 16r, 1) // __kmpc_atomic_float16_max MIN_MAX_CRITICAL(float16, min, QUAD_LEGACY, >, 16r, 1) // __kmpc_atomic_float16_min #if (KMP_ARCH_X86) MIN_MAX_CRITICAL(float16, max_a16, Quad_a16_t, <, 16r, 1) // __kmpc_atomic_float16_max_a16 MIN_MAX_CRITICAL(float16, min_a16, Quad_a16_t, >, 16r, 1) // __kmpc_atomic_float16_min_a16 #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // ------------------------------------------------------------------------ // Need separate macros for .EQV. because of the need of complement (~) // OP ignored for critical sections, ^=~ used instead #define ATOMIC_CRIT_EQV(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … // ------------------------------------------------------------------------ #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------ // X86 or X86_64: no alignment problems =================================== #define ATOMIC_CMPX_EQV(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \ GOMP_FLAG) … // ------------------------------------------------------------------------ #else // ------------------------------------------------------------------------ // Code for other architectures that don't handle unaligned accesses. #define ATOMIC_CMPX_EQV … #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed1_neqv ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed2_neqv ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed4_neqv ATOMIC_CMPXCHG(…) // __kmpc_atomic_fixed8_neqv ATOMIC_CMPX_EQV(…) // __kmpc_atomic_fixed1_eqv ATOMIC_CMPX_EQV(…) // __kmpc_atomic_fixed2_eqv ATOMIC_CMPX_EQV(…) // __kmpc_atomic_fixed4_eqv ATOMIC_CMPX_EQV(…) // __kmpc_atomic_fixed8_eqv // ------------------------------------------------------------------------ // Routines for Extended types: long double, _Quad, complex flavours (use // critical section) // TYPE_ID, OP_ID, TYPE - detailed above // OP - operator // LCK_ID - lock identifier, used to possibly distinguish lock variable #define ATOMIC_CRITICAL(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … /* ------------------------------------------------------------------------- */ #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // routines for long double type ATOMIC_CRITICAL(…) // __kmpc_atomic_float10_add ATOMIC_CRITICAL(…) // __kmpc_atomic_float10_sub ATOMIC_CRITICAL(…) // __kmpc_atomic_float10_mul ATOMIC_CRITICAL(…) // __kmpc_atomic_float10_div #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 #if KMP_HAVE_QUAD // routines for _Quad type ATOMIC_CRITICAL(float16, add, QUAD_LEGACY, +, 16r, 1) // __kmpc_atomic_float16_add ATOMIC_CRITICAL(float16, sub, QUAD_LEGACY, -, 16r, 1) // __kmpc_atomic_float16_sub ATOMIC_CRITICAL(float16, mul, QUAD_LEGACY, *, 16r, 1) // __kmpc_atomic_float16_mul ATOMIC_CRITICAL(float16, div, QUAD_LEGACY, /, 16r, 1) // __kmpc_atomic_float16_div #if (KMP_ARCH_X86) ATOMIC_CRITICAL(float16, add_a16, Quad_a16_t, +, 16r, 1) // __kmpc_atomic_float16_add_a16 ATOMIC_CRITICAL(float16, sub_a16, Quad_a16_t, -, 16r, 1) // __kmpc_atomic_float16_sub_a16 ATOMIC_CRITICAL(float16, mul_a16, Quad_a16_t, *, 16r, 1) // __kmpc_atomic_float16_mul_a16 ATOMIC_CRITICAL(float16, div_a16, Quad_a16_t, /, 16r, 1) // __kmpc_atomic_float16_div_a16 #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // routines for complex types #if USE_CMPXCHG_FIX // workaround for C78287 (complex(kind=4) data type) ATOMIC_CMPXCHG_WORKAROUND(…) // __kmpc_atomic_cmplx4_add ATOMIC_CMPXCHG_WORKAROUND(…) // __kmpc_atomic_cmplx4_sub ATOMIC_CMPXCHG_WORKAROUND(…) // __kmpc_atomic_cmplx4_mul ATOMIC_CMPXCHG_WORKAROUND(…) // __kmpc_atomic_cmplx4_div // end of the workaround for C78287 #else ATOMIC_CRITICAL(cmplx4, add, kmp_cmplx32, +, 8c, 1) // __kmpc_atomic_cmplx4_add ATOMIC_CRITICAL(cmplx4, sub, kmp_cmplx32, -, 8c, 1) // __kmpc_atomic_cmplx4_sub ATOMIC_CRITICAL(cmplx4, mul, kmp_cmplx32, *, 8c, 1) // __kmpc_atomic_cmplx4_mul ATOMIC_CRITICAL(cmplx4, div, kmp_cmplx32, /, 8c, 1) // __kmpc_atomic_cmplx4_div #endif // USE_CMPXCHG_FIX ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx8_add ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx8_sub ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx8_mul ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx8_div #if KMP_ARCH_X86 || KMP_ARCH_X86_64 ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx10_add ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx10_sub ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx10_mul ATOMIC_CRITICAL(…) // __kmpc_atomic_cmplx10_div #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 #if KMP_HAVE_QUAD ATOMIC_CRITICAL(cmplx16, add, CPLX128_LEG, +, 32c, 1) // __kmpc_atomic_cmplx16_add ATOMIC_CRITICAL(cmplx16, sub, CPLX128_LEG, -, 32c, 1) // __kmpc_atomic_cmplx16_sub ATOMIC_CRITICAL(cmplx16, mul, CPLX128_LEG, *, 32c, 1) // __kmpc_atomic_cmplx16_mul ATOMIC_CRITICAL(cmplx16, div, CPLX128_LEG, /, 32c, 1) // __kmpc_atomic_cmplx16_div #if (KMP_ARCH_X86) ATOMIC_CRITICAL(cmplx16, add_a16, kmp_cmplx128_a16_t, +, 32c, 1) // __kmpc_atomic_cmplx16_add_a16 ATOMIC_CRITICAL(cmplx16, sub_a16, kmp_cmplx128_a16_t, -, 32c, 1) // __kmpc_atomic_cmplx16_sub_a16 ATOMIC_CRITICAL(cmplx16, mul_a16, kmp_cmplx128_a16_t, *, 32c, 1) // __kmpc_atomic_cmplx16_mul_a16 ATOMIC_CRITICAL(cmplx16, div_a16, kmp_cmplx128_a16_t, /, 32c, 1) // __kmpc_atomic_cmplx16_div_a16 #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // OpenMP 4.0: x = expr binop x for non-commutative operations. // Supported only on IA-32 architecture and Intel(R) 64 #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------ // Operation on *lhs, rhs bound by critical section // OP - operator (it's supposed to contain an assignment) // LCK_ID - lock identifier // Note: don't check gtid as it should always be valid // 1, 2-byte - expect valid parameter, other - check before this macro #define OP_CRITICAL_REV(TYPE, OP, LCK_ID) … #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_REV(TYPE, OP, FLAG) … #else #define OP_GOMP_CRITICAL_REV … #endif /* KMP_GOMP_COMPAT */ // Beginning of a definition (provides name, parameters, gebug trace) // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned // fixed) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operands' type #define ATOMIC_BEGIN_REV(TYPE_ID, OP_ID, TYPE, RET_TYPE) … // ------------------------------------------------------------------------ // Operation on *lhs, rhs using "compare_and_store" routine // TYPE - operands' type // BITS - size in bits, used to distinguish low level calls // OP - operator // Note: temp_val introduced in order to force the compiler to read // *lhs only once (w/o it the compiler reads *lhs twice) #define OP_CMPXCHG_REV(TYPE, BITS, OP) … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_REV(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, GOMP_FLAG) … // ------------------------------------------------------------------------ // Entries definition for integer operands // TYPE_ID - operands type and size (fixed4, float4) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operand type // BITS - size in bits, used to distinguish low level calls // OP - operator (used in critical section) // LCK_ID - lock identifier, used to possibly distinguish lock variable // TYPE_ID,OP_ID, TYPE, BITS,OP,LCK_ID,GOMP_FLAG // ------------------------------------------------------------------------ // Routines for ATOMIC integer operands, other operators // ------------------------------------------------------------------------ // TYPE_ID,OP_ID, TYPE, BITS, OP, LCK_ID, GOMP_FLAG ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed1_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed1u_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed1_shl_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed1_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed1u_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed1_sub_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed2_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed2u_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed2_shl_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed2_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed2u_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed2_sub_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed4_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed4u_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed4_shl_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed4_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed4u_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed4_sub_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed8_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed8u_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed8_shl_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed8_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed8u_shr_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_fixed8_sub_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_float4_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_float4_sub_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_float8_div_rev ATOMIC_CMPXCHG_REV(…) // __kmpc_atomic_float8_sub_rev // TYPE_ID,OP_ID, TYPE, BITS,OP,LCK_ID, GOMP_FLAG // ------------------------------------------------------------------------ // Routines for Extended types: long double, _Quad, complex flavours (use // critical section) // TYPE_ID, OP_ID, TYPE - detailed above // OP - operator // LCK_ID - lock identifier, used to possibly distinguish lock variable #define ATOMIC_CRITICAL_REV(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … /* ------------------------------------------------------------------------- */ // routines for long double type ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_float10_sub_rev ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_float10_div_rev #if KMP_HAVE_QUAD // routines for _Quad type ATOMIC_CRITICAL_REV(float16, sub, QUAD_LEGACY, -, 16r, 1) // __kmpc_atomic_float16_sub_rev ATOMIC_CRITICAL_REV(float16, div, QUAD_LEGACY, /, 16r, 1) // __kmpc_atomic_float16_div_rev #if (KMP_ARCH_X86) ATOMIC_CRITICAL_REV(float16, sub_a16, Quad_a16_t, -, 16r, 1) // __kmpc_atomic_float16_sub_a16_rev ATOMIC_CRITICAL_REV(float16, div_a16, Quad_a16_t, /, 16r, 1) // __kmpc_atomic_float16_div_a16_rev #endif // KMP_ARCH_X86 #endif // KMP_HAVE_QUAD // routines for complex types ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_cmplx4_sub_rev ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_cmplx4_div_rev ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_cmplx8_sub_rev ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_cmplx8_div_rev ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_cmplx10_sub_rev ATOMIC_CRITICAL_REV(…) // __kmpc_atomic_cmplx10_div_rev #if KMP_HAVE_QUAD ATOMIC_CRITICAL_REV(cmplx16, sub, CPLX128_LEG, -, 32c, 1) // __kmpc_atomic_cmplx16_sub_rev ATOMIC_CRITICAL_REV(cmplx16, div, CPLX128_LEG, /, 32c, 1) // __kmpc_atomic_cmplx16_div_rev #if (KMP_ARCH_X86) ATOMIC_CRITICAL_REV(cmplx16, sub_a16, kmp_cmplx128_a16_t, -, 32c, 1) // __kmpc_atomic_cmplx16_sub_a16_rev ATOMIC_CRITICAL_REV(cmplx16, div_a16, kmp_cmplx128_a16_t, /, 32c, 1) // __kmpc_atomic_cmplx16_div_a16_rev #endif // KMP_ARCH_X86 #endif // KMP_HAVE_QUAD #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 // End of OpenMP 4.0: x = expr binop x for non-commutative operations. /* ------------------------------------------------------------------------ */ /* Routines for mixed types of LHS and RHS, when RHS is "larger" */ /* Note: in order to reduce the total number of types combinations */ /* it is supposed that compiler converts RHS to longest floating type,*/ /* that is _Quad, before call to any of these routines */ /* Conversion to _Quad will be done by the compiler during calculation, */ /* conversion back to TYPE - before the assignment, like: */ /* *lhs = (TYPE)( (_Quad)(*lhs) OP rhs ) */ /* Performance penalty expected because of SW emulation use */ /* ------------------------------------------------------------------------ */ #define ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) … // ------------------------------------------------------------------------- #define ATOMIC_CRITICAL_FP(TYPE_ID, TYPE, OP_ID, OP, RTYPE_ID, RTYPE, LCK_ID, \ GOMP_FLAG) … // ------------------------------------------------------------------------- #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------- // X86 or X86_64: no alignment problems ==================================== #define ATOMIC_CMPXCHG_MIX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, RTYPE, \ LCK_ID, MASK, GOMP_FLAG) … // ------------------------------------------------------------------------- #else // ------------------------------------------------------------------------ // Code for other architectures that don't handle unaligned accesses. #define ATOMIC_CMPXCHG_MIX … #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ // ------------------------------------------------------------------------- #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_REV_MIX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, \ RTYPE, LCK_ID, MASK, GOMP_FLAG) … #define ATOMIC_CRITICAL_REV_FP(TYPE_ID, TYPE, OP_ID, OP, RTYPE_ID, RTYPE, \ LCK_ID, GOMP_FLAG) … #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ // RHS=float8 ATOMIC_CMPXCHG_MIX(fixed1, char, mul, 8, *, float8, kmp_real64, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul_float8 ATOMIC_CMPXCHG_MIX(fixed1, char, div, 8, /, float8, kmp_real64, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_float8 ATOMIC_CMPXCHG_MIX(fixed2, short, mul, 16, *, float8, kmp_real64, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul_float8 ATOMIC_CMPXCHG_MIX(fixed2, short, div, 16, /, float8, kmp_real64, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_float8 ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, mul, 32, *, float8, kmp_real64, 4i, 3, 0) // __kmpc_atomic_fixed4_mul_float8 ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, div, 32, /, float8, kmp_real64, 4i, 3, 0) // __kmpc_atomic_fixed4_div_float8 ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, mul, 64, *, float8, kmp_real64, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul_float8 ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, div, 64, /, float8, kmp_real64, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_float8 ATOMIC_CMPXCHG_MIX(float4, kmp_real32, add, 32, +, float8, kmp_real64, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_add_float8 ATOMIC_CMPXCHG_MIX(float4, kmp_real32, sub, 32, -, float8, kmp_real64, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_sub_float8 ATOMIC_CMPXCHG_MIX(float4, kmp_real32, mul, 32, *, float8, kmp_real64, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_mul_float8 ATOMIC_CMPXCHG_MIX(float4, kmp_real32, div, 32, /, float8, kmp_real64, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_div_float8 // RHS=float16 (deprecated, to be removed when we are sure the compiler does not // use them) #if KMP_HAVE_QUAD ATOMIC_CMPXCHG_MIX(fixed1, char, add, 8, +, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_add_fp ATOMIC_CMPXCHG_MIX(fixed1u, uchar, add, 8, +, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_add_fp ATOMIC_CMPXCHG_MIX(fixed1, char, sub, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_fp ATOMIC_CMPXCHG_MIX(fixed1u, uchar, sub, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_fp ATOMIC_CMPXCHG_MIX(fixed1, char, mul, 8, *, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul_fp ATOMIC_CMPXCHG_MIX(fixed1u, uchar, mul, 8, *, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_mul_fp ATOMIC_CMPXCHG_MIX(fixed1, char, div, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_fp ATOMIC_CMPXCHG_MIX(fixed1u, uchar, div, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_fp ATOMIC_CMPXCHG_MIX(fixed2, short, add, 16, +, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_add_fp ATOMIC_CMPXCHG_MIX(fixed2u, ushort, add, 16, +, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_add_fp ATOMIC_CMPXCHG_MIX(fixed2, short, sub, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_fp ATOMIC_CMPXCHG_MIX(fixed2u, ushort, sub, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_fp ATOMIC_CMPXCHG_MIX(fixed2, short, mul, 16, *, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul_fp ATOMIC_CMPXCHG_MIX(fixed2u, ushort, mul, 16, *, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_mul_fp ATOMIC_CMPXCHG_MIX(fixed2, short, div, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_fp ATOMIC_CMPXCHG_MIX(fixed2u, ushort, div, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_fp ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, add, 32, +, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_add_fp ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, add, 32, +, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_add_fp ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, sub, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_sub_fp ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, sub, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_sub_fp ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, mul, 32, *, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_mul_fp ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, mul, 32, *, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_mul_fp ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, div, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_div_fp ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, div, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_div_fp ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, add, 64, +, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_add_fp ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, add, 64, +, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_add_fp ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, sub, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_fp ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, sub, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_fp ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, mul, 64, *, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul_fp ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, mul, 64, *, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_mul_fp ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, div, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_fp ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, div, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_fp ATOMIC_CMPXCHG_MIX(float4, kmp_real32, add, 32, +, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_add_fp ATOMIC_CMPXCHG_MIX(float4, kmp_real32, sub, 32, -, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_sub_fp ATOMIC_CMPXCHG_MIX(float4, kmp_real32, mul, 32, *, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_mul_fp ATOMIC_CMPXCHG_MIX(float4, kmp_real32, div, 32, /, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_div_fp ATOMIC_CMPXCHG_MIX(float8, kmp_real64, add, 64, +, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_add_fp ATOMIC_CMPXCHG_MIX(float8, kmp_real64, sub, 64, -, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_sub_fp ATOMIC_CMPXCHG_MIX(float8, kmp_real64, mul, 64, *, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_mul_fp ATOMIC_CMPXCHG_MIX(float8, kmp_real64, div, 64, /, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_div_fp #if KMP_ARCH_X86 || KMP_ARCH_X86_64 ATOMIC_CRITICAL_FP(float10, long double, add, +, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_add_fp ATOMIC_CRITICAL_FP(float10, long double, sub, -, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_sub_fp ATOMIC_CRITICAL_FP(float10, long double, mul, *, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_mul_fp ATOMIC_CRITICAL_FP(float10, long double, div, /, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_div_fp // Reverse operations ATOMIC_CMPXCHG_REV_MIX(fixed1, char, sub_rev, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed1u, uchar, sub_rev, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed1, char, div_rev, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed1u, uchar, div_rev, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed2, short, sub_rev, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed2u, ushort, sub_rev, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed2, short, div_rev, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed2u, ushort, div_rev, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed4, kmp_int32, sub_rev, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed4u, kmp_uint32, sub_rev, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed4, kmp_int32, div_rev, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed4u, kmp_uint32, div_rev, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed8, kmp_int64, sub_rev, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed8u, kmp_uint64, sub_rev, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed8, kmp_int64, div_rev, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(fixed8u, kmp_uint64, div_rev, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(float4, kmp_real32, sub_rev, 32, -, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(float4, kmp_real32, div_rev, 32, /, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_div_rev_fp ATOMIC_CMPXCHG_REV_MIX(float8, kmp_real64, sub_rev, 64, -, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_sub_rev_fp ATOMIC_CMPXCHG_REV_MIX(float8, kmp_real64, div_rev, 64, /, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_div_rev_fp ATOMIC_CRITICAL_REV_FP(float10, long double, sub_rev, -, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_sub_rev_fp ATOMIC_CRITICAL_REV_FP(float10, long double, div_rev, /, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_div_rev_fp #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ #endif // KMP_HAVE_QUAD #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------ // X86 or X86_64: no alignment problems ==================================== #if USE_CMPXCHG_FIX // workaround for C78287 (complex(kind=4) data type) #define ATOMIC_CMPXCHG_CMPLX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, RTYPE, \ LCK_ID, MASK, GOMP_FLAG) … // end of the second part of the workaround for C78287 #else #define ATOMIC_CMPXCHG_CMPLX … #endif // USE_CMPXCHG_FIX #else // ------------------------------------------------------------------------ // Code for other architectures that don't handle unaligned accesses. #define ATOMIC_CMPXCHG_CMPLX … #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, add, 64, +, cmplx8, kmp_cmplx64, 8c, 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_add_cmplx8 ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, sub, 64, -, cmplx8, kmp_cmplx64, 8c, 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_sub_cmplx8 ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, mul, 64, *, cmplx8, kmp_cmplx64, 8c, 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_mul_cmplx8 ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, div, 64, /, cmplx8, kmp_cmplx64, 8c, 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_div_cmplx8 // READ, WRITE, CAPTURE // ------------------------------------------------------------------------ // Atomic READ routines // ------------------------------------------------------------------------ // Beginning of a definition (provides name, parameters, gebug trace) // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned // fixed) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operands' type #define ATOMIC_BEGIN_READ(TYPE_ID, OP_ID, TYPE, RET_TYPE) … // ------------------------------------------------------------------------ // Operation on *lhs, rhs using "compare_and_store_ret" routine // TYPE - operands' type // BITS - size in bits, used to distinguish low level calls // OP - operator // Note: temp_val introduced in order to force the compiler to read // *lhs only once (w/o it the compiler reads *lhs twice) // TODO: check if it is still necessary // Return old value regardless of the result of "compare & swap# operation #define OP_CMPXCHG_READ(TYPE, BITS, OP) … // ------------------------------------------------------------------------- // Operation on *lhs, rhs bound by critical section // OP - operator (it's supposed to contain an assignment) // LCK_ID - lock identifier // Note: don't check gtid as it should always be valid // 1, 2-byte - expect valid parameter, other - check before this macro #define OP_CRITICAL_READ(OP, LCK_ID) … // ------------------------------------------------------------------------- #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_READ(OP, FLAG) … #else #define OP_GOMP_CRITICAL_READ … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------- #define ATOMIC_FIXED_READ(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_READ(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------ // Routines for Extended types: long double, _Quad, complex flavours (use // critical section) // TYPE_ID, OP_ID, TYPE - detailed above // OP - operator // LCK_ID - lock identifier, used to possibly distinguish lock variable #define ATOMIC_CRITICAL_READ(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … // ------------------------------------------------------------------------ // Fix for cmplx4 read (CQ220361) on Windows* OS. Regular routine with return // value doesn't work. // Let's return the read value through the additional parameter. #if (KMP_OS_WINDOWS) #define OP_CRITICAL_READ_WRK … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_READ_WRK … #else #define OP_GOMP_CRITICAL_READ_WRK … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ #define ATOMIC_BEGIN_READ_WRK … // ------------------------------------------------------------------------ #define ATOMIC_CRITICAL_READ_WRK … #endif // KMP_OS_WINDOWS // ------------------------------------------------------------------------ // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG ATOMIC_FIXED_READ(…) // __kmpc_atomic_fixed4_rd ATOMIC_FIXED_READ(…) // __kmpc_atomic_fixed8_rd ATOMIC_CMPXCHG_READ(…) // __kmpc_atomic_float4_rd ATOMIC_CMPXCHG_READ(…) // __kmpc_atomic_float8_rd // !!! TODO: Remove lock operations for "char" since it can't be non-atomic ATOMIC_CMPXCHG_READ(…) // __kmpc_atomic_fixed1_rd ATOMIC_CMPXCHG_READ(…) // __kmpc_atomic_fixed2_rd ATOMIC_CRITICAL_READ(…) // __kmpc_atomic_float10_rd #if KMP_HAVE_QUAD ATOMIC_CRITICAL_READ(float16, rd, QUAD_LEGACY, +, 16r, 1) // __kmpc_atomic_float16_rd #endif // KMP_HAVE_QUAD // Fix for CQ220361 on Windows* OS #if (KMP_OS_WINDOWS) ATOMIC_CRITICAL_READ_WRK(cmplx4, rd, kmp_cmplx32, +, 8c, 1) // __kmpc_atomic_cmplx4_rd #else ATOMIC_CRITICAL_READ(…) // __kmpc_atomic_cmplx4_rd #endif // (KMP_OS_WINDOWS) ATOMIC_CRITICAL_READ(…) // __kmpc_atomic_cmplx8_rd ATOMIC_CRITICAL_READ(…) // __kmpc_atomic_cmplx10_rd #if KMP_HAVE_QUAD ATOMIC_CRITICAL_READ(cmplx16, rd, CPLX128_LEG, +, 32c, 1) // __kmpc_atomic_cmplx16_rd #if (KMP_ARCH_X86) ATOMIC_CRITICAL_READ(float16, a16_rd, Quad_a16_t, +, 16r, 1) // __kmpc_atomic_float16_a16_rd ATOMIC_CRITICAL_READ(cmplx16, a16_rd, kmp_cmplx128_a16_t, +, 32c, 1) // __kmpc_atomic_cmplx16_a16_rd #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // ------------------------------------------------------------------------ // Atomic WRITE routines #define ATOMIC_XCHG_WR(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------ #define ATOMIC_XCHG_FLOAT_WR(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------ // Operation on *lhs, rhs using "compare_and_store" routine // TYPE - operands' type // BITS - size in bits, used to distinguish low level calls // OP - operator // Note: temp_val introduced in order to force the compiler to read // *lhs only once (w/o it the compiler reads *lhs twice) #define OP_CMPXCHG_WR(TYPE, BITS, OP) … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_WR(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------ // Routines for Extended types: long double, _Quad, complex flavours (use // critical section) // TYPE_ID, OP_ID, TYPE - detailed above // OP - operator // LCK_ID - lock identifier, used to possibly distinguish lock variable #define ATOMIC_CRITICAL_WR(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … // ------------------------------------------------------------------------- ATOMIC_XCHG_WR(…) // __kmpc_atomic_fixed1_wr ATOMIC_XCHG_WR(…) // __kmpc_atomic_fixed2_wr ATOMIC_XCHG_WR(…) // __kmpc_atomic_fixed4_wr #if (KMP_ARCH_X86) ATOMIC_CMPXCHG_WR(fixed8, wr, kmp_int64, 64, =, KMP_ARCH_X86) // __kmpc_atomic_fixed8_wr #else ATOMIC_XCHG_WR(…) // __kmpc_atomic_fixed8_wr #endif // (KMP_ARCH_X86) ATOMIC_XCHG_FLOAT_WR(…) // __kmpc_atomic_float4_wr #if (KMP_ARCH_X86) ATOMIC_CMPXCHG_WR(float8, wr, kmp_real64, 64, =, KMP_ARCH_X86) // __kmpc_atomic_float8_wr #else ATOMIC_XCHG_FLOAT_WR(…) // __kmpc_atomic_float8_wr #endif // (KMP_ARCH_X86) ATOMIC_CRITICAL_WR(…) // __kmpc_atomic_float10_wr #if KMP_HAVE_QUAD ATOMIC_CRITICAL_WR(float16, wr, QUAD_LEGACY, =, 16r, 1) // __kmpc_atomic_float16_wr #endif // KMP_HAVE_QUAD ATOMIC_CRITICAL_WR(…) // __kmpc_atomic_cmplx4_wr ATOMIC_CRITICAL_WR(…) // __kmpc_atomic_cmplx8_wr ATOMIC_CRITICAL_WR(…) // __kmpc_atomic_cmplx10_wr #if KMP_HAVE_QUAD ATOMIC_CRITICAL_WR(cmplx16, wr, CPLX128_LEG, =, 32c, 1) // __kmpc_atomic_cmplx16_wr #if (KMP_ARCH_X86) ATOMIC_CRITICAL_WR(float16, a16_wr, Quad_a16_t, =, 16r, 1) // __kmpc_atomic_float16_a16_wr ATOMIC_CRITICAL_WR(cmplx16, a16_wr, kmp_cmplx128_a16_t, =, 32c, 1) // __kmpc_atomic_cmplx16_a16_wr #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // ------------------------------------------------------------------------ // Atomic CAPTURE routines // Beginning of a definition (provides name, parameters, gebug trace) // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned // fixed) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operands' type #define ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, RET_TYPE) … // ------------------------------------------------------------------------- // Operation on *lhs, rhs bound by critical section // OP - operator (it's supposed to contain an assignment) // LCK_ID - lock identifier // Note: don't check gtid as it should always be valid // 1, 2-byte - expect valid parameter, other - check before this macro #define OP_CRITICAL_CPT(OP, LCK_ID) … #define OP_UPDATE_CRITICAL_CPT(TYPE, OP, LCK_ID) … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_CPT(TYPE, OP, FLAG) … #else #define OP_GOMP_CRITICAL_CPT … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ // Operation on *lhs, rhs using "compare_and_store" routine // TYPE - operands' type // BITS - size in bits, used to distinguish low level calls // OP - operator // Note: temp_val introduced in order to force the compiler to read // *lhs only once (w/o it the compiler reads *lhs twice) #define OP_CMPXCHG_CPT(TYPE, BITS, OP) … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------- #define ATOMIC_FIXED_ADD_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------- ATOMIC_FIXED_ADD_CPT(…) // __kmpc_atomic_fixed4_add_cpt ATOMIC_FIXED_ADD_CPT(…) // __kmpc_atomic_fixed4_sub_cpt ATOMIC_FIXED_ADD_CPT(…) // __kmpc_atomic_fixed8_add_cpt ATOMIC_FIXED_ADD_CPT(…) // __kmpc_atomic_fixed8_sub_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float4_add_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float4_sub_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float8_add_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float8_sub_cpt // ------------------------------------------------------------------------ // Entries definition for integer operands // TYPE_ID - operands type and size (fixed4, float4) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operand type // BITS - size in bits, used to distinguish low level calls // OP - operator (used in critical section) // TYPE_ID,OP_ID, TYPE, BITS,OP,GOMP_FLAG // ------------------------------------------------------------------------ // Routines for ATOMIC integer operands, other operators // ------------------------------------------------------------------------ // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_add_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_andb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1u_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_mul_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_orb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_shl_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1u_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_sub_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_xor_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_add_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_andb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2u_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_mul_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_orb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_shl_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2u_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_sub_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_xor_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_andb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4u_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_mul_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_orb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_shl_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4u_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_xor_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_andb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8u_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_mul_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_orb_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_shl_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8u_shr_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_xor_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float4_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float4_mul_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float8_div_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_float8_mul_cpt // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG // CAPTURE routines for mixed types RHS=float16 #if KMP_HAVE_QUAD // Beginning of a definition (provides name, parameters, gebug trace) // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned // fixed) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operands' type #define ATOMIC_BEGIN_CPT_MIX … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_CPT_MIX … // ------------------------------------------------------------------------- #define ATOMIC_CRITICAL_CPT_MIX … ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, add_cpt, 8, +, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, add_cpt, 8, +, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, sub_cpt, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, sub_cpt, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, mul_cpt, 8, *, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, mul_cpt, 8, *, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, div_cpt, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, div_cpt, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, add_cpt, 16, +, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, add_cpt, 16, +, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, sub_cpt, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, sub_cpt, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, mul_cpt, 16, *, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, mul_cpt, 16, *, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, div_cpt, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, div_cpt, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, add_cpt, 32, +, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, add_cpt, 32, +, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, sub_cpt, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, sub_cpt, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, mul_cpt, 32, *, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, mul_cpt, 32, *, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, div_cpt, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, div_cpt, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, add_cpt, 64, +, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, add_cpt, 64, +, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, sub_cpt, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, sub_cpt, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, mul_cpt, 64, *, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, mul_cpt, 64, *, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, div_cpt, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, div_cpt, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, add_cpt, 32, +, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, sub_cpt, 32, -, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, mul_cpt, 32, *, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, div_cpt, 32, /, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_div_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, add_cpt, 64, +, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_add_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, sub_cpt, 64, -, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_sub_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, mul_cpt, 64, *, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_mul_cpt_fp ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, div_cpt, 64, /, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_div_cpt_fp ATOMIC_CRITICAL_CPT_MIX(float10, long double, add_cpt, +, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_add_cpt_fp ATOMIC_CRITICAL_CPT_MIX(float10, long double, sub_cpt, -, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_sub_cpt_fp ATOMIC_CRITICAL_CPT_MIX(float10, long double, mul_cpt, *, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_mul_cpt_fp ATOMIC_CRITICAL_CPT_MIX(float10, long double, div_cpt, /, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_div_cpt_fp #endif // KMP_HAVE_QUAD // ------------------------------------------------------------------------ // Routines for C/C++ Reduction operators && and || // ------------------------------------------------------------------------- // Operation on *lhs, rhs bound by critical section // OP - operator (it's supposed to contain an assignment) // LCK_ID - lock identifier // Note: don't check gtid as it should always be valid // 1, 2-byte - expect valid parameter, other - check before this macro #define OP_CRITICAL_L_CPT(OP, LCK_ID) … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_L_CPT(OP, FLAG) … #else #define OP_GOMP_CRITICAL_L_CPT … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ // Need separate macros for &&, || because there is no combined assignment #define ATOMIC_CMPX_L_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed1_andl_cpt ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed1_orl_cpt ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed2_andl_cpt ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed2_orl_cpt ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed4_andl_cpt ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed4_orl_cpt ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed8_andl_cpt ATOMIC_CMPX_L_CPT(…) // __kmpc_atomic_fixed8_orl_cpt // ------------------------------------------------------------------------- // Routines for Fortran operators that matched no one in C: // MAX, MIN, .EQV., .NEQV. // Operators .AND., .OR. are covered by __kmpc_atomic_*_{andl,orl}_cpt // Intrinsics IAND, IOR, IEOR are covered by __kmpc_atomic_*_{andb,orb,xor}_cpt // ------------------------------------------------------------------------- // MIN and MAX need separate macros // OP - operator to check if we need any actions? #define MIN_MAX_CRITSECT_CPT(OP, LCK_ID) … // ------------------------------------------------------------------------- #ifdef KMP_GOMP_COMPAT #define GOMP_MIN_MAX_CRITSECT_CPT(OP, FLAG) … #else #define GOMP_MIN_MAX_CRITSECT_CPT … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------- #define MIN_MAX_CMPXCHG_CPT(TYPE, BITS, OP) … // ------------------------------------------------------------------------- // 1-byte, 2-byte operands - use critical section #define MIN_MAX_CRITICAL_CPT(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … #define MIN_MAX_COMPXCHG_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed1_max_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed1_min_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed2_max_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed2_min_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed4_max_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed4_min_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed8_max_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_fixed8_min_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_float4_max_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_float4_min_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_float8_max_cpt MIN_MAX_COMPXCHG_CPT(…) // __kmpc_atomic_float8_min_cpt MIN_MAX_CRITICAL_CPT(…) // __kmpc_atomic_float10_max_cpt MIN_MAX_CRITICAL_CPT(…) // __kmpc_atomic_float10_min_cpt #if KMP_HAVE_QUAD MIN_MAX_CRITICAL_CPT(float16, max_cpt, QUAD_LEGACY, <, 16r, 1) // __kmpc_atomic_float16_max_cpt MIN_MAX_CRITICAL_CPT(float16, min_cpt, QUAD_LEGACY, >, 16r, 1) // __kmpc_atomic_float16_min_cpt #if (KMP_ARCH_X86) MIN_MAX_CRITICAL_CPT(float16, max_a16_cpt, Quad_a16_t, <, 16r, 1) // __kmpc_atomic_float16_max_a16_cpt MIN_MAX_CRITICAL_CPT(float16, min_a16_cpt, Quad_a16_t, >, 16r, 1) // __kmpc_atomic_float16_mix_a16_cpt #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_EQV_CPT(OP, FLAG) … #else #define OP_GOMP_CRITICAL_EQV_CPT … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ #define ATOMIC_CMPX_EQV_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … // ------------------------------------------------------------------------ ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed1_neqv_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed2_neqv_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed4_neqv_cpt ATOMIC_CMPXCHG_CPT(…) // __kmpc_atomic_fixed8_neqv_cpt ATOMIC_CMPX_EQV_CPT(…) // __kmpc_atomic_fixed1_eqv_cpt ATOMIC_CMPX_EQV_CPT(…) // __kmpc_atomic_fixed2_eqv_cpt ATOMIC_CMPX_EQV_CPT(…) // __kmpc_atomic_fixed4_eqv_cpt ATOMIC_CMPX_EQV_CPT(…) // __kmpc_atomic_fixed8_eqv_cpt // ------------------------------------------------------------------------ // Routines for Extended types: long double, _Quad, complex flavours (use // critical section) // TYPE_ID, OP_ID, TYPE - detailed above // OP - operator // LCK_ID - lock identifier, used to possibly distinguish lock variable #define ATOMIC_CRITICAL_CPT(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … // ------------------------------------------------------------------------ // Workaround for cmplx4. Regular routines with return value don't work // on Win_32e. Let's return captured values through the additional parameter. #define OP_CRITICAL_CPT_WRK(OP, LCK_ID) … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_CPT_WRK(OP, FLAG) … #else #define OP_GOMP_CRITICAL_CPT_WRK … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ #define ATOMIC_BEGIN_WRK(TYPE_ID, OP_ID, TYPE) … // ------------------------------------------------------------------------ #define ATOMIC_CRITICAL_CPT_WRK(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … // The end of workaround for cmplx4 /* ------------------------------------------------------------------------- */ // routines for long double type ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_float10_add_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_float10_sub_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_float10_mul_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_float10_div_cpt #if KMP_HAVE_QUAD // routines for _Quad type ATOMIC_CRITICAL_CPT(float16, add_cpt, QUAD_LEGACY, +, 16r, 1) // __kmpc_atomic_float16_add_cpt ATOMIC_CRITICAL_CPT(float16, sub_cpt, QUAD_LEGACY, -, 16r, 1) // __kmpc_atomic_float16_sub_cpt ATOMIC_CRITICAL_CPT(float16, mul_cpt, QUAD_LEGACY, *, 16r, 1) // __kmpc_atomic_float16_mul_cpt ATOMIC_CRITICAL_CPT(float16, div_cpt, QUAD_LEGACY, /, 16r, 1) // __kmpc_atomic_float16_div_cpt #if (KMP_ARCH_X86) ATOMIC_CRITICAL_CPT(float16, add_a16_cpt, Quad_a16_t, +, 16r, 1) // __kmpc_atomic_float16_add_a16_cpt ATOMIC_CRITICAL_CPT(float16, sub_a16_cpt, Quad_a16_t, -, 16r, 1) // __kmpc_atomic_float16_sub_a16_cpt ATOMIC_CRITICAL_CPT(float16, mul_a16_cpt, Quad_a16_t, *, 16r, 1) // __kmpc_atomic_float16_mul_a16_cpt ATOMIC_CRITICAL_CPT(float16, div_a16_cpt, Quad_a16_t, /, 16r, 1) // __kmpc_atomic_float16_div_a16_cpt #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // routines for complex types // cmplx4 routines to return void ATOMIC_CRITICAL_CPT_WRK(…) // __kmpc_atomic_cmplx4_add_cpt ATOMIC_CRITICAL_CPT_WRK(…) // __kmpc_atomic_cmplx4_sub_cpt ATOMIC_CRITICAL_CPT_WRK(…) // __kmpc_atomic_cmplx4_mul_cpt ATOMIC_CRITICAL_CPT_WRK(…) // __kmpc_atomic_cmplx4_div_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx8_add_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx8_sub_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx8_mul_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx8_div_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx10_add_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx10_sub_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx10_mul_cpt ATOMIC_CRITICAL_CPT(…) // __kmpc_atomic_cmplx10_div_cpt #if KMP_HAVE_QUAD ATOMIC_CRITICAL_CPT(cmplx16, add_cpt, CPLX128_LEG, +, 32c, 1) // __kmpc_atomic_cmplx16_add_cpt ATOMIC_CRITICAL_CPT(cmplx16, sub_cpt, CPLX128_LEG, -, 32c, 1) // __kmpc_atomic_cmplx16_sub_cpt ATOMIC_CRITICAL_CPT(cmplx16, mul_cpt, CPLX128_LEG, *, 32c, 1) // __kmpc_atomic_cmplx16_mul_cpt ATOMIC_CRITICAL_CPT(cmplx16, div_cpt, CPLX128_LEG, /, 32c, 1) // __kmpc_atomic_cmplx16_div_cpt #if (KMP_ARCH_X86) ATOMIC_CRITICAL_CPT(cmplx16, add_a16_cpt, kmp_cmplx128_a16_t, +, 32c, 1) // __kmpc_atomic_cmplx16_add_a16_cpt ATOMIC_CRITICAL_CPT(cmplx16, sub_a16_cpt, kmp_cmplx128_a16_t, -, 32c, 1) // __kmpc_atomic_cmplx16_sub_a16_cpt ATOMIC_CRITICAL_CPT(cmplx16, mul_a16_cpt, kmp_cmplx128_a16_t, *, 32c, 1) // __kmpc_atomic_cmplx16_mul_a16_cpt ATOMIC_CRITICAL_CPT(cmplx16, div_a16_cpt, kmp_cmplx128_a16_t, /, 32c, 1) // __kmpc_atomic_cmplx16_div_a16_cpt #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // OpenMP 4.0: v = x = expr binop x; { v = x; x = expr binop x; } { x = expr // binop x; v = x; } for non-commutative operations. // Supported only on IA-32 architecture and Intel(R) 64 #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // ------------------------------------------------------------------------- // Operation on *lhs, rhs bound by critical section // OP - operator (it's supposed to contain an assignment) // LCK_ID - lock identifier // Note: don't check gtid as it should always be valid // 1, 2-byte - expect valid parameter, other - check before this macro #define OP_CRITICAL_CPT_REV(TYPE, OP, LCK_ID) … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_CPT_REV(TYPE, OP, FLAG) … #else #define OP_GOMP_CRITICAL_CPT_REV … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ // Operation on *lhs, rhs using "compare_and_store" routine // TYPE - operands' type // BITS - size in bits, used to distinguish low level calls // OP - operator // Note: temp_val introduced in order to force the compiler to read // *lhs only once (w/o it the compiler reads *lhs twice) #define OP_CMPXCHG_CPT_REV(TYPE, BITS, OP) … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_CPT_REV(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) … ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed1_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed1u_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed1_shl_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed1_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed1u_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed1_sub_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed2_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed2u_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed2_shl_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed2_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed2u_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed2_sub_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed4_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed4u_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed4_shl_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed4_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed4u_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed4_sub_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed8_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed8u_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed8_shl_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed8_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed8u_shr_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_fixed8_sub_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_float4_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_float4_sub_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_float8_div_cpt_rev ATOMIC_CMPXCHG_CPT_REV(…) // __kmpc_atomic_float8_sub_cpt_rev // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG // ------------------------------------------------------------------------ // Routines for Extended types: long double, _Quad, complex flavours (use // critical section) // TYPE_ID, OP_ID, TYPE - detailed above // OP - operator // LCK_ID - lock identifier, used to possibly distinguish lock variable #define ATOMIC_CRITICAL_CPT_REV(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) … /* ------------------------------------------------------------------------- */ // routines for long double type ATOMIC_CRITICAL_CPT_REV(…) // __kmpc_atomic_float10_sub_cpt_rev ATOMIC_CRITICAL_CPT_REV(…) // __kmpc_atomic_float10_div_cpt_rev #if KMP_HAVE_QUAD // routines for _Quad type ATOMIC_CRITICAL_CPT_REV(float16, sub_cpt_rev, QUAD_LEGACY, -, 16r, 1) // __kmpc_atomic_float16_sub_cpt_rev ATOMIC_CRITICAL_CPT_REV(float16, div_cpt_rev, QUAD_LEGACY, /, 16r, 1) // __kmpc_atomic_float16_div_cpt_rev #if (KMP_ARCH_X86) ATOMIC_CRITICAL_CPT_REV(float16, sub_a16_cpt_rev, Quad_a16_t, -, 16r, 1) // __kmpc_atomic_float16_sub_a16_cpt_rev ATOMIC_CRITICAL_CPT_REV(float16, div_a16_cpt_rev, Quad_a16_t, /, 16r, 1) // __kmpc_atomic_float16_div_a16_cpt_rev #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // routines for complex types // ------------------------------------------------------------------------ // Workaround for cmplx4. Regular routines with return value don't work // on Win_32e. Let's return captured values through the additional parameter. #define OP_CRITICAL_CPT_REV_WRK(OP, LCK_ID) … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define OP_GOMP_CRITICAL_CPT_REV_WRK(OP, FLAG) … #else #define OP_GOMP_CRITICAL_CPT_REV_WRK … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ #define ATOMIC_CRITICAL_CPT_REV_WRK(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, \ GOMP_FLAG) … // The end of workaround for cmplx4 // !!! TODO: check if we need to return void for cmplx4 routines // cmplx4 routines to return void ATOMIC_CRITICAL_CPT_REV_WRK(…) // __kmpc_atomic_cmplx4_sub_cpt_rev ATOMIC_CRITICAL_CPT_REV_WRK(…) // __kmpc_atomic_cmplx4_div_cpt_rev ATOMIC_CRITICAL_CPT_REV(…) // __kmpc_atomic_cmplx8_sub_cpt_rev ATOMIC_CRITICAL_CPT_REV(…) // __kmpc_atomic_cmplx8_div_cpt_rev ATOMIC_CRITICAL_CPT_REV(…) // __kmpc_atomic_cmplx10_sub_cpt_rev ATOMIC_CRITICAL_CPT_REV(…) // __kmpc_atomic_cmplx10_div_cpt_rev #if KMP_HAVE_QUAD ATOMIC_CRITICAL_CPT_REV(cmplx16, sub_cpt_rev, CPLX128_LEG, -, 32c, 1) // __kmpc_atomic_cmplx16_sub_cpt_rev ATOMIC_CRITICAL_CPT_REV(cmplx16, div_cpt_rev, CPLX128_LEG, /, 32c, 1) // __kmpc_atomic_cmplx16_div_cpt_rev #if (KMP_ARCH_X86) ATOMIC_CRITICAL_CPT_REV(cmplx16, sub_a16_cpt_rev, kmp_cmplx128_a16_t, -, 32c, 1) // __kmpc_atomic_cmplx16_sub_a16_cpt_rev ATOMIC_CRITICAL_CPT_REV(cmplx16, div_a16_cpt_rev, kmp_cmplx128_a16_t, /, 32c, 1) // __kmpc_atomic_cmplx16_div_a16_cpt_rev #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // Capture reverse for mixed type: RHS=float16 #if KMP_HAVE_QUAD // Beginning of a definition (provides name, parameters, gebug trace) // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned // fixed) // OP_ID - operation identifier (add, sub, mul, ...) // TYPE - operands' type // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_CPT_REV_MIX … // ------------------------------------------------------------------------- #define ATOMIC_CRITICAL_CPT_REV_MIX … ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1, char, sub_cpt_rev, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1u, uchar, sub_cpt_rev, 8, -, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1, char, div_cpt_rev, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1u, uchar, div_cpt_rev, 8, /, fp, _Quad, 1i, 0, KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2, short, sub_cpt_rev, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2u, ushort, sub_cpt_rev, 16, -, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2, short, div_cpt_rev, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2u, ushort, div_cpt_rev, 16, /, fp, _Quad, 2i, 1, KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4, kmp_int32, sub_cpt_rev, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4u, kmp_uint32, sub_cpt_rev, 32, -, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4, kmp_int32, div_cpt_rev, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4u, kmp_uint32, div_cpt_rev, 32, /, fp, _Quad, 4i, 3, 0) // __kmpc_atomic_fixed4u_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8, kmp_int64, sub_cpt_rev, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8u, kmp_uint64, sub_cpt_rev, 64, -, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8, kmp_int64, div_cpt_rev, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8u, kmp_uint64, div_cpt_rev, 64, /, fp, _Quad, 8i, 7, KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(float4, kmp_real32, sub_cpt_rev, 32, -, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(float4, kmp_real32, div_cpt_rev, 32, /, fp, _Quad, 4r, 3, KMP_ARCH_X86) // __kmpc_atomic_float4_div_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(float8, kmp_real64, sub_cpt_rev, 64, -, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_sub_cpt_rev_fp ATOMIC_CMPXCHG_CPT_REV_MIX(float8, kmp_real64, div_cpt_rev, 64, /, fp, _Quad, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_div_cpt_rev_fp ATOMIC_CRITICAL_CPT_REV_MIX(float10, long double, sub_cpt_rev, -, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_sub_cpt_rev_fp ATOMIC_CRITICAL_CPT_REV_MIX(float10, long double, div_cpt_rev, /, fp, _Quad, 10r, 1) // __kmpc_atomic_float10_div_cpt_rev_fp #endif // KMP_HAVE_QUAD // OpenMP 4.0 Capture-write (swap): {v = x; x = expr;} #define ATOMIC_BEGIN_SWP(TYPE_ID, TYPE) … #define CRITICAL_SWP(LCK_ID) … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define GOMP_CRITICAL_SWP(FLAG) … #else #define GOMP_CRITICAL_SWP … #endif /* KMP_GOMP_COMPAT */ #define ATOMIC_XCHG_SWP(TYPE_ID, TYPE, BITS, GOMP_FLAG) … // ------------------------------------------------------------------------ #define ATOMIC_XCHG_FLOAT_SWP(TYPE_ID, TYPE, BITS, GOMP_FLAG) … // ------------------------------------------------------------------------ #define CMPXCHG_SWP(TYPE, BITS) … // ------------------------------------------------------------------------- #define ATOMIC_CMPXCHG_SWP(TYPE_ID, TYPE, BITS, GOMP_FLAG) … ATOMIC_XCHG_SWP(…) // __kmpc_atomic_fixed1_swp ATOMIC_XCHG_SWP(…) // __kmpc_atomic_fixed2_swp ATOMIC_XCHG_SWP(…) // __kmpc_atomic_fixed4_swp ATOMIC_XCHG_FLOAT_SWP(…) // __kmpc_atomic_float4_swp #if (KMP_ARCH_X86) ATOMIC_CMPXCHG_SWP(fixed8, kmp_int64, 64, KMP_ARCH_X86) // __kmpc_atomic_fixed8_swp ATOMIC_CMPXCHG_SWP(float8, kmp_real64, 64, KMP_ARCH_X86) // __kmpc_atomic_float8_swp #else ATOMIC_XCHG_SWP(…) // __kmpc_atomic_fixed8_swp ATOMIC_XCHG_FLOAT_SWP(…) // __kmpc_atomic_float8_swp #endif // (KMP_ARCH_X86) // ------------------------------------------------------------------------ // Routines for Extended types: long double, _Quad, complex flavours (use // critical section) #define ATOMIC_CRITICAL_SWP(TYPE_ID, TYPE, LCK_ID, GOMP_FLAG) … // ------------------------------------------------------------------------ // !!! TODO: check if we need to return void for cmplx4 routines // Workaround for cmplx4. Regular routines with return value don't work // on Win_32e. Let's return captured values through the additional parameter. #define ATOMIC_BEGIN_SWP_WRK(TYPE_ID, TYPE) … #define CRITICAL_SWP_WRK(LCK_ID) … // ------------------------------------------------------------------------ #ifdef KMP_GOMP_COMPAT #define GOMP_CRITICAL_SWP_WRK(FLAG) … #else #define GOMP_CRITICAL_SWP_WRK … #endif /* KMP_GOMP_COMPAT */ // ------------------------------------------------------------------------ #define ATOMIC_CRITICAL_SWP_WRK(TYPE_ID, TYPE, LCK_ID, GOMP_FLAG) … // The end of workaround for cmplx4 ATOMIC_CRITICAL_SWP(…) // __kmpc_atomic_float10_swp #if KMP_HAVE_QUAD ATOMIC_CRITICAL_SWP(float16, QUAD_LEGACY, 16r, 1) // __kmpc_atomic_float16_swp #endif // KMP_HAVE_QUAD // cmplx4 routine to return void ATOMIC_CRITICAL_SWP_WRK(…) // __kmpc_atomic_cmplx4_swp // ATOMIC_CRITICAL_SWP( cmplx4, kmp_cmplx32, 8c, 1 ) // // __kmpc_atomic_cmplx4_swp ATOMIC_CRITICAL_SWP(…) // __kmpc_atomic_cmplx8_swp ATOMIC_CRITICAL_SWP(…) // __kmpc_atomic_cmplx10_swp #if KMP_HAVE_QUAD ATOMIC_CRITICAL_SWP(cmplx16, CPLX128_LEG, 32c, 1) // __kmpc_atomic_cmplx16_swp #if (KMP_ARCH_X86) ATOMIC_CRITICAL_SWP(float16_a16, Quad_a16_t, 16r, 1) // __kmpc_atomic_float16_a16_swp ATOMIC_CRITICAL_SWP(cmplx16_a16, kmp_cmplx128_a16_t, 32c, 1) // __kmpc_atomic_cmplx16_a16_swp #endif // (KMP_ARCH_X86) #endif // KMP_HAVE_QUAD // End of OpenMP 4.0 Capture #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 #undef OP_CRITICAL /* ------------------------------------------------------------------------ */ /* Generic atomic routines */ void __kmpc_atomic_1(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } void __kmpc_atomic_2(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } void __kmpc_atomic_4(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } void __kmpc_atomic_8(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } #if KMP_ARCH_X86 || KMP_ARCH_X86_64 void __kmpc_atomic_10(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 void __kmpc_atomic_16(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } #if KMP_ARCH_X86 || KMP_ARCH_X86_64 void __kmpc_atomic_20(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 void __kmpc_atomic_32(ident_t *id_ref, int gtid, void *lhs, void *rhs, void (*f)(void *, void *, void *)) { … } // AC: same two routines as GOMP_atomic_start/end, but will be called by our // compiler; duplicated in order to not use 3-party names in pure Intel code // TODO: consider adding GTID parameter after consultation with Ernesto/Xinmin. void __kmpc_atomic_start(void) { … } void __kmpc_atomic_end(void) { … } #if KMP_ARCH_X86 || KMP_ARCH_X86_64 // OpenMP 5.1 compare and swap /*! @param loc Source code location @param gtid Global thread id @param x Memory location to operate on @param e Expected value @param d Desired value @return Result of comparison Implements Compare And Swap atomic operation. Sample code: #pragma omp atomic compare update capture { r = x == e; if(r) { x = d; } } */ bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d) { … } bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e, short d) { … } bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e, kmp_int32 d) { … } bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e, kmp_int64 d) { … } /*! @param loc Source code location @param gtid Global thread id @param x Memory location to operate on @param e Expected value @param d Desired value @return Old value of x Implements Compare And Swap atomic operation. Sample code: #pragma omp atomic compare update capture { v = x; if (x == e) { x = d; } } */ char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d) { … } short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e, short d) { … } kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e, kmp_int32 d) { … } kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e, kmp_int64 d) { … } /*! @param loc Source code location @param gtid Global thread id @param x Memory location to operate on @param e Expected value @param d Desired value @param pv Captured value location @return Result of comparison Implements Compare And Swap + Capture atomic operation. v gets old valie of x if comparison failed, untouched otherwise. Sample code: #pragma omp atomic compare update capture { r = x == e; if(r) { x = d; } else { v = x; } } */ bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d, char *pv) { … } bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d, short *pv) { … } bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e, kmp_int32 d, kmp_int32 *pv) { … } bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e, kmp_int64 d, kmp_int64 *pv) { … } /*! @param loc Source code location @param gtid Global thread id @param x Memory location to operate on @param e Expected value @param d Desired value @param pv Captured value location @return Old value of x Implements Compare And Swap + Capture atomic operation. v gets new valie of x. Sample code: #pragma omp atomic compare update capture { if (x == e) { x = d; }; v = x; } */ char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d, char *pv) { … } short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d, short *pv) { … } kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e, kmp_int32 d, kmp_int32 *pv) { … } kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e, kmp_int64 d, kmp_int64 *pv) { … } // End OpenMP 5.1 compare + capture #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 /*! @} */ // end of file