This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp] RFC: Optimize omp_get_{num_threads,thread_num} () calls


Hi!

omp_get_thread_num () and omp_get_num_threads () seem to be used heavily
in OpenMP constructs, but they can't be declared const, because while
they are const within a particular parallel region, they can return different
values e.g. before #omp parallel and inside of it etc.
OpenMP 3.0 makes this even worse, because in untied tasks omp_get_thread_num ()
can change at many places.  __builtin_omp_get_thread_num () and
__builtin_omp_get_num_threads () is marked as const though - we use it
only in GCC generated code which resides in #pragma omp parallel separate
functions, which aren't inlininable.  The following patch extends this,
by transforming even the user calls into the __builtin_omp_* inside the new
artificial functions created for omp parallel (for omp task if untied it
would just do that for omp_get_num_threads).  With 3.0 on the horizon
it is probably a bad idea to do in orphaned constructs, because we don't
know if they can't be called by untied task.

Do you think this is reasonably safe?

Guess the omp.h part is useful anyway, none of these functions should throw.

2007-11-20  Jakub Jelinek  <jakub@redhat.com>

	* omp-low.c (optimize_omp_library_calls): New function.
	(expand_omp_parallel): Call it if optimizing.

	* omp.h.in (__GOMP_NOTHROW): Define.  Use it on omp_* prototypes.

--- gcc/gcc/omp-low.c.jj	2007-10-30 11:46:29.000000000 +0100
+++ gcc/gcc/omp-low.c	2007-11-20 16:17:54.000000000 +0100
@@ -2433,6 +2433,61 @@ remove_exit_barriers (struct omp_region 
     }
 }
 
+/* Optimize omp_get_thread_num () and omp_get_num_threads ()
+   calls.  These can't be declared as const functions, but
+   within one parallel body they are constant, so they can be
+   transformed there into __builtin_omp_get_{thread_num,num_threads} ()
+   which are declared const.  */
+
+static void
+optimize_omp_library_calls (void)
+{
+  basic_block bb;
+  block_stmt_iterator bsi;
+  tree thr_num_id
+    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
+  tree num_thr_id
+    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
+
+  FOR_EACH_BB (bb)
+    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+      {
+	tree stmt = bsi_stmt (bsi);
+	tree call = get_call_expr_in (stmt);
+	tree decl;
+
+	if (call
+	    && (decl = get_callee_fndecl (call))
+	    && DECL_EXTERNAL (decl)
+	    && TREE_PUBLIC (decl)
+	    && DECL_INITIAL (decl) == NULL)
+	  {
+	    tree built_in;
+
+	    if (DECL_NAME (decl) == thr_num_id)
+	      built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
+	    else if (DECL_NAME (decl) == num_thr_id)
+	      built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
+	    else
+	      continue;
+
+	    if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
+		|| call_expr_nargs (call) != 0)
+	      continue;
+
+	    if (flag_exceptions && !TREE_NOTHROW (decl))
+	      continue;
+
+	    if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
+		|| TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl)))
+		   != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
+	      continue;
+
+	    CALL_EXPR_FN (call) = build_fold_addr_expr (built_in);
+	  }
+      }
+}
+
 /* Expand the OpenMP parallel directive starting at REGION.  */
 
 static void
@@ -2595,6 +2650,8 @@ expand_omp_parallel (struct omp_region *
       /* Fix the callgraph edges for child_cfun.  Those for cfun will be
 	 fixed in a following pass.  */
       push_cfun (child_cfun);
+      if (optimize)
+	optimize_omp_library_calls ();
       rebuild_cgraph_edges ();
       pop_cfun ();
     }
--- gcc/libgomp/omp.h.in.jj	2006-10-05 00:24:40.000000000 +0200
+++ gcc/libgomp/omp.h.in	2007-11-20 15:58:57.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -49,36 +49,39 @@ typedef struct
 
 #ifdef __cplusplus
 extern "C" {
+# define __GOMP_NOTHROW throw ()
+#else
+# define __GOMP_NOTHROW __attribute__((__nothrow__))
 #endif
 
-extern void omp_set_num_threads (int);
-extern int omp_get_num_threads (void);
-extern int omp_get_max_threads (void);
-extern int omp_get_thread_num (void);
-extern int omp_get_num_procs (void);
-
-extern int omp_in_parallel (void);
-
-extern void omp_set_dynamic (int);
-extern int omp_get_dynamic (void);
-
-extern void omp_set_nested (int);
-extern int omp_get_nested (void);
-
-extern void omp_init_lock (omp_lock_t *);
-extern void omp_destroy_lock (omp_lock_t *);
-extern void omp_set_lock (omp_lock_t *);
-extern void omp_unset_lock (omp_lock_t *);
-extern int omp_test_lock (omp_lock_t *);
-
-extern void omp_init_nest_lock (omp_nest_lock_t *);
-extern void omp_destroy_nest_lock (omp_nest_lock_t *);
-extern void omp_set_nest_lock (omp_nest_lock_t *);
-extern void omp_unset_nest_lock (omp_nest_lock_t *);
-extern int omp_test_nest_lock (omp_nest_lock_t *);
+extern void omp_set_num_threads (int) __GOMP_NOTHROW;
+extern int omp_get_num_threads (void) __GOMP_NOTHROW;
+extern int omp_get_max_threads (void) __GOMP_NOTHROW;
+extern int omp_get_thread_num (void) __GOMP_NOTHROW;
+extern int omp_get_num_procs (void) __GOMP_NOTHROW;
+
+extern int omp_in_parallel (void) __GOMP_NOTHROW;
+
+extern void omp_set_dynamic (int) __GOMP_NOTHROW;
+extern int omp_get_dynamic (void) __GOMP_NOTHROW;
+
+extern void omp_set_nested (int) __GOMP_NOTHROW;
+extern int omp_get_nested (void) __GOMP_NOTHROW;
+
+extern void omp_init_lock (omp_lock_t *) __GOMP_NOTHROW;
+extern void omp_destroy_lock (omp_lock_t *) __GOMP_NOTHROW;
+extern void omp_set_lock (omp_lock_t *) __GOMP_NOTHROW;
+extern void omp_unset_lock (omp_lock_t *) __GOMP_NOTHROW;
+extern int omp_test_lock (omp_lock_t *) __GOMP_NOTHROW;
+
+extern void omp_init_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern void omp_destroy_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern void omp_set_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern void omp_unset_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern int omp_test_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
 
-extern double omp_get_wtime (void);
-extern double omp_get_wtick (void);
+extern double omp_get_wtime (void) __GOMP_NOTHROW;
+extern double omp_get_wtick (void) __GOMP_NOTHROW;
 
 #ifdef __cplusplus
 }

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]