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:

committed by
Marge Bot

parent
001c8caae0
commit
09f1c40f2e
@@ -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;
|
||||
|
@@ -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()));
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user