예제 #1
0
/* Since there is no statement to visit between the "then" and "else"
 * instructions try to vectorize before, in between, and after them to avoid
 * combining statements from different basic blocks.
 */
ir_visitor_status
ir_vectorize_visitor::visit_enter(ir_if *ir)
{
   try_vectorize();

   visit_list_elements(this, &ir->then_instructions);
   try_vectorize();

   visit_list_elements(this, &ir->else_instructions);
   try_vectorize();

   return visit_continue_with_parent;
}
예제 #2
0
ir_visitor_status
ir_copy_propagation_visitor::visit_enter(ir_function_signature *ir)
{
   /* Treat entry into a function signature as a completely separate
    * block.  Any instructions at global scope will be shuffled into
    * main() at link time, so they're irrelevant to us.
    */
   hash_table *orig_acp = this->acp;
   exec_list *orig_kills = this->kills;
   bool orig_killed_all = this->killed_all;

   acp = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
                                 _mesa_key_pointer_equal);
   this->kills = new(mem_ctx) exec_list;
   this->killed_all = false;

   visit_list_elements(this, &ir->body);

   _mesa_hash_table_destroy(acp, NULL);
   ralloc_free(this->kills);

   this->kills = orig_kills;
   this->acp = orig_acp;
   this->killed_all = orig_killed_all;

   return visit_continue_with_parent;
}
bool do_noop_swizzle(exec_list *instructions)
{
	ir_noop_swizzle_visitor v;
	visit_list_elements(&v, instructions);

	return v.progress;
}
예제 #4
0
ir_visitor_status gp_ir_visitor::visit_enter(ir_if* ir)
{
	this->emit_inverse_cond(ir->condition);
	
	ir_dead_branches* db = this->dbv->get_dead_branches(ir);
	
	lima_gp_ir_branch_node_t* branch =
		lima_gp_ir_branch_node_create(lima_gp_ir_op_branch_cond);
	branch->condition = this->cur_nodes[0];
	lima_gp_ir_block_t** beginning_dest = &branch->dest;
	lima_gp_ir_block_insert_end(this->cur_block, &branch->root_node);
	
	lima_gp_ir_block_t* if_block = lima_gp_ir_block_create();
	lima_gp_ir_prog_insert(if_block, this->cur_block);
	this->cur_block = if_block;
	
	visit_list_elements(this, &ir->then_instructions);
	
	lima_gp_ir_block_t** then_dest = NULL;
	if (!db->then_dead && !ir->else_instructions.is_empty())
	{
		branch = lima_gp_ir_branch_node_create(lima_gp_ir_op_branch_uncond);
		then_dest = &branch->dest;
		lima_gp_ir_block_insert_end(this->cur_block, &branch->root_node);
	}
	
	if (!ir->else_instructions.is_empty())
	{
		lima_gp_ir_block_t* else_block = lima_gp_ir_block_create();
		lima_gp_ir_prog_insert(this->cur_block, else_block);
		this->cur_block = else_block;
		*beginning_dest = else_block;
		
		visit_list_elements(this, &ir->else_instructions);
	}
	
	lima_gp_ir_block_t* end_block = lima_gp_ir_block_create();
	lima_gp_ir_prog_insert(this->cur_block, end_block);
	this->cur_block = end_block;
	
	if (ir->else_instructions.is_empty())
		*beginning_dest = end_block;
	
	visit_list_elements(this, &ir->phi_nodes, false);
	
	return visit_continue_with_parent;
}
예제 #5
0
bool
do_explog_to_explog2(exec_list *instructions)
{
   ir_explog_to_explog2_visitor v;

   visit_list_elements(&v, instructions);
   return v.progress;
}
예제 #6
0
bool
lower_instructions(exec_list *instructions, unsigned what_to_lower)
{
   lower_instructions_visitor v(what_to_lower);

   visit_list_elements(&v, instructions);
   return v.progress;
}
예제 #7
0
bool
do_algebraic(exec_list *instructions)
{
   ir_algebraic_visitor v;

   visit_list_elements(&v, instructions);

   return v.progress;
}
예제 #8
0
bool
lower_clip_distance(exec_list *instructions)
{
   lower_clip_distance_visitor v;

   visit_list_elements(&v, instructions);

   return v.progress;
}
/**
 * Does a constant propagation pass on the code present in the instruction stream.
 */
bool
do_constant_propagation(exec_list *instructions)
{
   ir_constant_propagation_visitor v;

   visit_list_elements(&v, instructions);

   return v.progress;
}
bool
lower_discard(exec_list *instructions)
{
   lower_discard_visitor v;

   visit_list_elements(&v, instructions);

   return v.progress;
}
예제 #11
0
bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz)
{
	lower_vector_visitor v;

	v.dont_lower_swz = dont_lower_swz;
	visit_list_elements(&v, instructions);

	return v.progress;
}
ir_visitor_status
ir_variable_refcount_visitor::visit_enter(ir_function_signature *ir)
{
	/* We don't want to descend into the function parameters and
	* dead-code eliminate them, so just accept the body here.
	*/
	visit_list_elements(this, &ir->body);
	return visit_continue_with_parent;
}
ir_visitor_status
ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
{
   /* We don't want to descend into the function parameters and
    * consider them as shader inputs or outputs.
    */
   visit_list_elements(this, &ir->body);
   return visit_continue_with_parent;
}
void
propagate_invariance(exec_list *instructions)
{
   ir_invariance_propagation_visitor visitor;

   do {
      visitor.progress = false;
      visit_list_elements(&visitor, instructions);
   } while (visitor.progress);
}
bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth)
{
	if (max_depth == UINT_MAX)
		return false;

	ir_if_to_cond_assign_visitor v(max_depth);

	visit_list_elements(&v, instructions);

	return v.progress;
}
예제 #16
0
ir_visitor_status gp_ir_visitor::visit_enter(ir_loop* ir)
{
	_mesa_hash_table_insert(this->loop_beginning_to_block,
							_mesa_hash_pointer(ir), ir, this->cur_block);
	
	lima_gp_ir_block_t* loop_header = lima_gp_ir_block_create();
	lima_gp_ir_prog_insert(loop_header, this->cur_block);
	this->cur_block = loop_header;
	
	//we create after_loop and append it after loop_header, but we *do not* set
	//this->cur_block - any additional blocks in the loop will go in between
	//loop_header and after_loop
	lima_gp_ir_block_t* after_loop = lima_gp_ir_block_create();
	lima_gp_ir_prog_insert(after_loop, this->cur_block);
	
	lima_gp_ir_block_t* old_break_block = this->break_block;
	lima_gp_ir_block_t* old_continue_block = this->continue_block;
	
	this->break_block = after_loop;
	this->continue_block = loop_header;
	
	visit_list_elements(this, &ir->begin_phi_nodes, false);
	visit_list_elements(this, &ir->body_instructions);
	
	_mesa_hash_table_insert(this->loop_end_to_block,
							_mesa_hash_pointer(ir), ir, this->cur_block);
	
	lima_gp_ir_branch_node_t* branch =
		lima_gp_ir_branch_node_create(lima_gp_ir_op_branch_uncond);
	branch->dest = loop_header;
	lima_gp_ir_block_insert_end(this->cur_block, &branch->root_node);
	
	this->break_block = old_break_block;
	this->continue_block = old_continue_block;
	
	this->cur_block = after_loop;
	
	visit_list_elements(this, &ir->end_phi_nodes, false);
	
	return visit_continue_with_parent;
}
예제 #17
0
bool
lower_clip_distance(gl_shader *shader)
{
   lower_clip_distance_visitor v;

   visit_list_elements(&v, shader->ir);

   if (v.new_clip_distance_var)
      shader->symbols->add_variable(v.new_clip_distance_var);

   return v.progress;
}
bool do_mat_op_to_vec(exec_list *instructions)
{
	ir_mat_op_to_vec_visitor v;

	/* Pull out any matrix expression to a separate assignment to a
	* temp.  This will make our handling of the breakdown to
	* operations on the matrix's vector components much easier.
	*/
	do_expression_flattening(instructions, mat_op_to_vec_predicate);

	visit_list_elements(&v, instructions);

	return v.made_progress;
}
예제 #19
0
void
do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
                      bool is_fragment_shader)
{
   ir_set_program_inouts_visitor v(prog, is_fragment_shader);

   prog->InputsRead = 0;
   prog->OutputsWritten = 0;
   prog->SystemValuesRead = 0;
   if (is_fragment_shader) {
      memset(((gl_fragment_program *) prog)->InterpQualifier, 0,
             sizeof(((gl_fragment_program *) prog)->InterpQualifier));
   }
   visit_list_elements(&v, instructions);
}
예제 #20
0
void
lower_discard_flow(exec_list *ir)
{
   void *mem_ctx = ir;

   ir_variable *var = new(mem_ctx) ir_variable(glsl_type::bool_type,
					       "discarded",
					       ir_var_temporary);

   ir->push_head(var);

   lower_discard_flow_visitor v(var);

   visit_list_elements(&v, ir);
}
예제 #21
0
/**
 * Does a copy propagation pass on the code present in the instruction stream.
 */
bool
do_tree_grafting(exec_list *instructions)
{
   ir_variable_refcount_visitor refs;
   struct tree_grafting_info info;

   info.progress = false;
   info.refs = &refs;

   visit_list_elements(info.refs, instructions);

   call_for_basic_blocks(instructions, tree_grafting_basic_block, &info);

   return info.progress;
}
예제 #22
0
void
do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
                      GLenum shader_type)
{
   ir_set_program_inouts_visitor v(prog, shader_type);

   prog->InputsRead = 0;
   prog->OutputsWritten = 0;
   prog->SystemValuesRead = 0;
   if (shader_type == GL_FRAGMENT_SHADER) {
      gl_fragment_program *fprog = (gl_fragment_program *) prog;
      memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier));
      fprog->IsCentroid = 0;
      fprog->UsesDFdy = false;
      fprog->UsesKill = false;
   }
   visit_list_elements(&v, instructions);
}
예제 #23
0
bool
lower_tess_level(gl_linked_shader *shader)
{
   if ((shader->Stage != MESA_SHADER_TESS_CTRL) &&
       (shader->Stage != MESA_SHADER_TESS_EVAL))
      return false;

   lower_tess_level_visitor v(shader->Stage);

   visit_list_elements(&v, shader->ir);

   if (v.new_tess_level_outer_var)
      shader->symbols->add_variable(v.new_tess_level_outer_var);
   if (v.new_tess_level_inner_var)
      shader->symbols->add_variable(v.new_tess_level_inner_var);

   return v.progress;
}
예제 #24
0
void
link_uniform_blocks(void *mem_ctx,
                    struct gl_context *ctx,
                    struct gl_shader_program *prog,
                    struct gl_linked_shader *shader,
                    struct gl_uniform_block **ubo_blocks,
                    unsigned *num_ubo_blocks,
                    struct gl_uniform_block **ssbo_blocks,
                    unsigned *num_ssbo_blocks)
{
   /* This hash table will track all of the uniform blocks that have been
    * encountered.  Since blocks with the same block-name must be the same,
    * the hash is organized by block-name.
    */
   struct hash_table *block_hash =
      _mesa_hash_table_create(mem_ctx, _mesa_key_hash_string,
                              _mesa_key_string_equal);

   if (block_hash == NULL) {
      _mesa_error_no_memory(__func__);
      linker_error(prog, "out of memory\n");
      return;
   }

   /* Determine which uniform blocks are active.
    */
   link_uniform_block_active_visitor v(mem_ctx, block_hash, prog);
   visit_list_elements(&v, shader->ir);

   /* Count the number of active uniform blocks.  Count the total number of
    * active slots in those uniform blocks.
    */
   unsigned num_ubo_variables = 0;
   unsigned num_ssbo_variables = 0;
   count_block_size block_size;
   struct hash_entry *entry;

   hash_table_foreach (block_hash, entry) {
      struct link_uniform_block_active *const b =
         (struct link_uniform_block_active *) entry->data;

      assert((b->array != NULL) == b->type->is_array());

      if (b->array != NULL &&
          (b->type->without_array()->interface_packing ==
           GLSL_INTERFACE_PACKING_PACKED)) {
         b->type = resize_block_array(b->type, b->array);
         b->var->type = b->type;
      }

      block_size.num_active_uniforms = 0;
      block_size.process(b->type->without_array(), "");

      if (b->array != NULL) {
         unsigned aoa_size = b->type->arrays_of_arrays_size();
         if (b->is_shader_storage) {
            *num_ssbo_blocks += aoa_size;
            num_ssbo_variables += aoa_size * block_size.num_active_uniforms;
         } else {
            *num_ubo_blocks += aoa_size;
            num_ubo_variables += aoa_size * block_size.num_active_uniforms;
         }
      } else {
         if (b->is_shader_storage) {
            (*num_ssbo_blocks)++;
            num_ssbo_variables += block_size.num_active_uniforms;
         } else {
            (*num_ubo_blocks)++;
            num_ubo_variables += block_size.num_active_uniforms;
         }
      }

   }

   create_buffer_blocks(mem_ctx, ctx, prog, ubo_blocks, *num_ubo_blocks,
                        block_hash, num_ubo_variables, true);
   create_buffer_blocks(mem_ctx, ctx, prog, ssbo_blocks, *num_ssbo_blocks,
                        block_hash, num_ssbo_variables, false);

   _mesa_hash_table_destroy(block_hash, NULL);
}
예제 #25
0
void
lower_output_reads(unsigned stage, exec_list *instructions)
{
   output_read_remover v(stage);
   visit_list_elements(&v, instructions);
}
void
ir_hierarchical_visitor::run(exec_list *instructions)
{
   visit_list_elements(this, instructions);
}
예제 #27
0
void
lower_output_reads(exec_list *instructions)
{
   output_read_remover v;
   visit_list_elements(&v, instructions);
}