src/lima/pp_lir/peephole.c
//Finds instructions of the form:
//^uniform = loadu
//register = mov ^uniform
//And tries to move the uniform load into uses of the register
Finds instructions of the form:
^uniform = loadu
register = mov ^uniform
And tries to move the uniform load into uses of the register
Finds instructions of the form : ^uniform = loadu register = mov ^uniform And tries to move the uniform load into uses of the register
static bool peephole_uniform(lima_pp_lir_scheduled_instr_t* instr)
{
	if (!instr->uniform_instr)
		return true;
	if (instr->uniform_instr->op != lima_pp_hir_op_loadu_one &&
		instr->uniform_instr->op != lima_pp_hir_op_loadu_one_off &&
		instr->uniform_instr->op != lima_pp_hir_op_loadu_two &&
		instr->uniform_instr->op != lima_pp_hir_op_loadu_two_off &&
		instr->uniform_instr->op != lima_pp_hir_op_loadu_four &&
		instr->uniform_instr->op != lima_pp_hir_op_loadu_four_off)
		return true;
	if (instr->varying_instr ||
		instr->texld_instr ||
		instr->temp_store_instr ||
		instr->branch_instr)
		return true;
	lima_pp_lir_reg_t* offset = NULL;
	if (lima_pp_hir_op[instr->uniform_instr->op].args == 1)
		offset = instr->uniform_instr->sources[0].reg;
	lima_pp_lir_instr_t* move = find_single_pipeline_move(
		instr,
		lima_pp_lir_pipeline_reg_uniform,
		uniform_load_width(instr->uniform_instr->op));
	if (!move)
		return true;
	lima_pp_lir_reg_t* reg = move->dest.reg;
	if (ptrset_size(reg->defs) > 1)
		return true;
	unsigned i = 0;
	while (instr->alu_instrs[i] != move)
		i++;
	for (i++; i < 5; i++)
		if (instr->alu_instrs[i] && !instr->alu_instrs[i]->dest.pipeline &&
			instr->alu_instrs[i]->dest.reg == offset)
		{
			return true;
		}
	if (instr->temp_store_instr &&
		lima_pp_hir_op[instr->temp_store_instr->op].has_dest &&
		!instr->temp_store_instr->dest.pipeline &&
		 instr->temp_store_instr->dest.reg == offset)
	{
		return true;
	}
	lima_pp_lir_instr_t* use_instr;
	ptrset_iter_t iter = ptrset_iter_create(reg->uses);
	ptrset_iter_for_each(iter, use_instr)
	{
		lima_pp_lir_scheduled_instr_t* use = use_instr->sched_instr;
		if (offset && !ptrset_contains(instr->min_succs, use))
			continue;
		if (use->uniform_instr)
			continue;
		if (use_instr == use->varying_instr)
			continue;
		if (use->varying_instr &&
			!use->varying_instr->dest.pipeline &&
			 use->varying_instr->dest.reg == offset)
			continue;
		if (use_instr == use->texld_instr)
			continue;
		use->uniform_instr = copy_uniform_instr(instr->uniform_instr);
		if (!use->uniform_instr)
			return false;
		use->uniform_instr->sched_instr = use;
		for (i = 0; i < 5; i++)
		{
			if (!use->alu_instrs[i])
				continue;
			if (use->alu_instrs[i] == use_instr)
			{
				reg_to_pipeline_reg(use_instr, reg,
									lima_pp_lir_pipeline_reg_uniform);
				break;
			}
		}
		if (use->temp_store_instr == use_instr)
		{
			reg_to_pipeline_reg(use_instr, reg,
								lima_pp_lir_pipeline_reg_uniform);
			continue;
		}
		if (use->branch_instr == use_instr)
		{
			reg_to_pipeline_reg(use_instr, reg,
								lima_pp_lir_pipeline_reg_uniform);
		}
	}
	if (ptrset_size(reg->uses) == 0)
	{
		delete_reg(reg, instr->block->prog);
		remove_instr(instr);
	}
	return true;
}
static bool peephole_uniform ( lima_pp_lir_scheduled_instr_t * instr ) { if ( ! instr -> uniform_instr ) return true ; if ( instr -> uniform_instr -> op != lima_pp_hir_op_loadu_one && instr -> uniform_instr -> op != lima_pp_hir_op_loadu_one_off && instr -> uniform_instr -> op != lima_pp_hir_op_loadu_two && instr -> uniform_instr -> op != lima_pp_hir_op_loadu_two_off && instr -> uniform_instr -> op != lima_pp_hir_op_loadu_four && instr -> uniform_instr -> op != lima_pp_hir_op_loadu_four_off ) return true ; if ( instr -> varying_instr || instr -> texld_instr || instr -> temp_store_instr || instr -> branch_instr ) return true ; lima_pp_lir_reg_t * offset = NULL ; if ( lima_pp_hir_op [ instr -> uniform_instr -> op ] . args == 1 ) offset = instr -> uniform_instr -> sources [ 0 ] . reg ; lima_pp_lir_instr_t * move = find_single_pipeline_move ( instr , lima_pp_lir_pipeline_reg_uniform , uniform_load_width ( instr -> uniform_instr -> op ) ) ; if ( ! move ) return true ; lima_pp_lir_reg_t * reg = move -> dest . reg ; if ( ptrset_size ( reg -> defs ) > 1 ) return true ; unsigned i = 0 ; while ( instr -> alu_instrs [ i ] != move ) i ++ ; for ( i ++ ; i < 5 ; i ++ ) if ( instr -> alu_instrs [ i ] && ! instr -> alu_instrs [ i ] -> dest . pipeline && instr -> alu_instrs [ i ] -> dest . reg == offset ) { return true ; } if ( instr -> temp_store_instr && lima_pp_hir_op [ instr -> temp_store_instr -> op ] . has_dest && ! instr -> temp_store_instr -> dest . pipeline && instr -> temp_store_instr -> dest . reg == offset ) { return true ; } lima_pp_lir_instr_t * use_instr ; ptrset_iter_t iter = ptrset_iter_create ( reg -> uses ) ; ptrset_iter_for_each ( iter , use_instr ) { lima_pp_lir_scheduled_instr_t * use = use_instr -> sched_instr ; if ( offset && ! ptrset_contains ( instr -> min_succs , use ) ) continue ; if ( use -> uniform_instr ) continue ; if ( use_instr == use -> varying_instr ) continue ; if ( use -> varying_instr && ! use -> varying_instr -> dest . pipeline && use -> varying_instr -> dest . reg == offset ) continue ; if ( use_instr == use -> texld_instr ) continue ; use -> uniform_instr = copy_uniform_instr ( instr -> uniform_instr ) ; if ( ! use -> uniform_instr ) return false ; use -> uniform_instr -> sched_instr = use ; for ( i = 0 ; i < 5 ; i ++ ) { if ( ! use -> alu_instrs [ i ] ) continue ; if ( use -> alu_instrs [ i ] == use_instr ) { reg_to_pipeline_reg ( use_instr , reg , lima_pp_lir_pipeline_reg_uniform ) ; break ; } } if ( use -> temp_store_instr == use_instr ) { reg_to_pipeline_reg ( use_instr , reg , lima_pp_lir_pipeline_reg_uniform ) ; continue ; } if ( use -> branch_instr == use_instr ) { reg_to_pipeline_reg ( use_instr , reg , lima_pp_lir_pipeline_reg_uniform ) ; } } if ( ptrset_size ( reg -> uses ) == 0 ) { delete_reg ( reg , instr -> block -> prog ) ; remove_instr ( instr ) ; } return true ; }
Finds instructions of the form:
^uniform = loadu
register = mov ^uniform
And tries to move the uniform load into uses of the register
Finds instructions of the form : ^uniform = loadu register = mov ^uniform And tries to move the uniform load into uses of the register