Example #1
0
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);
}
Example #2
0
/* 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);
    }
Example #3
0
/**
 * \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);
}
Example #4
0
/* 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;
      }
   }
}