diff mbox series

[committed] Avoid some Fortran FE opts in OpenMP atomics (PR fortran/92977)

Message ID 20191218233743.GP10088@tucnak
State New
Headers show
Series [committed] Avoid some Fortran FE opts in OpenMP atomics (PR fortran/92977) | expand

Commit Message

Jakub Jelinek Dec. 18, 2019, 11:37 p.m. UTC
Hi!

Similarly to EXEC_OMP_WORKSHARE, EXEC_OMP_ATOMIC has also very tight rules
what can and can't appear in the block, enforced through parsing and
resolving, so e.g. inserting EXEC_BLOCK there leads to ICEs.  In theory, one
could add such a BLOCK around the atomic rather than inside of it, but the
code isn't prepared to be able to do that and furthermore there is still
risk of breaking the EXEC_OMP_ATOMIC expectations.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
committed to trunk so far.

2019-12-19  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/92977
	* frontend-passes.c (in_omp_atomic): New variable.
	(cfe_expr_0, matmul_to_var_expr, matmul_temp_args,
	inline_matmul_assign, call_external_blas): Don't optimize in
	EXEC_OMP_ATOMIC.
	(optimize_namespace): Clear in_omp_atomic.
	(gfc_code_walker): Set in_omp_atomic for EXEC_OMP_ATOMIC, save/restore
	it around.

	* gfortran.dg/gomp/pr92977.f90: New test.


	Jakub
diff mbox series

Patch

--- gcc/fortran/frontend-passes.c.jj	2019-11-09 18:08:47.866374726 +0100
+++ gcc/fortran/frontend-passes.c	2019-12-18 14:45:23.996493420 +0100
@@ -92,6 +92,10 @@  static int forall_level;
 
 static bool in_omp_workshare;
 
+/* Keep track of whether we are within an OMP atomic.  */
+
+static bool in_omp_atomic;
+
 /* Keep track of whether we are within a WHERE statement.  */
 
 static bool in_where;
@@ -913,9 +917,9 @@  cfe_expr_0 (gfc_expr **e, int *walk_subt
   gfc_expr *newvar;
   gfc_expr **ei, **ej;
 
-  /* Don't do this optimization within OMP workshare or ASSOC lists.  */
+  /* Don't do this optimization within OMP workshare/atomic or ASSOC lists.  */
 
-  if (in_omp_workshare || in_assoc_list)
+  if (in_omp_workshare || in_omp_atomic || in_assoc_list)
     {
       *walk_subtrees = 0;
       return 0;
@@ -1464,6 +1468,7 @@  optimize_namespace (gfc_namespace *ns)
   iterator_level = 0;
   in_assoc_list = false;
   in_omp_workshare = false;
+  in_omp_atomic = false;
 
   if (flag_frontend_optimize)
     {
@@ -2818,7 +2823,7 @@  matmul_to_var_expr (gfc_expr **ep, int *
     return 0;
 
   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
-      || in_where || in_assoc_list)
+      || in_omp_atomic || in_where || in_assoc_list)
     return 0;
 
   /* Check if this is already in the form c = matmul(a,b).  */
@@ -2880,7 +2885,7 @@  matmul_temp_args (gfc_code **c, int *wal
     return 0;
 
   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
-      || in_where)
+      || in_omp_atomic || in_where)
     return 0;
 
   /* This has some duplication with inline_matmul_assign.  This
@@ -3848,7 +3853,7 @@  inline_matmul_assign (gfc_code **c, int
   /* For now don't do anything in OpenMP workshare, it confuses
      its translation, which expects only the allowed statements in there.
      We should figure out how to parallelize this eventually.  */
-  if (in_omp_workshare)
+  if (in_omp_workshare || in_omp_atomic)
     return 0;
 
   expr1 = co->expr1;
@@ -4385,7 +4390,7 @@  call_external_blas (gfc_code **c, int *w
   /* For now don't do anything in OpenMP workshare, it confuses
      its translation, which expects only the allowed statements in there. */
 
-  if (in_omp_workshare)
+  if (in_omp_workshare | in_omp_atomic)
     return 0;
 
   expr1 = co->expr1;
@@ -5047,6 +5052,7 @@  gfc_code_walker (gfc_code **c, walk_code
 	  gfc_code *co;
 	  gfc_association_list *alist;
 	  bool saved_in_omp_workshare;
+	  bool saved_in_omp_atomic;
 	  bool saved_in_where;
 
 	  /* There might be statement insertions before the current code,
@@ -5054,6 +5060,7 @@  gfc_code_walker (gfc_code **c, walk_code
 
 	  co = *c;
 	  saved_in_omp_workshare = in_omp_workshare;
+	  saved_in_omp_atomic = in_omp_atomic;
 	  saved_in_where = in_where;
 
 	  switch (co->op)
@@ -5251,6 +5258,10 @@  gfc_code_walker (gfc_code **c, walk_code
 	      WALK_SUBEXPR (co->ext.dt->extra_comma);
 	      break;
 
+	    case EXEC_OMP_ATOMIC:
+	      in_omp_atomic = true;
+	      break;
+
 	    case EXEC_OMP_PARALLEL:
 	    case EXEC_OMP_PARALLEL_DO:
 	    case EXEC_OMP_PARALLEL_DO_SIMD:
@@ -5368,6 +5379,7 @@  gfc_code_walker (gfc_code **c, walk_code
 	    select_level --;
 
 	  in_omp_workshare = saved_in_omp_workshare;
+	  in_omp_atomic = saved_in_omp_atomic;
 	  in_where = saved_in_where;
 	}
     }
--- gcc/testsuite/gfortran.dg/gomp/pr92977.f90.jj	2019-12-18 15:16:14.657486591 +0100
+++ gcc/testsuite/gfortran.dg/gomp/pr92977.f90	2019-12-18 15:16:08.310582750 +0100
@@ -0,0 +1,15 @@ 
+! PR fortran/92977
+! { dg-do compile }
+! { dg-additional-options "-O2" }
+
+program pr92977
+  integer :: n = 1
+  integer :: a
+!$omp atomic write
+  a = f(n) - f(n)
+contains
+  integer function f(x)
+    integer, intent(in) :: x
+    f = x
+  end
+end