Hi! As mentioned in the PR, atomics on types that contain some inner padding (e.g. long double type on x86_64) have various issues. Before my ATOMIC_COMPARE_EXCHANGE internal-fn addition, unless the user uses atomic_compare_exchange* APIs and changes (e.g. copies elsewhere) the expected variable, what can worst case happen is that atomic_load (done using integral type covering all the bits) reads a value, then it is VCEd to long double and stored as long double into the "expected" variable and during this store, we can end up with random padding bits in the "expected" variable and the first CAS can fail because of that. But, with the RTL store of the new "expected" value which is done using the integral type the padding bits will have all proper values in the second iteration already. While with ATOMIC_COMPARE_EXCHANGE, the VIEW_CONVERT_EXPRs are visible in GIMPLE and it is possible that all iterations have some issues in the padding bits.
Thus, the following patch just disables the optimization for floating point types (float/double perhaps might be fine, but I'm worried about sNaNs), and also any other types that can contain some padding. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-07-01 Jakub Jelinek <ja...@redhat.com> PR middle-end/71716 * gimple-fold.c (optimize_atomic_compare_exchange_p): Return false for SCALAR_FLOAT_TYPE_P type of expected var, or if TYPE_PRECISION is different from mode's bitsize. Small cleanup. --- gcc/gimple-fold.c.jj 2016-06-28 10:26:52.000000000 +0200 +++ gcc/gimple-fold.c 2016-07-01 11:29:57.700252754 +0200 @@ -2984,12 +2984,19 @@ optimize_atomic_compare_exchange_p (gimp tree expected = gimple_call_arg (stmt, 1); if (TREE_CODE (expected) != ADDR_EXPR - || !SSA_VAR_P (TREE_OPERAND (expected, 0)) - || !is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (expected, 0))) + || !SSA_VAR_P (TREE_OPERAND (expected, 0))) + return false; + + tree etype = TREE_TYPE (TREE_OPERAND (expected, 0)); + if (!is_gimple_reg_type (etype) || !auto_var_in_fn_p (TREE_OPERAND (expected, 0), current_function_decl) - || TREE_THIS_VOLATILE (TREE_TYPE (TREE_OPERAND (expected, 0))) - || TREE_CODE (TREE_TYPE (TREE_OPERAND (expected, 0))) == VECTOR_TYPE - || TREE_CODE (TREE_TYPE (TREE_OPERAND (expected, 0))) == COMPLEX_TYPE) + || TREE_THIS_VOLATILE (etype) + || VECTOR_TYPE_P (etype) + || TREE_CODE (etype) == COMPLEX_TYPE + /* Don't optimize floating point expected vars, VIEW_CONVERT_EXPRs + might not preserve all the bits. See PR71716. */ + || SCALAR_FLOAT_TYPE_P (etype) + || TYPE_PRECISION (etype) != GET_MODE_BITSIZE (TYPE_MODE (etype))) return false; tree weak = gimple_call_arg (stmt, 3); @@ -3005,8 +3012,7 @@ optimize_atomic_compare_exchange_p (gimp && optab_handler (sync_compare_and_swap_optab, mode) == CODE_FOR_nothing) return false; - if (int_size_in_bytes (TREE_TYPE (TREE_OPERAND (expected, 0))) - != GET_MODE_SIZE (mode)) + if (int_size_in_bytes (etype) != GET_MODE_SIZE (mode)) return false; return true; Jakub