mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
537d4fa684
commit
c18c98c0ad
|
@ -1,4 +1,15 @@
|
||||||
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.
|
||||||
|
|
113
gcc/omp-low.c
113
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,
|
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,
|
||||||
/* 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
|
storedi = stored_val;
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
storedi =
|
||||||
loadedi = force_gimple_operand_bsi (&bsi,
|
force_gimple_operand_bsi (&bsi,
|
||||||
build1 (VIEW_CONVERT_EXPR, itype,
|
build1 (VIEW_CONVERT_EXPR, itype,
|
||||||
loaded_val), true,
|
stored_val), true, NULL_TREE, true,
|
||||||
NULL_TREE, true, BSI_SAME_STMT);
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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,
|
||||||
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,
|
||||||
|
|
||||||
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. */
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
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)
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue