From c18c98c0ade56bc46ce65bbf5cdff26a2577c990 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 7 May 2008 09:28:14 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 13 ++- gcc/omp-low.c | 113 +++++++++++++++--------- libgomp/ChangeLog | 7 ++ libgomp/testsuite/libgomp.c/atomic-5.c | 40 +++++++++ libgomp/testsuite/libgomp.c/atomic-6.c | 36 ++++++++ libgomp/testsuite/libgomp.c/autopar-1.c | 44 +++++++++ 6 files changed, 210 insertions(+), 43 deletions(-) create mode 100644 libgomp/testsuite/libgomp.c/atomic-5.c create mode 100644 libgomp/testsuite/libgomp.c/atomic-6.c create mode 100644 libgomp/testsuite/libgomp.c/autopar-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f35a21b5eee..6147e355356 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,15 @@ -2008-05-08 Uros Bizjak +2008-05-07 Jakub Jelinek + + 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. + +2008-05-07 Uros Bizjak * config/i386/i386.c (ix86_expand_copysign): Force non-zero constant TFmode op0 to register. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 60b14800679..1d3bf7b1f9c 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. */ diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 7ad1189ac1d..3e98750e751 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,10 @@ +2008-05-07 Jakub Jelinek + + PR middle-end/36106 + * testsuite/libgomp.c/atomic-5.c: New test. + * testsuite/libgomp.c/atomic-6.c: New test. + * testsuite/libgomp.c/autopar-1.c: New test. + 2008-04-21 Ralf Wildenhues * acinclude.m4 (LIBGOMP_CHECK_SYNC_BUILTINS) diff --git a/libgomp/testsuite/libgomp.c/atomic-5.c b/libgomp/testsuite/libgomp.c/atomic-5.c new file mode 100644 index 00000000000..3b4b0f11d64 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/atomic-5.c @@ -0,0 +1,40 @@ +/* PR middle-end/36106 */ +/* { dg-options "-O2" } */ +/* { dg-options "-O2 -mcx16" { target { { i?86-*-* x86_64-*-* } && lp64 } } } */ + +#ifdef __x86_64__ +# include "../../../gcc/config/i386/cpuid.h" +#endif + +extern void abort (void); + +int __attribute__((noinline)) +do_test (void) +{ + long double d = .0L; + int i; + #pragma omp parallel for shared (d) + for (i = 0; i < 10; i++) + #pragma omp atomic + d += 1.0L; + if (d != 10.0L) + abort (); + return 0; +} + +int +main (void) +{ +#ifdef __x86_64__ + unsigned int eax, ebx, ecx, edx; + + if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return 0; + + if (ecx & bit_CMPXCHG16B) + do_test (); +#else + do_test (); +#endif + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/atomic-6.c b/libgomp/testsuite/libgomp.c/atomic-6.c new file mode 100644 index 00000000000..949fc3d73da --- /dev/null +++ b/libgomp/testsuite/libgomp.c/atomic-6.c @@ -0,0 +1,36 @@ +/* PR middle-end/36106 */ +/* { dg-options "-O2" } */ +/* { dg-options "-O2 -march=i586" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ + +#ifdef __i386__ +# include "../../../gcc/config/i386/cpuid.h" +#endif + +extern void abort (void); + +union { unsigned long long l; double d; } u = { .l = 0x7ff0000000072301ULL }; + +int __attribute__((noinline)) +do_test (void) +{ +#pragma omp atomic + u.d += 1.0L; + return 0; +} + +int +main (void) +{ +#ifdef __i386__ + unsigned int eax, ebx, ecx, edx; + + if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return 0; + + if (edx & bit_CMPXCHG8B) + do_test (); +#else + do_test (); +#endif + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/autopar-1.c b/libgomp/testsuite/libgomp.c/autopar-1.c new file mode 100644 index 00000000000..e56549b4845 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/autopar-1.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-options "-ftree-parallelize-loops=4 -O2 -ffast-math" } */ + +extern void abort (void); + +double d[1024], e[1024]; +int f[1024], g[1024]; + +double __attribute__((noinline)) +foo (void) +{ + double s = 0.0; + int i; + for (i = 0; i < 1024; i++) + s += d[i] - e[i]; + return s; +} + +int __attribute__((noinline)) +bar (void) +{ + int s = 0, i; + for (i = 0; i < 1024; i++) + s += f[i] - g[i]; + return s; +} + +int +main (void) +{ + int i; + for (i = 0; i < 1024; i++) + { + d[i] = i * 2; + e[i] = i; + f[i] = i * 2; + g[i] = i; + } + if (foo () != 1023 * 1024 / 2) + abort (); + if (bar () != 1023 * 1024 / 2) + abort (); + return 0; +} -- 2.30.2