aco: track and use the live-in register demand per basic block

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29804>
This commit is contained in:
Daniel Schürmann
2024-06-19 14:11:51 +02:00
committed by Marge Bot
parent 001c8caae0
commit 09f1c40f2e
3 changed files with 12 additions and 35 deletions

View File

@@ -1887,6 +1887,7 @@ struct Block {
edge_vec logical_succs;
edge_vec linear_succs;
RegisterDemand register_demand = RegisterDemand();
RegisterDemand live_in_demand = RegisterDemand();
uint32_t kind = 0;
int32_t logical_idom = -1;
int32_t linear_idom = -1;

View File

@@ -200,7 +200,6 @@ process_live_temps_per_block(Program* program, Block* block, unsigned& worklist,
uint16_t linear_phi_defs = 0;
int phi_idx = idx;
while (phi_idx >= 0) {
register_demand[phi_idx] = new_demand;
Instruction* insn = block->instructions[phi_idx].get();
assert(is_phi(insn) && insn->definitions.size() == 1);
@@ -215,10 +214,12 @@ process_live_temps_per_block(Program* program, Block* block, unsigned& worklist,
const Temp temp = definition.getTemp();
const size_t n = live.erase(temp.id());
if (n)
if (n) {
definition.setKill(false);
else
} else {
new_demand += temp;
definition.setKill(true);
}
if (insn->opcode == aco_opcode::p_linear_phi) {
assert(definition.getTemp().type() == RegType::sgpr);
@@ -268,6 +269,7 @@ process_live_temps_per_block(Program* program, Block* block, unsigned& worklist,
/* handle phi operands */
phi_idx = idx;
while (phi_idx >= 0) {
register_demand[phi_idx] = new_demand;
Instruction* insn = block->instructions[phi_idx].get();
assert(is_phi(insn));
/* directly insert into the predecessors live-out set */
@@ -297,6 +299,9 @@ process_live_temps_per_block(Program* program, Block* block, unsigned& worklist,
phi_idx--;
}
block->live_in_demand = new_demand;
block->live_in_demand.sgpr += 2; /* Add 2 SGPRs for potential long-jumps. */
assert(!block->linear_preds.empty() || (new_demand == RegisterDemand() && live.empty()));
}

View File

@@ -308,34 +308,6 @@ get_demand_before(spill_ctx& ctx, unsigned block_idx, unsigned idx)
}
}
RegisterDemand
get_live_in_demand(spill_ctx& ctx, unsigned block_idx)
{
unsigned idx = 0;
RegisterDemand reg_pressure = RegisterDemand();
Block& block = ctx.program->blocks[block_idx];
for (aco_ptr<Instruction>& phi : block.instructions) {
if (!is_phi(phi))
break;
idx++;
/* Killed phi definitions increase pressure in the predecessor but not
* the block they're in. Since the loops below are both to control
* pressure of the start of this block and the ends of it's
* predecessors, we need to count killed unspilled phi definitions here. */
if (phi->definitions[0].isTemp() && phi->definitions[0].isKill() &&
!ctx.spills_entry[block_idx].count(phi->definitions[0].getTemp()))
reg_pressure += phi->definitions[0].getTemp();
}
reg_pressure += get_demand_before(ctx, block_idx, idx);
/* In order to create long jumps, we might need an empty SGPR pair. */
reg_pressure.sgpr += 2;
return reg_pressure;
}
RegisterDemand
init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
{
@@ -354,7 +326,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
assert(block->logical_preds[0] == block_idx - 1);
/* check how many live-through variables should be spilled */
RegisterDemand reg_pressure = get_live_in_demand(ctx, block_idx);
RegisterDemand reg_pressure = block->live_in_demand;
RegisterDemand loop_demand = reg_pressure;
unsigned i = block_idx;
while (ctx.program->blocks[i].loop_nest_depth >= block->loop_nest_depth)
@@ -570,7 +542,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
}
/* if reg pressure at first instruction is still too high, add partially spilled variables */
RegisterDemand reg_pressure = get_live_in_demand(ctx, block_idx);
RegisterDemand reg_pressure = block->live_in_demand;
reg_pressure -= spilled_registers;
while (reg_pressure.exceeds(ctx.target_pressure)) {
@@ -929,11 +901,10 @@ add_coupling_code(spill_ctx& ctx, Block* block, IDSet& live_in)
if (!ctx.processed[block_idx]) {
assert(!(block->kind & block_kind_loop_header));
RegisterDemand demand_before = get_demand_before(ctx, block_idx, idx);
std::vector<RegisterDemand>& register_demand =
ctx.program->live.register_demand[block->index];
register_demand.erase(register_demand.begin(), register_demand.begin() + idx);
register_demand.insert(register_demand.begin(), instructions.size(), demand_before);
register_demand.insert(register_demand.begin(), instructions.size(), block->live_in_demand);
}
std::vector<aco_ptr<Instruction>>::iterator start = std::next(block->instructions.begin(), idx);