void ir3_block_depth(struct ir3_block *block) { unsigned i; block->head = NULL; ir3_clear_mark(block->shader); for (i = 0; i < block->noutputs; i++) if (block->outputs[i]) ir3_instr_depth(block->outputs[i]); /* mark un-used instructions: */ for (i = 0; i < block->shader->instrs_count; i++) { struct ir3_instruction *instr = block->shader->instrs[i]; /* just consider instructions within this block: */ if (instr->block != block) continue; if (!ir3_instr_check_mark(instr)) instr->depth = DEPTH_UNUSED; } /* cleanup unused inputs: */ for (i = 0; i < block->ninputs; i++) { struct ir3_instruction *in = block->inputs[i]; if (in && (in->depth == DEPTH_UNUSED)) block->inputs[i] = NULL; } }
void ir3_cp(struct ir3 *ir, struct ir3_shader_variant *so) { struct ir3_cp_ctx ctx = { .shader = ir, .so = so, }; ir3_clear_mark(ir); for (unsigned i = 0; i < ir->noutputs; i++) { if (ir->outputs[i]) { instr_cp(&ctx, ir->outputs[i]); ir->outputs[i] = eliminate_output_mov(ir->outputs[i]); } } list_for_each_entry (struct ir3_block, block, &ir->block_list, node) { if (block->condition) { instr_cp(&ctx, block->condition); block->condition = eliminate_output_mov(block->condition); } for (unsigned i = 0; i < block->keeps_count; i++) { instr_cp(&ctx, block->keeps[i]); block->keeps[i] = eliminate_output_mov(block->keeps[i]); } } }
int ir3_block_sched(struct ir3_block *block) { struct ir3_sched_ctx ctx = {0}; ir3_clear_mark(block->shader); block_sched(&ctx, block); if (ctx.error) return -1; return 0; }
void ir3_cp(struct ir3 *ir, struct ir3_shader_variant *so) { struct ir3_cp_ctx ctx = { .shader = ir, .so = so, }; /* This is a bit annoying, and probably wouldn't be necessary if we * tracked a reverse link from producing instruction to consumer. * But we need to know when we've eliminated the last consumer of * a mov, so we need to do a pass to first count consumers of a * mov. */ list_for_each_entry (struct ir3_block, block, &ir->block_list, node) { list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) { struct ir3_instruction *src; /* by the way, we don't account for false-dep's, so the CP * pass should always happen before false-dep's are inserted */ debug_assert(instr->deps_count == 0); foreach_ssa_src(src, instr) { src->use_count++; } } } ir3_clear_mark(ir); for (unsigned i = 0; i < ir->noutputs; i++) { if (ir->outputs[i]) { instr_cp(&ctx, ir->outputs[i]); ir->outputs[i] = eliminate_output_mov(ir->outputs[i]); } } list_for_each_entry (struct ir3_block, block, &ir->block_list, node) { if (block->condition) { instr_cp(&ctx, block->condition); block->condition = eliminate_output_mov(block->condition); } for (unsigned i = 0; i < block->keeps_count; i++) { instr_cp(&ctx, block->keeps[i]); block->keeps[i] = eliminate_output_mov(block->keeps[i]); } } }
void ir3_block_depth(struct ir3_block *block) { unsigned i; block->head = NULL; ir3_clear_mark(block->shader); for (i = 0; i < block->noutputs; i++) if (block->outputs[i]) ir3_instr_depth(block->outputs[i]); /* at this point, any unvisited input is unused: */ for (i = 0; i < block->ninputs; i++) { struct ir3_instruction *in = block->inputs[i]; if (in && !ir3_instr_check_mark(in)) block->inputs[i] = NULL; } }
void ir3_group(struct ir3 *ir) { ir3_clear_mark(ir); find_neighbors(ir); }