static void worklist_push(struct exec_list *worklist, nir_instr *instr) { worklist_elem *elem = ralloc(worklist, worklist_elem); elem->instr = instr; instr->pass_flags = 1; exec_list_push_tail(worklist, &elem->node); }
/* clone list of nir_variable: */ static void clone_var_list(clone_state *state, struct exec_list *dst, const struct exec_list *list) { exec_list_make_empty(dst); foreach_list_typed(nir_variable, var, node, list) { nir_variable *nvar = clone_variable(state, var); exec_list_push_tail(dst, &nvar->node); }
/** * \brief Set that the miptree slice at (level, layer) needs a resolve. * * If a map element already exists with the given key, then the value is * changed to the given value of \c need. */ void intel_resolve_map_set(struct exec_list *resolve_map, uint32_t level, uint32_t layer, unsigned need) { foreach_list_typed(struct intel_resolve_map, map, link, resolve_map) { if (map->level == level && map->layer == layer) { map->need = need; return; } } struct intel_resolve_map *m = malloc(sizeof(struct intel_resolve_map)); exec_node_init(&m->link); m->level = level; m->layer = layer; m->need = need; exec_list_push_tail(resolve_map, &m->link); }
/* Gets the deref_node for the given deref chain and creates it if it * doesn't yet exist. If the deref is fully-qualified and direct and * state->add_to_direct_deref_nodes is true, it will be added to the hash * table of of fully-qualified direct derefs. */ static struct deref_node * get_deref_node(nir_deref_var *deref, struct lower_variables_state *state) { bool is_direct = true; /* Start at the base of the chain. */ struct deref_node *node = get_deref_node_for_var(deref->var, state); assert(deref->deref.type == node->type); for (nir_deref *tail = deref->deref.child; tail; tail = tail->child) { switch (tail->deref_type) { case nir_deref_type_struct: { nir_deref_struct *deref_struct = nir_deref_as_struct(tail); assert(deref_struct->index < glsl_get_length(node->type)); if (node->children[deref_struct->index] == NULL) node->children[deref_struct->index] = deref_node_create(node, tail->type, state->dead_ctx); node = node->children[deref_struct->index]; break; } case nir_deref_type_array: { nir_deref_array *arr = nir_deref_as_array(tail); switch (arr->deref_array_type) { case nir_deref_array_type_direct: /* This is possible if a loop unrolls and generates an * out-of-bounds offset. We need to handle this at least * somewhat gracefully. */ if (arr->base_offset >= glsl_get_length(node->type)) return NULL; if (node->children[arr->base_offset] == NULL) node->children[arr->base_offset] = deref_node_create(node, tail->type, state->dead_ctx); node = node->children[arr->base_offset]; break; case nir_deref_array_type_indirect: if (node->indirect == NULL) node->indirect = deref_node_create(node, tail->type, state->dead_ctx); node = node->indirect; is_direct = false; break; case nir_deref_array_type_wildcard: if (node->wildcard == NULL) node->wildcard = deref_node_create(node, tail->type, state->dead_ctx); node = node->wildcard; is_direct = false; break; default: unreachable("Invalid array deref type"); } break; } default: unreachable("Invalid deref type"); } } assert(node); /* Only insert if it isn't already in the list. */ if (is_direct && state->add_to_direct_deref_nodes && node->direct_derefs_link.next == NULL) { node->deref = deref; assert(deref->var != NULL); exec_list_push_tail(&state->direct_deref_nodes, &node->direct_derefs_link); } return node; }
static void emit_indirect_load_store(nir_builder *b, nir_intrinsic_instr *orig_instr, nir_deref_var *deref, nir_deref *arr_parent, int start, int end, nir_ssa_def **dest, nir_ssa_def *src) { assert(arr_parent->child && arr_parent->child->deref_type == nir_deref_type_array); nir_deref_array *arr = nir_deref_as_array(arr_parent->child); assert(arr->deref_array_type == nir_deref_array_type_indirect); assert(arr->indirect.is_ssa); assert(start < end); if (start == end - 1) { /* Base case. Just emit the load/store op */ nir_deref_array direct = *arr; direct.deref_array_type = nir_deref_array_type_direct; direct.base_offset += start; direct.indirect = NIR_SRC_INIT; arr_parent->child = &direct.deref; emit_load_store(b, orig_instr, deref, &arr->deref, dest, src); arr_parent->child = &arr->deref; } else { int mid = start + (end - start) / 2; nir_ssa_def *then_dest, *else_dest; nir_if *if_stmt = nir_if_create(b->shader); if_stmt->condition = nir_src_for_ssa(nir_ilt(b, arr->indirect.ssa, nir_imm_int(b, mid))); nir_cf_node_insert(b->cursor, &if_stmt->cf_node); b->cursor = nir_after_cf_list(&if_stmt->then_list); emit_indirect_load_store(b, orig_instr, deref, arr_parent, start, mid, &then_dest, src); b->cursor = nir_after_cf_list(&if_stmt->else_list); emit_indirect_load_store(b, orig_instr, deref, arr_parent, mid, end, &else_dest, src); b->cursor = nir_after_cf_node(&if_stmt->cf_node); if (src == NULL) { /* We're a load. We need to insert a phi node */ nir_phi_instr *phi = nir_phi_instr_create(b->shader); unsigned bit_size = then_dest->bit_size; nir_ssa_dest_init(&phi->instr, &phi->dest, then_dest->num_components, bit_size, NULL); nir_phi_src *src0 = ralloc(phi, nir_phi_src); src0->pred = nir_cf_node_as_block(nir_if_last_then_node(if_stmt)); src0->src = nir_src_for_ssa(then_dest); exec_list_push_tail(&phi->srcs, &src0->node); nir_phi_src *src1 = ralloc(phi, nir_phi_src); src1->pred = nir_cf_node_as_block(nir_if_last_else_node(if_stmt)); src1->src = nir_src_for_ssa(else_dest); exec_list_push_tail(&phi->srcs, &src1->node); nir_builder_instr_insert(b, &phi->instr); *dest = &phi->dest.ssa; } } }