Commit c18c98c0 by Jakub Jelinek

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
parent 537d4fa6
2008-05-08 Uros Bizjak <ubizjak@gmail.com> 2008-05-07 Jakub Jelinek <jakub@redhat.com>
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 <ubizjak@gmail.com>
* config/i386/i386.c (ix86_expand_copysign): Force non-zero constant * config/i386/i386.c (ix86_expand_copysign): Force non-zero constant
TFmode op0 to register. TFmode op0 to register.
......
...@@ -3758,7 +3758,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, ...@@ -3758,7 +3758,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
tree addr, tree loaded_val, tree stored_val, tree addr, tree loaded_val, tree stored_val,
int index) 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; tree type, itype, cmpxchg, iaddr;
block_stmt_iterator bsi; block_stmt_iterator bsi;
basic_block loop_header = single_succ (load_bb); basic_block loop_header = single_succ (load_bb);
...@@ -3775,48 +3775,81 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_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. */ /* Load the initial value, replacing the OMP_ATOMIC_LOAD. */
bsi = bsi_last (load_bb); bsi = bsi_last (load_bb);
gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD); 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); 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)) if (gimple_in_ssa_p (cfun))
{ {
gcc_assert (phi_nodes (loop_header) == NULL_TREE); gcc_assert (phi_nodes (loop_header) == NULL_TREE);
phi = create_phi_node (loaded_val, loop_header); phi = create_phi_node (loadedi, loop_header);
SSA_NAME_DEF_STMT (loaded_val) = phi; SSA_NAME_DEF_STMT (loadedi) = phi;
SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)), SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
initial); initial);
} }
else else
bsi_insert_before (&bsi, bsi_insert_before (&bsi,
build_gimple_modify_stmt (loaded_val, initial), build_gimple_modify_stmt (loadedi, initial),
BSI_SAME_STMT); 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_remove (&bsi, true);
bsi = bsi_last (store_bb); bsi = bsi_last (store_bb);
gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE); gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE);
/* For floating-point values, we'll need to view-convert them to integers if (iaddr == addr)
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; storedi = stored_val;
iaddr = addr;
}
else else
{
loadedi = force_gimple_operand_bsi (&bsi,
build1 (VIEW_CONVERT_EXPR, itype,
loaded_val), true,
NULL_TREE, true, BSI_SAME_STMT);
storedi = storedi =
force_gimple_operand_bsi (&bsi, force_gimple_operand_bsi (&bsi,
build1 (VIEW_CONVERT_EXPR, itype, build1 (VIEW_CONVERT_EXPR, itype,
stored_val), true, NULL_TREE, true, stored_val), true, NULL_TREE, true,
BSI_SAME_STMT); BSI_SAME_STMT);
iaddr = fold_convert (build_pointer_type (itype), addr);
}
/* Build the compare&swap statement. */ /* Build the compare&swap statement. */
new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi); 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, ...@@ -3824,32 +3857,28 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
fold_convert (itype, new_storedi), fold_convert (itype, new_storedi),
true, NULL_TREE, true, NULL_TREE,
true, BSI_SAME_STMT); 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)) if (gimple_in_ssa_p (cfun))
old_vali = loadedi; old_vali = loadedi;
else else
{ {
old_vali = create_tmp_var (itype, NULL); 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); 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); x = build_gimple_modify_stmt (loadedi, new_storedi);
bsi_insert_before (&bsi, x, BSI_SAME_STMT); 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 /* Note that we always perform the comparison as an integer, even for
floating point. This allows the atomic operation to properly floating point. This allows the atomic operation to properly
succeed even with NaNs and -0.0. */ succeed even with NaNs and -0.0. */
x = build3 (COND_EXPR, void_type_node, x = build2 (NE_EXPR, boolean_type_node, new_storedi, old_vali);
build2 (NE_EXPR, boolean_type_node, x = build3 (COND_EXPR, void_type_node, x, NULL_TREE, NULL_TREE);
new_storedi, old_vali), NULL_TREE, NULL_TREE);
bsi_insert_before (&bsi, x, BSI_SAME_STMT); bsi_insert_before (&bsi, x, BSI_SAME_STMT);
/* Update cfg. */ /* Update cfg. */
...@@ -3859,12 +3888,12 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, ...@@ -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); 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 we are not in SSA). */
if (gimple_in_ssa_p (cfun)) if (gimple_in_ssa_p (cfun))
{ {
phi = phi_nodes (loop_header); 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. */ /* Remove OMP_ATOMIC_STORE. */
......
2008-05-07 Jakub Jelinek <jakub@redhat.com>
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 <Ralf.Wildenhues@gmx.de> 2008-04-21 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* acinclude.m4 (LIBGOMP_CHECK_SYNC_BUILTINS) * acinclude.m4 (LIBGOMP_CHECK_SYNC_BUILTINS)
......
/* 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;
}
/* 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;
}
/* { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment