#include "gimple-pretty-print.h"
#include "stringpool.h"
#include "attribs.h"
+#include "omp-offload.h"
/* Lowering of OMP parallel and workshare constructs proceeds in two
phases. The first phase scans the function looking for OMP statements
g->have_offload = true;
}
- if (cgraph_node::get_create (decl)->offloadable
- && !lookup_attribute ("omp declare target",
- DECL_ATTRIBUTES (current_function_decl)))
+ if (cgraph_node::get_create (decl)->offloadable)
{
const char *target_attr = (is_gimple_omp_offloaded (ctx->stmt)
? "omp target entrypoint"
: "omp declare target");
- DECL_ATTRIBUTES (decl)
- = tree_cons (get_identifier (target_attr),
- NULL_TREE, DECL_ATTRIBUTES (decl));
+ if (lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (current_function_decl)))
+ {
+ if (is_gimple_omp_offloaded (ctx->stmt))
+ DECL_ATTRIBUTES (decl)
+ = remove_attribute ("omp declare target",
+ copy_list (DECL_ATTRIBUTES (decl)));
+ else
+ target_attr = NULL;
+ }
+ if (target_attr)
+ DECL_ATTRIBUTES (decl)
+ = tree_cons (get_identifier (target_attr),
+ NULL_TREE, DECL_ATTRIBUTES (decl));
}
t = build_decl (DECL_SOURCE_LOCATION (decl),
gimple_build_assign (TREE_VEC_ELT (t, i),
clobber));
}
+ else if (omp_maybe_offloaded_ctx (ctx->outer))
+ {
+ tree id = get_identifier ("omp declare target");
+ tree decl = TREE_VEC_ELT (t, i);
+ DECL_ATTRIBUTES (decl)
+ = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
+ varpool_node *node = varpool_node::get (decl);
+ if (node)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING)
+ {
+ g->have_offload = true;
+ vec_safe_push (offload_vars, t);
+ }
+ }
+ }
tree clobber = build_clobber (ctx->record_type);
gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
- gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
+ {
+ if (gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_GOMP_TARGET))
+ {
+ /* Nullify the second argument of __builtin_GOMP_target_ext. */
+ gimple_call_set_arg (gsi_stmt (gsi), 1, null_pointer_node);
+ update_stmt (gsi_stmt (gsi));
+ }
+ if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
+ gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
+ }
}
return 0;
ialias (omp_pause_resource)
ialias (omp_pause_resource_all)
+
+void
+GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend, void **args)
+{
+ (void) device;
+ (void) fn;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ (void) args;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_data_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_end_data (void)
+{
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_update_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
ialias (omp_pause_resource)
ialias (omp_pause_resource_all)
+
+void
+GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend, void **args)
+{
+ (void) device;
+ (void) fn;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ (void) args;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_data_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_end_data (void)
+{
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_update_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
#define M(x, y, z) O(x, y, z)
#define O(x, y, z) x ## _ ## y ## _ ## z
+#define DO_PRAGMA(x) _Pragma (#x)
+#define OMPTEAMS DO_PRAGMA (omp target teams)
+#define OMPFROM(v) DO_PRAGMA (omp target update from(v))
+#define OMPTO(v) DO_PRAGMA (omp target update to(v))
+
#pragma omp declare target
#define F distribute
main ()
{
int err = 0;
- #pragma omp target teams reduction(|:err)
- {
- err |= test_d_normal ();
- err |= test_d_ds128_normal ();
- err |= test_ds_normal ();
- err |= test_ds_ds128_normal ();
- err |= test_dpf_static ();
- err |= test_dpf_static32 ();
- err |= test_dpf_auto ();
- err |= test_dpf_guided32 ();
- err |= test_dpf_runtime ();
- err |= test_dpf_ds128_static ();
- err |= test_dpf_ds128_static32 ();
- err |= test_dpf_ds128_auto ();
- err |= test_dpf_ds128_guided32 ();
- err |= test_dpf_ds128_runtime ();
- err |= test_dpfs_static ();
- err |= test_dpfs_static32 ();
- err |= test_dpfs_auto ();
- err |= test_dpfs_guided32 ();
- err |= test_dpfs_runtime ();
- err |= test_dpfs_ds128_static ();
- err |= test_dpfs_ds128_static32 ();
- err |= test_dpfs_ds128_auto ();
- err |= test_dpfs_ds128_guided32 ();
- err |= test_dpfs_ds128_runtime ();
- }
+ err |= test_d_normal ();
+ err |= test_d_ds128_normal ();
+ err |= test_ds_normal ();
+ err |= test_ds_ds128_normal ();
+ err |= test_dpf_static ();
+ err |= test_dpf_static32 ();
+ err |= test_dpf_auto ();
+ err |= test_dpf_guided32 ();
+ err |= test_dpf_runtime ();
+ err |= test_dpf_ds128_static ();
+ err |= test_dpf_ds128_static32 ();
+ err |= test_dpf_ds128_auto ();
+ err |= test_dpf_ds128_guided32 ();
+ err |= test_dpf_ds128_runtime ();
+ err |= test_dpfs_static ();
+ err |= test_dpfs_static32 ();
+ err |= test_dpfs_auto ();
+ err |= test_dpfs_guided32 ();
+ err |= test_dpfs_runtime ();
+ err |= test_dpfs_ds128_static ();
+ err |= test_dpfs_ds128_static32 ();
+ err |= test_dpfs_ds128_auto ();
+ err |= test_dpfs_ds128_guided32 ();
+ err |= test_dpfs_ds128_runtime ();
if (err)
abort ();
return 0;
--- /dev/null
+/* PR libgomp/100573 */
+
+int
+foo (int a)
+{
+ if (a == 0)
+ {
+ int c;
+ a++;
+ #pragma omp target map(tofrom:a)
+ a = foo (a);
+ #pragma omp target data map(tofrom:a)
+ c = a != 2;
+ if (c)
+ return -1;
+ #pragma omp target enter data map(to:a)
+ #pragma omp target exit data map(from:a)
+ }
+ return a + 1;
+}
+
+int
+main ()
+{
+ if (foo (0) != 3)
+ __builtin_abort ();
+ return 0;
+}
--- /dev/null
+/* PR libgomp/100573 */
+
+int
+foo (int a)
+{
+ #pragma omp target firstprivate(a)
+ if (a == 0)
+ {
+ a++;
+ #pragma omp target map(tofrom:a) /* { dg-warning "'target' construct inside of 'target' region" } */
+ a = foo (a);
+ #pragma omp target data map(tofrom:a) /* { dg-warning "'target data' construct inside of 'target' region" } */
+ a++;
+ #pragma omp target enter data map(to:a) /* { dg-warning "'target enter data' construct inside of 'target' region" } */
+ #pragma omp target exit data map(from:a) /* { dg-warning "'target exit data' construct inside of 'target' region" } */
+ }
+ return a + 1;
+}
+
+int
+main ()
+{
+ if (foo (1) != 2)
+ __builtin_abort ();
+ return 0;
+}