static void omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl) { splay_tree_node n = splay_tree_lookup (omp_ctx->variables, (splay_tree_key) decl); if (n == NULL) { int flags = OMP_CLAUSE_DEFAULT_SHARED; if (omp_ctx->outer) omp_cxx_notice_variable (omp_ctx->outer, decl); if (!omp_ctx->default_shared) { struct cp_genericize_omp_taskreg *octx; for (octx = omp_ctx->outer; octx; octx = octx->outer) { n = splay_tree_lookup (octx->variables, (splay_tree_key) decl); if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED) { flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; break; } if (octx->is_parallel) break; } if (octx == NULL && (TREE_CODE (decl) == PARM_DECL || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl)) && DECL_CONTEXT (decl) == current_function_decl))) flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE) { /* DECL is implicitly determined firstprivate in the current task construct. Ensure copy ctor and dtor are instantiated, because during gimplification it will be already too late. */ tree type = TREE_TYPE (decl); if (is_invisiref_parm (decl)) type = TREE_TYPE (type); while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); get_copy_ctor (type, tf_none); get_dtor (type, tf_none); } } splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags); } }
static void interval_tree_intersection_1(interval_tree tree, uint64_t start, uint64_t end, varray * dest) { interval_tree_node node; node = splay_tree_lookup(tree->splay, start); if (!node) { node = splay_tree_predecessor(tree->splay, start); if (!node || INTERVAL_END(node) <= start) node = splay_tree_successor(tree->splay, start); } if (!node) node = splay_tree_successor(tree->splay, start); for (; node && INTERVAL_START(node) < end; node = splay_tree_successor(tree->splay, INTERVAL_START(node))) { interval *x; VARRAY_EMPTY_PUSH(*dest); x = &VARRAY_TOP(*dest, interval); x->start = MAX(start, INTERVAL_START(node)); x->end = MIN(end, INTERVAL_END(node)); } }
void queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags) { unsigned int index; splay_tree_node n; /* If there's no node, just return. This makes for fewer checks in our callers. */ if (!t) return; /* See if we've already queued or dumped this node. */ n = splay_tree_lookup (di->nodes, (splay_tree_key) t); if (n) index = ((dump_node_info_p) n->value)->index; else /* If we haven't, add it to the queue. */ index = queue (di, t, flags); /* Print the index of the node. */ dump_maybe_newline (di); fprintf (di->stream, "%-4s: ", field); di->column += 6; dump_index (di, index); }
gfc_constructor * gfc_constructor_lookup (gfc_constructor_base base, int offset) { gfc_constructor *c; splay_tree_node node; if (!base) return NULL; node = splay_tree_lookup (base, (splay_tree_key) offset); if (node) return (gfc_constructor *) node->value; /* Check if the previous node has a repeat count big enough to cover the offset looked for. */ node = splay_tree_predecessor (base, (splay_tree_key) offset); if (!node) return NULL; c = (gfc_constructor *) node->value; if (mpz_cmp_si (c->repeat, 1) > 0) { if (mpz_get_si (c->offset) + mpz_get_si (c->repeat) <= offset) c = NULL; } else c = NULL; return c; }
/* Lookup the tree node for the static variable that has UID. */ static tree get_static_decl (int index) { splay_tree_node stn = splay_tree_lookup (reference_vars_to_consider, index); if (stn) return (tree)stn->value; return NULL; }
static const char * get_static_name (int index) { splay_tree_node stn = splay_tree_lookup (reference_vars_to_consider, index); if (stn) return lang_hooks.decl_printable_name ((tree)(stn->value), 2); return NULL; }
/* Find the splay tree node for the definition of NAME at LINE in SOURCE, or zero if there is none. */ static splay_tree_node find_definition (const char *name, struct macro_source_file *file, int line) { struct macro_table *t = file->table; splay_tree_node n; /* Construct a macro_key object, just for the query. */ struct macro_key query; query.name = name; query.start_file = file; query.start_line = line; query.end_file = NULL; n = splay_tree_lookup (t->definitions, (splay_tree_key) &query); if (! n) { /* It's okay for us to do two queries like this: the real work of the searching is done when we splay, and splaying the tree a second time at the same key is a constant time operation. If this still bugs you, you could always just extend the splay tree library with a predecessor-or-equal operation, and use that. */ splay_tree_node pred = splay_tree_predecessor (t->definitions, (splay_tree_key) &query); if (pred) { /* Make sure this predecessor actually has the right name. We just want to search within a given name's definitions. */ struct macro_key *found = (struct macro_key *) pred->key; if (strcmp (found->name, name) == 0) n = pred; } } if (n) { struct macro_key *found = (struct macro_key *) n->key; /* Okay, so this definition has the right name, and its scope begins before the given source location. But does its scope end after the given source location? */ if (compare_locations (file, line, found->end_file, found->end_line) < 0) return n; else return 0; } else return 0; }
static splay_tree_key lookup_host (struct gomp_device_descr *dev, void *h, size_t s) { struct splay_tree_key_s node; splay_tree_key key; node.host_start = (uintptr_t) h; node.host_end = (uintptr_t) h + s; key = splay_tree_lookup (&dev->mem_map, &node); return key; }
bool interval_tree_covered(interval_tree tree, uint64_t start, uint64_t end) { interval_tree_node node; node = splay_tree_lookup(tree->splay, start); if (!node) { node = splay_tree_predecessor(tree->splay, start); if (!node) return false; } return (end <= INTERVAL_END(node)); }
static struct dcache_block * dcache_hit (DCACHE *dcache, CORE_ADDR addr) { struct dcache_block *db; splay_tree_node node = splay_tree_lookup (dcache->tree, (splay_tree_key) MASK (addr)); if (!node) return NULL; db = (struct dcache_block *) node->value; db->refs++; return db; }
static gfc_constructor * find_con_by_offset (splay_tree spt, mpz_t offset) { mpz_t tmp; gfc_constructor *ret = NULL; gfc_constructor *con; splay_tree_node sptn; /* The complexity is due to needing quick access to the linked list of constructors. Both a linked list and a splay tree are used, and both are kept up to date if they are array elements (which is the only time that a specific constructor has to be found). */ gcc_assert (spt != NULL); mpz_init (tmp); sptn = splay_tree_lookup (spt, (splay_tree_key) mpz_get_si (offset)); if (sptn) ret = (gfc_constructor*) sptn->value; else { /* Need to check and see if we match a range, so we will pull the next lowest index and see if the range matches. */ sptn = splay_tree_predecessor (spt, (splay_tree_key) mpz_get_si (offset)); if (sptn) { con = (gfc_constructor*) sptn->value; if (mpz_cmp_ui (con->repeat, 1) > 0) { mpz_init (tmp); mpz_add (tmp, con->n.offset, con->repeat); if (mpz_cmp (offset, tmp) < 0) ret = con; mpz_clear (tmp); } else ret = NULL; /* The range did not match. */ } else ret = NULL; /* No pred, so no match. */ } return ret; }
static void interval_tree_complement_1(interval_tree tree, uint64_t start, uint64_t end, varray * dest) { interval_tree_node node; uint64_t last; node = splay_tree_lookup(tree->splay, start); if (node) { last = INTERVAL_END(node); } else { node = splay_tree_predecessor(tree->splay, start); if (node && INTERVAL_END(node) > start) last = INTERVAL_END(node); else last = start; } node = splay_tree_successor(tree->splay, start); while (last < end) { interval *x; VARRAY_EMPTY_PUSH(*dest); x = &VARRAY_TOP(*dest, interval); x->start = last; if (node) { x->end = INTERVAL_START(node); last = INTERVAL_END(node); node = splay_tree_successor(tree->splay, INTERVAL_START(node)); } else { x->end = end; break; } } }
interval_tree_node interval_tree_lookup(interval_tree tree, uint64_t value) { interval_tree_node node; CHECK_MUTEX_LOCKED(tree->mutex); /* Return the interval starting with VALUE if it exist. */ node = splay_tree_lookup(tree->splay, value); if (node) return node; /* Return the interval containing VALUE if it exist. */ node = splay_tree_predecessor(tree->splay, value); if (node && INTERVAL_END(node) > value) return node; /* Return the first interval after VALUE. */ return splay_tree_successor(tree->splay, value); }
struct c_fileinfo * get_fileinfo (const char *name) { splay_tree_node n; struct c_fileinfo *fi; if (!file_info_tree) file_info_tree = splay_tree_new ((splay_tree_compare_fn) strcmp, 0, (splay_tree_delete_value_fn) free); n = splay_tree_lookup (file_info_tree, (splay_tree_key) name); if (n) return (struct c_fileinfo *) n->value; fi = XNEW (struct c_fileinfo); fi->time = 0; fi->interface_only = 0; fi->interface_unknown = 1; splay_tree_insert (file_info_tree, (splay_tree_key) name, (splay_tree_value) fi); return fi; }
/* Type-correct wrappers for splay tree access. */ static splay_tree_node addrmap_splay_tree_lookup (struct addrmap_mutable *map, CORE_ADDR addr) { return splay_tree_lookup (map->tree, (splay_tree_key) &addr); }
void GOACC_parallel_keyed (int device, void (*fn) (void *), size_t mapnum, void **hostaddrs, size_t *sizes, unsigned short *kinds, ...) { bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK; va_list ap; struct goacc_thread *thr; struct gomp_device_descr *acc_dev; struct target_mem_desc *tgt; void **devaddrs; unsigned int i; struct splay_tree_key_s k; splay_tree_key tgt_fn_key; void (*tgt_fn); int async = GOMP_ASYNC_SYNC; unsigned dims[GOMP_DIM_MAX]; unsigned tag; #ifdef HAVE_INTTYPES_H gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n", __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds); #else gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n", __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds); #endif goacc_lazy_initialize (); thr = goacc_thread (); acc_dev = thr->dev; /* Host fallback if "if" clause is false or if the current device is set to the host. */ if (host_fallback) { goacc_save_and_set_bind (acc_device_host); fn (hostaddrs); goacc_restore_bind (); return; } else if (acc_device_type (acc_dev->type) == acc_device_host) { fn (hostaddrs); return; } va_start (ap, kinds); /* TODO: This will need amending when device_type is implemented. */ while ((tag = va_arg (ap, unsigned)) != 0) { if (GOMP_LAUNCH_DEVICE (tag)) gomp_fatal ("device_type '%d' offload parameters, libgomp is too old", GOMP_LAUNCH_DEVICE (tag)); switch (GOMP_LAUNCH_CODE (tag)) { case GOMP_LAUNCH_DIM: { unsigned mask = GOMP_LAUNCH_OP (tag); for (i = 0; i != GOMP_DIM_MAX; i++) if (mask & GOMP_DIM_MASK (i)) dims[i] = va_arg (ap, unsigned); } break; case GOMP_LAUNCH_ASYNC: { /* Small constant values are encoded in the operand. */ async = GOMP_LAUNCH_OP (tag); if (async == GOMP_LAUNCH_OP_MAX) async = va_arg (ap, unsigned); break; } case GOMP_LAUNCH_WAIT: { unsigned num_waits = GOMP_LAUNCH_OP (tag); if (num_waits) goacc_wait (async, num_waits, &ap); break; } default: gomp_fatal ("unrecognized offload code '%d'," " libgomp is too old", GOMP_LAUNCH_CODE (tag)); } } va_end (ap); acc_dev->openacc.async_set_async_func (async); if (!(acc_dev->capabilities & GOMP_OFFLOAD_CAP_NATIVE_EXEC)) { k.host_start = (uintptr_t) fn; k.host_end = k.host_start + 1; gomp_mutex_lock (&acc_dev->lock); tgt_fn_key = splay_tree_lookup (&acc_dev->mem_map, &k); gomp_mutex_unlock (&acc_dev->lock); if (tgt_fn_key == NULL) gomp_fatal ("target function wasn't mapped"); tgt_fn = (void (*)) tgt_fn_key->tgt_offset; } else tgt_fn = (void (*)) fn; tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true, GOMP_MAP_VARS_OPENACC); devaddrs = gomp_alloca (sizeof (void *) * mapnum); for (i = 0; i < mapnum; i++) devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start + tgt->list[i].key->tgt_offset); acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs, async, dims, tgt); /* If running synchronously, unmap immediately. */ if (async < acc_async_noval) gomp_unmap_vars (tgt, true); else { gomp_copy_from_async (tgt); acc_dev->openacc.register_async_cleanup_func (tgt); } acc_dev->openacc.async_set_async_func (acc_async_sync); }
bool gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index, mpz_t *repeat) { gfc_ref *ref; gfc_expr *init; gfc_expr *expr = NULL; gfc_constructor *con; gfc_constructor *last_con; gfc_symbol *symbol; gfc_typespec *last_ts; mpz_t offset; symbol = lvalue->symtree->n.sym; init = symbol->value; last_ts = &symbol->ts; last_con = NULL; mpz_init_set_si (offset, 0); /* Find/create the parent expressions for subobject references. */ for (ref = lvalue->ref; ref; ref = ref->next) { /* Break out of the loop if we find a substring. */ if (ref->type == REF_SUBSTRING) { /* A substring should always be the last subobject reference. */ gcc_assert (ref->next == NULL); break; } /* Use the existing initializer expression if it exists. Otherwise create a new one. */ if (init == NULL) expr = gfc_get_expr (); else expr = init; /* Find or create this element. */ switch (ref->type) { case REF_ARRAY: if (ref->u.ar.as->rank == 0) { gcc_assert (ref->u.ar.as->corank > 0); if (init == NULL) free (expr); continue; } if (init && expr->expr_type != EXPR_ARRAY) { gfc_error ("%qs at %L already is initialized at %L", lvalue->symtree->n.sym->name, &lvalue->where, &init->where); goto abort; } if (init == NULL) { /* The element typespec will be the same as the array typespec. */ expr->ts = *last_ts; /* Setup the expression to hold the constructor. */ expr->expr_type = EXPR_ARRAY; expr->rank = ref->u.ar.as->rank; } if (ref->u.ar.type == AR_ELEMENT) get_array_index (&ref->u.ar, &offset); else mpz_set (offset, index); /* Check the bounds. */ if (mpz_cmp_si (offset, 0) < 0) { gfc_error ("Data element below array lower bound at %L", &lvalue->where); goto abort; } else if (repeat != NULL && ref->u.ar.type != AR_ELEMENT) { mpz_t size, end; gcc_assert (ref->u.ar.type == AR_FULL && ref->next == NULL); mpz_init_set (end, offset); mpz_add (end, end, *repeat); if (spec_size (ref->u.ar.as, &size)) { if (mpz_cmp (end, size) > 0) { mpz_clear (size); gfc_error ("Data element above array upper bound at %L", &lvalue->where); goto abort; } mpz_clear (size); } con = gfc_constructor_lookup (expr->value.constructor, mpz_get_si (offset)); if (!con) { con = gfc_constructor_lookup_next (expr->value.constructor, mpz_get_si (offset)); if (con != NULL && mpz_cmp (con->offset, end) >= 0) con = NULL; } /* Overwriting an existing initializer is non-standard but usually only provokes a warning from other compilers. */ if (con != NULL && con->expr != NULL) { /* Order in which the expressions arrive here depends on whether they are from data statements or F95 style declarations. Therefore, check which is the most recent. */ gfc_expr *exprd; exprd = (LOCATION_LINE (con->expr->where.lb->location) > LOCATION_LINE (rvalue->where.lb->location)) ? con->expr : rvalue; if (gfc_notify_std (GFC_STD_GNU, "re-initialization of %qs at %L", symbol->name, &exprd->where) == false) return false; } while (con != NULL) { gfc_constructor *next_con = gfc_constructor_next (con); if (mpz_cmp (con->offset, end) >= 0) break; if (mpz_cmp (con->offset, offset) < 0) { gcc_assert (mpz_cmp_si (con->repeat, 1) > 0); mpz_sub (con->repeat, offset, con->offset); } else if (mpz_cmp_si (con->repeat, 1) > 0 && mpz_get_si (con->offset) + mpz_get_si (con->repeat) > mpz_get_si (end)) { int endi; splay_tree_node node = splay_tree_lookup (con->base, mpz_get_si (con->offset)); gcc_assert (node && con == (gfc_constructor *) node->value && node->key == (splay_tree_key) mpz_get_si (con->offset)); endi = mpz_get_si (con->offset) + mpz_get_si (con->repeat); if (endi > mpz_get_si (end) + 1) mpz_set_si (con->repeat, endi - mpz_get_si (end)); else mpz_set_si (con->repeat, 1); mpz_set (con->offset, end); node->key = (splay_tree_key) mpz_get_si (end); break; } else gfc_constructor_remove (con); con = next_con; } con = gfc_constructor_insert_expr (&expr->value.constructor, NULL, &rvalue->where, mpz_get_si (offset)); mpz_set (con->repeat, *repeat); repeat = NULL; mpz_clear (end); break; } else { mpz_t size; if (spec_size (ref->u.ar.as, &size)) { if (mpz_cmp (offset, size) >= 0) { mpz_clear (size); gfc_error ("Data element above array upper bound at %L", &lvalue->where); goto abort; } mpz_clear (size); } } con = gfc_constructor_lookup (expr->value.constructor, mpz_get_si (offset)); if (!con) { con = gfc_constructor_insert_expr (&expr->value.constructor, NULL, &rvalue->where, mpz_get_si (offset)); } else if (mpz_cmp_si (con->repeat, 1) > 0) { /* Need to split a range. */ if (mpz_cmp (con->offset, offset) < 0) { gfc_constructor *pred_con = con; con = gfc_constructor_insert_expr (&expr->value.constructor, NULL, &con->where, mpz_get_si (offset)); con->expr = gfc_copy_expr (pred_con->expr); mpz_add (con->repeat, pred_con->offset, pred_con->repeat); mpz_sub (con->repeat, con->repeat, offset); mpz_sub (pred_con->repeat, offset, pred_con->offset); } if (mpz_cmp_si (con->repeat, 1) > 0) { gfc_constructor *succ_con; succ_con = gfc_constructor_insert_expr (&expr->value.constructor, NULL, &con->where, mpz_get_si (offset) + 1); succ_con->expr = gfc_copy_expr (con->expr); mpz_sub_ui (succ_con->repeat, con->repeat, 1); mpz_set_si (con->repeat, 1); } } break; case REF_COMPONENT: if (init == NULL) { /* Setup the expression to hold the constructor. */ expr->expr_type = EXPR_STRUCTURE; expr->ts.type = BT_DERIVED; expr->ts.u.derived = ref->u.c.sym; } else gcc_assert (expr->expr_type == EXPR_STRUCTURE); last_ts = &ref->u.c.component->ts; /* Find the same element in the existing constructor. */ con = find_con_by_component (ref->u.c.component, expr->value.constructor); if (con == NULL) { /* Create a new constructor. */ con = gfc_constructor_append_expr (&expr->value.constructor, NULL, NULL); con->n.component = ref->u.c.component; } break; default: gcc_unreachable (); } if (init == NULL) { /* Point the container at the new expression. */ if (last_con == NULL) symbol->value = expr; else last_con->expr = expr; } init = con->expr; last_con = con; } mpz_clear (offset); gcc_assert (repeat == NULL); if (ref || last_ts->type == BT_CHARACTER) { if (lvalue->ts.u.cl->length == NULL && !(ref && ref->u.ss.length != NULL)) return false; expr = create_character_initializer (init, last_ts, ref, rvalue); } else { /* Overwriting an existing initializer is non-standard but usually only provokes a warning from other compilers. */ if (init != NULL) { /* Order in which the expressions arrive here depends on whether they are from data statements or F95 style declarations. Therefore, check which is the most recent. */ expr = (LOCATION_LINE (init->where.lb->location) > LOCATION_LINE (rvalue->where.lb->location)) ? init : rvalue; if (gfc_notify_std (GFC_STD_GNU, "re-initialization of %qs at %L", symbol->name, &expr->where) == false) return false; } expr = gfc_copy_expr (rvalue); if (!gfc_compare_types (&lvalue->ts, &expr->ts)) gfc_convert_type (expr, &lvalue->ts, 0); } if (last_con == NULL) symbol->value = expr; else last_con->expr = expr; return true; abort: if (!init) gfc_free_expr (expr); mpz_clear (offset); return false; }
void interval_tree_delete(interval_tree tree, uint64_t start, uint64_t end) { splay_tree_node node, prev, next; CHECK_MUTEX_LOCKED(tree->mutex); if ((node = splay_tree_lookup(tree->splay, start)) != NULL) { tree->deleted = true; if (INTERVAL_END(node) > end) { /* We are shortening the interval NODE. */ INTERVAL_START(node) = end; return; } else { splay_tree_delete(tree->splay, start); tree->size--; } } else { prev = splay_tree_predecessor(tree->splay, start); if (prev && start < INTERVAL_END(prev)) { tree->deleted = true; if (INTERVAL_END(prev) > end) { /* We are cutting a subinterval from interval PREV. */ splay_tree_insert(tree->splay, end, INTERVAL_END(prev)); tree->size++; INTERVAL_END(prev) = start; return; } else { /* We are shortening the interval PREV. */ INTERVAL_END(prev) = start; } } } /* Delete rest intervals which intersect [START, END). */ while (1) { next = splay_tree_successor(tree->splay, start); if (!next || INTERVAL_START(next) >= end) break; tree->deleted = true; if (INTERVAL_END(next) <= end) { splay_tree_delete(tree->splay, INTERVAL_START(next)); tree->size--; } else { INTERVAL_START(next) = end; return; } } }
interval_tree_node interval_tree_insert(interval_tree tree, uint64_t start, uint64_t end) { splay_tree_node node, prev, next; CHECK_MUTEX_LOCKED(tree->mutex); if ((node = splay_tree_lookup(tree->splay, start)) != NULL) { /* The START of interval is already in the tree. */ if (INTERVAL_END(node) >= end) { /* There already is a larger interval starting in START so we have nothing to do. */ return node; } INTERVAL_END(node) = end; } else { /* Lookup the predecessor and successor of key START. */ prev = splay_tree_predecessor(tree->splay, start); next = splay_tree_successor(tree->splay, start); if (prev && INTERVAL_END(prev) >= start) { /* We are extending PREV. */ node = prev; if (INTERVAL_END(node) < end) INTERVAL_END(node) = end; } else if (next && INTERVAL_START(next) <= end) { /* We are extending NEXT. */ node = next; if (INTERVAL_START(node) > start) INTERVAL_START(node) = start; if (INTERVAL_END(node) < end) INTERVAL_END(node) = end; } else { /* We are really inserting a new node. */ node = splay_tree_insert(tree->splay, start, end); tree->size++; } } /* Merge the successors if they are covered by [START, END). */ while ((next = splay_tree_successor(tree->splay, INTERVAL_START(node))) != NULL) { if (INTERVAL_START(next) <= INTERVAL_END(node)) { if (INTERVAL_END(node) < INTERVAL_END(next)) INTERVAL_END(node) = INTERVAL_END(next); splay_tree_delete(tree->splay, INTERVAL_START(next)); tree->size--; } else break; } return node; }
void GOACC_parallel (int device, void (*fn) (void *), const void *offload_table, size_t mapnum, void **hostaddrs, size_t *sizes, unsigned short *kinds, int num_gangs, int num_workers, int vector_length, int async, int num_waits, ...) { bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK; va_list ap; struct goacc_thread *thr; struct gomp_device_descr *acc_dev; struct target_mem_desc *tgt; void **devaddrs; unsigned int i; struct splay_tree_key_s k; splay_tree_key tgt_fn_key; void (*tgt_fn); if (num_gangs != 1) gomp_fatal ("num_gangs (%d) different from one is not yet supported", num_gangs); if (num_workers != 1) gomp_fatal ("num_workers (%d) different from one is not yet supported", num_workers); gomp_debug (0, "%s: mapnum=%zd, hostaddrs=%p, sizes=%p, kinds=%p, async=%d\n", __FUNCTION__, mapnum, hostaddrs, sizes, kinds, async); select_acc_device (device); thr = goacc_thread (); acc_dev = thr->dev; /* Host fallback if "if" clause is false or if the current device is set to the host. */ if (host_fallback) { goacc_save_and_set_bind (acc_device_host); fn (hostaddrs); goacc_restore_bind (); return; } else if (acc_device_type (acc_dev->type) == acc_device_host) { fn (hostaddrs); return; } va_start (ap, num_waits); if (num_waits > 0) goacc_wait (async, num_waits, ap); va_end (ap); acc_dev->openacc.async_set_async_func (async); if (!(acc_dev->capabilities & GOMP_OFFLOAD_CAP_NATIVE_EXEC)) { k.host_start = (uintptr_t) fn; k.host_end = k.host_start + 1; gomp_mutex_lock (&acc_dev->mem_map.lock); tgt_fn_key = splay_tree_lookup (&acc_dev->mem_map.splay_tree, &k); gomp_mutex_unlock (&acc_dev->mem_map.lock); if (tgt_fn_key == NULL) gomp_fatal ("target function wasn't mapped"); tgt_fn = (void (*)) tgt_fn_key->tgt->tgt_start; } else tgt_fn = (void (*)) fn; tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true, false); devaddrs = alloca (sizeof (void *) * mapnum); for (i = 0; i < mapnum; i++) devaddrs[i] = (void *) (tgt->list[i]->tgt->tgt_start + tgt->list[i]->tgt_offset); acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs, sizes, kinds, num_gangs, num_workers, vector_length, async, tgt); /* If running synchronously, unmap immediately. */ if (async < acc_async_noval) gomp_unmap_vars (tgt, true); else { gomp_copy_from_async (tgt); acc_dev->openacc.register_async_cleanup_func (tgt); } acc_dev->openacc.async_set_async_func (acc_async_sync); }
static tree cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) { tree stmt = *stmt_p; struct cp_genericize_data *wtd = (struct cp_genericize_data *) data; struct pointer_set_t *p_set = wtd->p_set; /* If in an OpenMP context, note var uses. */ if (__builtin_expect (wtd->omp_ctx != NULL, 0) && (VAR_P (stmt) || TREE_CODE (stmt) == PARM_DECL || TREE_CODE (stmt) == RESULT_DECL) && omp_var_to_track (stmt)) omp_cxx_notice_variable (wtd->omp_ctx, stmt); if (is_invisiref_parm (stmt) /* Don't dereference parms in a thunk, pass the references through. */ && !(DECL_THUNK_P (current_function_decl) && TREE_CODE (stmt) == PARM_DECL)) { *stmt_p = convert_from_reference (stmt); *walk_subtrees = 0; return NULL; } /* Map block scope extern declarations to visible declarations with the same name and type in outer scopes if any. */ if (cp_function_chain->extern_decl_map && VAR_OR_FUNCTION_DECL_P (stmt) && DECL_EXTERNAL (stmt)) { struct cxx_int_tree_map *h, in; in.uid = DECL_UID (stmt); h = (struct cxx_int_tree_map *) htab_find_with_hash (cp_function_chain->extern_decl_map, &in, in.uid); if (h) { *stmt_p = h->to; *walk_subtrees = 0; return NULL; } } /* Other than invisiref parms, don't walk the same tree twice. */ if (pointer_set_contains (p_set, stmt)) { *walk_subtrees = 0; return NULL_TREE; } if (TREE_CODE (stmt) == ADDR_EXPR && is_invisiref_parm (TREE_OPERAND (stmt, 0))) { /* If in an OpenMP context, note var uses. */ if (__builtin_expect (wtd->omp_ctx != NULL, 0) && omp_var_to_track (TREE_OPERAND (stmt, 0))) omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0)); *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); *walk_subtrees = 0; } else if (TREE_CODE (stmt) == RETURN_EXPR && TREE_OPERAND (stmt, 0) && is_invisiref_parm (TREE_OPERAND (stmt, 0))) /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ *walk_subtrees = 0; else if (TREE_CODE (stmt) == OMP_CLAUSE) switch (OMP_CLAUSE_CODE (stmt)) { case OMP_CLAUSE_LASTPRIVATE: /* Don't dereference an invisiref in OpenMP clauses. */ if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) { *walk_subtrees = 0; if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt)) cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt), cp_genericize_r, data, NULL); } break; case OMP_CLAUSE_PRIVATE: /* Don't dereference an invisiref in OpenMP clauses. */ if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) *walk_subtrees = 0; else if (wtd->omp_ctx != NULL) { /* Private clause doesn't cause any references to the var in outer contexts, avoid calling omp_cxx_notice_variable for it. */ struct cp_genericize_omp_taskreg *old = wtd->omp_ctx; wtd->omp_ctx = NULL; cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r, data, NULL); wtd->omp_ctx = old; *walk_subtrees = 0; } break; case OMP_CLAUSE_SHARED: case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_COPYIN: case OMP_CLAUSE_COPYPRIVATE: /* Don't dereference an invisiref in OpenMP clauses. */ if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) *walk_subtrees = 0; break; case OMP_CLAUSE_REDUCTION: /* Don't dereference an invisiref in reduction clause's OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE} still needs to be genericized. */ if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) { *walk_subtrees = 0; if (OMP_CLAUSE_REDUCTION_INIT (stmt)) cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt), cp_genericize_r, data, NULL); if (OMP_CLAUSE_REDUCTION_MERGE (stmt)) cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt), cp_genericize_r, data, NULL); } break; default: break; } else if (IS_TYPE_OR_DECL_P (stmt)) *walk_subtrees = 0; /* Due to the way voidify_wrapper_expr is written, we don't get a chance to lower this construct before scanning it, so we need to lower these before doing anything else. */ else if (TREE_CODE (stmt) == CLEANUP_STMT) *stmt_p = build2_loc (EXPR_LOCATION (stmt), CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR, void_type_node, CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt)); else if (TREE_CODE (stmt) == IF_STMT) { genericize_if_stmt (stmt_p); /* *stmt_p has changed, tail recurse to handle it again. */ return cp_genericize_r (stmt_p, walk_subtrees, data); } /* COND_EXPR might have incompatible types in branches if one or both arms are bitfields. Fix it up now. */ else if (TREE_CODE (stmt) == COND_EXPR) { tree type_left = (TREE_OPERAND (stmt, 1) ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1)) : NULL_TREE); tree type_right = (TREE_OPERAND (stmt, 2) ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2)) : NULL_TREE); if (type_left && !useless_type_conversion_p (TREE_TYPE (stmt), TREE_TYPE (TREE_OPERAND (stmt, 1)))) { TREE_OPERAND (stmt, 1) = fold_convert (type_left, TREE_OPERAND (stmt, 1)); gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), type_left)); } if (type_right && !useless_type_conversion_p (TREE_TYPE (stmt), TREE_TYPE (TREE_OPERAND (stmt, 2)))) { TREE_OPERAND (stmt, 2) = fold_convert (type_right, TREE_OPERAND (stmt, 2)); gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), type_right)); } } else if (TREE_CODE (stmt) == BIND_EXPR) { if (__builtin_expect (wtd->omp_ctx != NULL, 0)) { tree decl; for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl)) if (VAR_P (decl) && !DECL_EXTERNAL (decl) && omp_var_to_track (decl)) { splay_tree_node n = splay_tree_lookup (wtd->omp_ctx->variables, (splay_tree_key) decl); if (n == NULL) splay_tree_insert (wtd->omp_ctx->variables, (splay_tree_key) decl, TREE_STATIC (decl) ? OMP_CLAUSE_DEFAULT_SHARED : OMP_CLAUSE_DEFAULT_PRIVATE); } } wtd->bind_expr_stack.safe_push (stmt); cp_walk_tree (&BIND_EXPR_BODY (stmt), cp_genericize_r, data, NULL); wtd->bind_expr_stack.pop (); } else if (TREE_CODE (stmt) == USING_STMT) { tree block = NULL_TREE; /* Get the innermost inclosing GIMPLE_BIND that has a non NULL BLOCK, and append an IMPORTED_DECL to its BLOCK_VARS chained list. */ if (wtd->bind_expr_stack.exists ()) { int i; for (i = wtd->bind_expr_stack.length () - 1; i >= 0; i--) if ((block = BIND_EXPR_BLOCK (wtd->bind_expr_stack[i]))) break; } if (block) { tree using_directive; gcc_assert (TREE_OPERAND (stmt, 0)); using_directive = make_node (IMPORTED_DECL); TREE_TYPE (using_directive) = void_type_node; IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = TREE_OPERAND (stmt, 0); DECL_CHAIN (using_directive) = BLOCK_VARS (block); BLOCK_VARS (block) = using_directive; } /* The USING_STMT won't appear in GENERIC. */ *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); *walk_subtrees = 0; } else if (TREE_CODE (stmt) == DECL_EXPR && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL) { /* Using decls inside DECL_EXPRs are just dropped on the floor. */ *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); *walk_subtrees = 0; } else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK) { struct cp_genericize_omp_taskreg omp_ctx; tree c, decl; splay_tree_node n; *walk_subtrees = 0; cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL); omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL; omp_ctx.default_shared = omp_ctx.is_parallel; omp_ctx.outer = wtd->omp_ctx; omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0); wtd->omp_ctx = &omp_ctx; for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c)) switch (OMP_CLAUSE_CODE (c)) { case OMP_CLAUSE_SHARED: case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_LASTPRIVATE: decl = OMP_CLAUSE_DECL (c); if (decl == error_mark_node || !omp_var_to_track (decl)) break; n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl); if (n != NULL) break; splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl, OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED ? OMP_CLAUSE_DEFAULT_SHARED : OMP_CLAUSE_DEFAULT_PRIVATE); if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE && omp_ctx.outer) omp_cxx_notice_variable (omp_ctx.outer, decl); break; case OMP_CLAUSE_DEFAULT: if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED) omp_ctx.default_shared = true; default: break; } cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL); wtd->omp_ctx = omp_ctx.outer; splay_tree_delete (omp_ctx.variables); } else if (TREE_CODE (stmt) == CONVERT_EXPR) gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt)); else if (TREE_CODE (stmt) == FOR_STMT) genericize_for_stmt (stmt_p, walk_subtrees, data); else if (TREE_CODE (stmt) == WHILE_STMT) genericize_while_stmt (stmt_p, walk_subtrees, data); else if (TREE_CODE (stmt) == DO_STMT) genericize_do_stmt (stmt_p, walk_subtrees, data); else if (TREE_CODE (stmt) == SWITCH_STMT) genericize_switch_stmt (stmt_p, walk_subtrees, data); else if (TREE_CODE (stmt) == CONTINUE_STMT) genericize_continue_stmt (stmt_p); else if (TREE_CODE (stmt) == BREAK_STMT) genericize_break_stmt (stmt_p); else if (TREE_CODE (stmt) == OMP_FOR || TREE_CODE (stmt) == OMP_SIMD || TREE_CODE (stmt) == OMP_DISTRIBUTE) genericize_omp_for_stmt (stmt_p, walk_subtrees, data); else if (TREE_CODE (stmt) == SIZEOF_EXPR) { if (SIZEOF_EXPR_TYPE_P (stmt)) *stmt_p = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)), SIZEOF_EXPR, false); else if (TYPE_P (TREE_OPERAND (stmt, 0))) *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0), SIZEOF_EXPR, false); else *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0), SIZEOF_EXPR, false); if (*stmt_p == error_mark_node) *stmt_p = size_one_node; return NULL; } pointer_set_insert (p_set, *stmt_p); return NULL; }