diff options
author | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-05-07 09:28:14 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-05-07 09:28:14 +0200 |
commit | c18c98c0ade56bc46ce65bbf5cdff26a2577c990 (patch) | |
tree | 8a49369b064d64c16fa89af2d0a836f7966d2e98 /gcc/omp-low.c | |
parent | 537d4fa684f272ea72c1c8db58e4f1dcd3b7cda4 (diff) | |
download | gcc-c18c98c0ade56bc46ce65bbf5cdff26a2577c990.zip gcc-c18c98c0ade56bc46ce65bbf5cdff26a2577c990.tar.gz gcc-c18c98c0ade56bc46ce65bbf5cdff26a2577c990.tar.bz2 |
re PR middle-end/36106 (#pragma omp atomic issues with floating point types)
PR middle-end/36106
* omp-low.c (expand_omp_atomic_pipeline): Load value using the
integral type rather than floating point, then VIEW_CONVERT_EXPR
to the floating point type.
* testsuite/libgomp.c/atomic-5.c: New test.
* testsuite/libgomp.c/atomic-6.c: New test.
* testsuite/libgomp.c/autopar-1.c: New test.
From-SVN: r135027
Diffstat (limited to 'gcc/omp-low.c')
-rw-r--r-- | gcc/omp-low.c | 113 |
1 files changed, 71 insertions, 42 deletions
diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 60b1480..1d3bf7b 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3758,7 +3758,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, tree addr, tree loaded_val, tree stored_val, int index) { - tree loadedi, storedi, initial, new_stored, new_storedi, old_vali; + tree loadedi, storedi, initial, new_storedi, old_vali; tree type, itype, cmpxchg, iaddr; block_stmt_iterator bsi; basic_block loop_header = single_succ (load_bb); @@ -3775,48 +3775,81 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, /* Load the initial value, replacing the OMP_ATOMIC_LOAD. */ bsi = bsi_last (load_bb); gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD); - initial = force_gimple_operand_bsi (&bsi, build_fold_indirect_ref (addr), + /* For floating-point values, we'll need to view-convert them to integers + so that we can perform the atomic compare and swap. Simplify the + following code by always setting up the "i"ntegral variables. */ + if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type)) + { + iaddr = create_tmp_var (build_pointer_type (itype), NULL); + x = build_gimple_modify_stmt (iaddr, + fold_convert (TREE_TYPE (iaddr), addr)); + force_gimple_operand_bsi (&bsi, x, true, NULL_TREE, + true, BSI_SAME_STMT); + DECL_NO_TBAA_P (iaddr) = 1; + DECL_POINTER_ALIAS_SET (iaddr) = 0; + loadedi = create_tmp_var (itype, NULL); + if (gimple_in_ssa_p (cfun)) + { + add_referenced_var (iaddr); + add_referenced_var (loadedi); + loadedi = make_ssa_name (loadedi, NULL); + } + } + else + { + iaddr = addr; + loadedi = loaded_val; + } + initial = force_gimple_operand_bsi (&bsi, build_fold_indirect_ref (iaddr), true, NULL_TREE, true, BSI_SAME_STMT); - /* Move the value to the LOADED_VAL temporary. */ + + /* Move the value to the LOADEDI temporary. */ if (gimple_in_ssa_p (cfun)) { gcc_assert (phi_nodes (loop_header) == NULL_TREE); - phi = create_phi_node (loaded_val, loop_header); - SSA_NAME_DEF_STMT (loaded_val) = phi; + phi = create_phi_node (loadedi, loop_header); + SSA_NAME_DEF_STMT (loadedi) = phi; SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)), initial); } else bsi_insert_before (&bsi, - build_gimple_modify_stmt (loaded_val, initial), + build_gimple_modify_stmt (loadedi, initial), BSI_SAME_STMT); + if (loadedi != loaded_val) + { + block_stmt_iterator bsi2; + + x = build1 (VIEW_CONVERT_EXPR, type, loadedi); + bsi2 = bsi_start (loop_header); + if (gimple_in_ssa_p (cfun)) + { + x = force_gimple_operand_bsi (&bsi2, x, true, NULL_TREE, + true, BSI_SAME_STMT); + x = build_gimple_modify_stmt (loaded_val, x); + bsi_insert_before (&bsi2, x, BSI_SAME_STMT); + SSA_NAME_DEF_STMT (loaded_val) = x; + } + else + { + x = build_gimple_modify_stmt (loaded_val, x); + force_gimple_operand_bsi (&bsi2, x, true, NULL_TREE, + true, BSI_SAME_STMT); + } + } bsi_remove (&bsi, true); bsi = bsi_last (store_bb); gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE); - /* For floating-point values, we'll need to view-convert them to integers - so that we can perform the atomic compare and swap. Simplify the - following code by always setting up the "i"ntegral variables. */ - if (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)) - { - loadedi = loaded_val; - storedi = stored_val; - iaddr = addr; - } + if (iaddr == addr) + storedi = stored_val; else - { - loadedi = force_gimple_operand_bsi (&bsi, - build1 (VIEW_CONVERT_EXPR, itype, - loaded_val), true, - NULL_TREE, true, BSI_SAME_STMT); - storedi = - force_gimple_operand_bsi (&bsi, - build1 (VIEW_CONVERT_EXPR, itype, - stored_val), true, NULL_TREE, true, - BSI_SAME_STMT); - iaddr = fold_convert (build_pointer_type (itype), addr); - } + storedi = + force_gimple_operand_bsi (&bsi, + build1 (VIEW_CONVERT_EXPR, itype, + stored_val), true, NULL_TREE, true, + BSI_SAME_STMT); /* Build the compare&swap statement. */ new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi); @@ -3824,32 +3857,28 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, fold_convert (itype, new_storedi), true, NULL_TREE, true, BSI_SAME_STMT); - if (storedi == stored_val) - new_stored = new_storedi; - else - new_stored = force_gimple_operand_bsi (&bsi, - build1 (VIEW_CONVERT_EXPR, type, - new_storedi), true, - NULL_TREE, true, BSI_SAME_STMT); if (gimple_in_ssa_p (cfun)) old_vali = loadedi; else { old_vali = create_tmp_var (itype, NULL); + if (gimple_in_ssa_p (cfun)) + add_referenced_var (old_vali); x = build_gimple_modify_stmt (old_vali, loadedi); - bsi_insert_before (&bsi, x, BSI_SAME_STMT); + force_gimple_operand_bsi (&bsi, x, true, NULL_TREE, + true, BSI_SAME_STMT); - x = build_gimple_modify_stmt (loaded_val, new_stored); - bsi_insert_before (&bsi, x, BSI_SAME_STMT); + x = build_gimple_modify_stmt (loadedi, new_storedi); + force_gimple_operand_bsi (&bsi, x, true, NULL_TREE, + true, BSI_SAME_STMT); } /* Note that we always perform the comparison as an integer, even for floating point. This allows the atomic operation to properly succeed even with NaNs and -0.0. */ - x = build3 (COND_EXPR, void_type_node, - build2 (NE_EXPR, boolean_type_node, - new_storedi, old_vali), NULL_TREE, NULL_TREE); + x = build2 (NE_EXPR, boolean_type_node, new_storedi, old_vali); + x = build3 (COND_EXPR, void_type_node, x, NULL_TREE, NULL_TREE); bsi_insert_before (&bsi, x, BSI_SAME_STMT); /* Update cfg. */ @@ -3859,12 +3888,12 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE); - /* Copy the new value to loaded_val (we already did that before the condition + /* Copy the new value to loadedi (we already did that before the condition if we are not in SSA). */ if (gimple_in_ssa_p (cfun)) { phi = phi_nodes (loop_header); - SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_stored); + SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi); } /* Remove OMP_ATOMIC_STORE. */ |