re PR middle-end/36106 (#pragma omp atomic issues with floating point types)
authorJakub Jelinek <jakub@gcc.gnu.org>
Wed, 7 May 2008 07:28:14 +0000 (09:28 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 7 May 2008 07:28:14 +0000 (09:28 +0200)
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
gcc/omp-low.c
libgomp/ChangeLog
libgomp/testsuite/libgomp.c/atomic-5.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/atomic-6.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c/autopar-1.c [new file with mode: 0644]

index f35a21b5eeeebe0fe9344fd080807d689099451e..6147e35535698106583794c15ac24967b2648c0b 100644 (file)
@@ -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.
index 60b14800679904810dee6d092761432a25db2044..1d3bf7b1f9c119e057bd8bf57f66263950456dc8 100644 (file)
@@ -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.  */
index 7ad1189ac1dde1e596416d8da0b62b3a043371ad..3e98750e75159150e11f56ee5223f270a75bcff2 100644 (file)
@@ -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 (file)
index 0000000..3b4b0f1
--- /dev/null
@@ -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 (file)
index 0000000..949fc3d
--- /dev/null
@@ -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 (file)
index 0000000..e56549b
--- /dev/null
@@ -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;
+}