aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/omp-low.c113
-rw-r--r--libgomp/ChangeLog7
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-5.c40
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-6.c36
-rw-r--r--libgomp/testsuite/libgomp.c/autopar-1.c44
6 files changed, 210 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f35a21b..6147e35 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
TFmode op0 to register.
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. */
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 7ad1189..3e98750 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -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>
* 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 0000000..3b4b0f1
--- /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 0000000..949fc3d
--- /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 0000000..e56549b
--- /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;
+}