diff mbox

[committed] Fix #pragma omp atomic handling

Message ID 20150204223552.GB1746@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 4, 2015, 10:35 p.m. UTC
Hi!

As the testcases show, not using build_binary_op resulted in sometimes
non-promoted arguments, and there were issues with division,
where we initially want to use TRUNC_DIV_EXPR, but if the arguments
are floating point, change it into RDIV_EXPR instead.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
committed to trunk (backports will follow later, but hopefully soon).

2015-02-04  Jakub Jelinek  <jakub@redhat.com>

	PR c/64824
	PR c/64868
gcc/c/
	* c-parser.c (c_parser_omp_atomic): Handle RDIV_EXPR.
gcc/cp/
	* parser.c (cp_parser_omp_atomic): Handle RDIV_EXPR.
gcc/c-family/
	* c-omp.c (c_finish_omp_atomic): Use TRUNC_DIV_EXPR
	instead of RDIV_EXPR.  Use build_binary_op instead of
	build2_loc.
libgomp/
	* testsuite/libgomp.c/pr64824.c: New test.
	* testsuite/libgomp.c/pr64868.c: New test.
	* testsuite/libgomp.c++/pr64824.C: New test.
	* testsuite/libgomp.c++/pr64868.C: New test.


	Jakub
diff mbox

Patch

--- gcc/c/c-parser.c.jj	2015-02-03 10:33:55.000000000 +0100
+++ gcc/c/c-parser.c	2015-02-04 17:57:50.318652940 +0100
@@ -12611,6 +12611,7 @@  restart:
 	    {
 	    case MULT_EXPR:
 	    case TRUNC_DIV_EXPR:
+	    case RDIV_EXPR:
 	    case PLUS_EXPR:
 	    case MINUS_EXPR:
 	    case LSHIFT_EXPR:
--- gcc/cp/parser.c.jj	2015-01-31 10:07:36.000000000 +0100
+++ gcc/cp/parser.c	2015-02-04 18:11:38.761575168 +0100
@@ -29835,6 +29835,7 @@  restart:
 		{
 		case MULT_EXPR:
 		case TRUNC_DIV_EXPR:
+		case RDIV_EXPR:
 		case PLUS_EXPR:
 		case MINUS_EXPR:
 		case LSHIFT_EXPR:
--- gcc/c-family/c-omp.c.jj	2015-01-15 23:39:03.000000000 +0100
+++ gcc/c-family/c-omp.c	2015-02-04 19:08:55.498673461 +0100
@@ -206,6 +206,9 @@  c_finish_omp_atomic (location_t loc, enu
       return error_mark_node;
     }
 
+  if (opcode == RDIV_EXPR)
+    opcode = TRUNC_DIV_EXPR;
+
   /* ??? Validate that rhs does not overlap lhs.  */
 
   /* Take and save the address of the lhs.  From then on we'll reference it
@@ -240,7 +243,7 @@  c_finish_omp_atomic (location_t loc, enu
      to do this, and then take it apart again.  */
   if (swapped)
     {
-      rhs = build2_loc (loc, opcode, TREE_TYPE (lhs), rhs, lhs);
+      rhs = build_binary_op (loc, opcode, rhs, lhs, 1);
       opcode = NOP_EXPR;
     }
   bool save = in_late_binary_op;
--- libgomp/testsuite/libgomp.c/pr64824.c.jj	2015-02-04 20:18:57.061199758 +0100
+++ libgomp/testsuite/libgomp.c/pr64824.c	2015-02-04 20:18:26.509710353 +0100
@@ -0,0 +1,16 @@ 
+/* PR c/64824 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp" } */
+
+int
+main ()
+{
+  long long a;
+  long long b = 1LL;
+  int c = 3;
+#pragma omp atomic capture
+  a = b = c << b;
+  if (b != 6LL || a != 6LL)
+    __builtin_abort ();
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/pr64868.c.jj	2015-02-04 19:46:39.570674828 +0100
+++ libgomp/testsuite/libgomp.c/pr64868.c	2015-02-04 19:46:19.000000000 +0100
@@ -0,0 +1,87 @@ 
+/* PR c/64868 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp" } */
+
+float f = 2.0f;
+double d = 4.0;
+long double ld = 8.0L;
+
+void
+foo ()
+{
+#pragma omp atomic
+  f = 1.0f / f;
+#pragma omp atomic
+  f = 1 / f;
+#pragma omp atomic
+  f = f / 2.0f;
+#pragma omp atomic
+  f = f / 2;
+#pragma omp atomic
+  f /= 2.0f;
+#pragma omp atomic
+  f /= 2;
+#pragma omp atomic
+  d = 1.0 / d;
+#pragma omp atomic
+  d = 1 / d;
+#pragma omp atomic
+  d = d / 2.0;
+#pragma omp atomic
+  d = d / 2;
+#pragma omp atomic
+  d /= 2.0;
+#pragma omp atomic
+  d /= 2;
+#pragma omp atomic
+  ld = 1.0L / ld;
+#pragma omp atomic
+  ld = 1 / ld;
+#pragma omp atomic
+  ld = ld / 2.0L;
+#pragma omp atomic
+  ld = ld / 2;
+#pragma omp atomic
+  ld /= 2.0L;
+#pragma omp atomic
+  ld /= 2;
+  if (f != 0.125f || d != 0.25 || ld != 0.5L)
+    __builtin_abort ();
+}
+
+#ifdef __cplusplus
+template <typename T, int N1, int N2>
+void
+bar ()
+{
+  T v = ::d;
+#pragma omp atomic
+  v *= 16;
+#pragma omp atomic
+  v = 1.0 / v;
+#pragma omp atomic
+  v = N1 / v;
+#pragma omp atomic
+  v = v / 2.0;
+#pragma omp atomic
+  v = v / N2;
+#pragma omp atomic
+  v /= 2.0;
+#pragma omp atomic
+  v /= N2;
+  if (v != 0.25)
+    __builtin_abort ();
+}
+#endif
+
+int
+main ()
+{
+  foo ();
+#ifdef __cplusplus
+  bar<float, 1, 2> ();
+  bar<double, 1, 2> ();
+  bar<long double, 1, 2> ();
+#endif
+  return 0;
+}
--- libgomp/testsuite/libgomp.c++/pr64824.C.jj	2015-02-04 20:19:23.268761761 +0100
+++ libgomp/testsuite/libgomp.c++/pr64824.C	2015-02-04 20:19:19.364827006 +0100
@@ -0,0 +1,5 @@ 
+// PR c/64824
+// { dg-do run }
+// { dg-options "-O2 -fopenmp" }
+
+#include "../libgomp.c/pr64824.c"
--- libgomp/testsuite/libgomp.c++/pr64868.C.jj	2015-02-04 19:47:23.565935798 +0100
+++ libgomp/testsuite/libgomp.c++/pr64868.C	2015-02-04 19:47:16.883048057 +0100
@@ -0,0 +1,5 @@ 
+// PR c/64868
+// { dg-do run }
+// { dg-options "-O2 -fopenmp" }
+
+#include "../libgomp.c/pr64868.c"