Hi! When expanding #pragma omp atomic or reduction merging using expand_omp_atomic_pipeline loop, we start by fetching the initial value using normal memory read and only in the second and following iteration use the one from the atomic compare and exchange. The initial value is just an optimization, it is better if it is what we'll want to use, but if it is something different, except perhaps for floating point exceptions it shouldn't really matter what exact value we load. This patch uses __atomic_load_N with MEMMODEL_RELAXED instead of normal load.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 2014-01-13 Jakub Jelinek <ja...@redhat.com> PR libgomp/59194 * omp-low.c (expand_omp_atomic_pipeline): Expand the initial load as __atomic_load_N if possible. --- gcc/omp-low.c.jj 2014-01-08 17:45:05.000000000 +0100 +++ gcc/omp-low.c 2014-01-10 21:12:22.498276852 +0100 @@ -7536,12 +7536,21 @@ expand_omp_atomic_pipeline (basic_block loadedi = loaded_val; } + fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1); + tree loaddecl = builtin_decl_explicit (fncode); + if (loaddecl) + initial + = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)), + build_call_expr (loaddecl, 2, iaddr, + build_int_cst (NULL_TREE, + MEMMODEL_RELAXED))); + else + initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr, + build_int_cst (TREE_TYPE (iaddr), 0)); + initial - = force_gimple_operand_gsi (&si, - build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), - iaddr, - build_int_cst (TREE_TYPE (iaddr), 0)), - true, NULL_TREE, true, GSI_SAME_STMT); + = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true, + GSI_SAME_STMT); /* Move the value to the LOADEDI temporary. */ if (gimple_in_ssa_p (cfun)) Jakub