}
}
+/* 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
/* 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 ();
}
-/* 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).
#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 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);
+extern int omp_in_parallel (void) __GOMP_NOTHROW;
-extern void omp_set_dynamic (int);
-extern int omp_get_dynamic (void);
+extern void omp_set_dynamic (int) __GOMP_NOTHROW;
+extern int omp_get_dynamic (void) __GOMP_NOTHROW;
-extern void omp_set_nested (int);
-extern int omp_get_nested (void);
+extern void omp_set_nested (int) __GOMP_NOTHROW;
+extern int omp_get_nested (void) __GOMP_NOTHROW;
-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_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 *);
-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_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
}