aco/spill: Allow spilling live-through operands
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29730>
This commit is contained in:
Natalie Vock 2024-04-21 17:22:54 +02:00 committed by Marge Bot
parent 416a016127
commit d6cb45dbb0

View file

@ -15,6 +15,7 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <optional>
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
@ -917,13 +918,17 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, RegisterDemand s
/* check if register demand is low enough during and after the current instruction */ /* check if register demand is low enough during and after the current instruction */
if (block->register_demand.exceeds(ctx.target_pressure)) { if (block->register_demand.exceeds(ctx.target_pressure)) {
RegisterDemand new_demand = instr->register_demand; RegisterDemand new_demand = instr->register_demand;
std::optional<RegisterDemand> live_changes;
/* if reg pressure is too high, spill variable with furthest next use */ /* if reg pressure is too high, spill variable with furthest next use */
while ((new_demand - spilled_registers).exceeds(ctx.target_pressure)) { while ((new_demand - spilled_registers).exceeds(ctx.target_pressure)) {
float score = 0.0; float score = 0.0;
Temp to_spill = Temp(); Temp to_spill = Temp();
bool spill_is_operand = false;
unsigned respill_slot = -1u;
unsigned do_rematerialize = 0; unsigned do_rematerialize = 0;
unsigned avoid_respill = 0; unsigned avoid_respill = 0;
RegType type = RegType::sgpr; RegType type = RegType::sgpr;
if (new_demand.vgpr - spilled_registers.vgpr > ctx.target_pressure.vgpr) if (new_demand.vgpr - spilled_registers.vgpr > ctx.target_pressure.vgpr)
type = RegType::vgpr; type = RegType::vgpr;
@ -941,24 +946,62 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, RegisterDemand s
if (can_rematerialize > do_rematerialize || loop_variable > avoid_respill || if (can_rematerialize > do_rematerialize || loop_variable > avoid_respill ||
ctx.ssa_infos[t].score() > score) { ctx.ssa_infos[t].score() > score) {
/* Don't spill operands */ bool is_operand = false;
if (std::any_of(instr->operands.begin(), instr->operands.end(), bool can_spill = true;
[&](Operand& op) { return op.isTemp() && op.getTemp() == var; })) for (auto& op : instr->operands) {
if (!op.isTemp() || op.getTemp() != var)
continue; continue;
/* Spilling vector operands causes us to emit a split_vector, increasing live
* state temporarily.
*/
if (op.isLateKill() || op.isKill() || op.size() > 1) {
can_spill = false;
break;
}
if (!live_changes)
live_changes = get_temp_reg_changes(instr.get());
/* Don't spill operands if killing operands won't help with register pressure */
if (RegisterDemand(op.getTemp()).exceeds(*live_changes)) {
can_spill = false;
break;
}
is_operand = true;
break;
}
if (!can_spill)
continue;
bool is_spilled_operand = is_operand && reloads.count(var);
to_spill = var; to_spill = var;
score = ctx.ssa_infos[t].score(); score = ctx.ssa_infos[t].score();
do_rematerialize = can_rematerialize; do_rematerialize = can_rematerialize;
avoid_respill = loop_variable; avoid_respill = loop_variable || is_spilled_operand;
spill_is_operand = is_operand;
/* This variable is spilled at the loop-header of the current loop.
* Re-use the spill-slot in order to avoid an extra store.
*/
if (loop_variable)
respill_slot = ctx.loop.back().spills[var];
else if (is_spilled_operand)
respill_slot = reloads[var].second;
} }
} }
assert(to_spill != Temp()); assert(to_spill != Temp());
if (avoid_respill) { if (spill_is_operand) {
/* This variable is spilled at the loop-header of the current loop. /* We might not be able to spill all operands. Keep live_changes up-to-date so we
* Re-use the spill-slot in order to avoid an extra store. * stop when we spilled every operand we can.
*/ */
current_spills[to_spill] = ctx.loop.back().spills[to_spill]; *live_changes -= to_spill;
}
if (avoid_respill) {
current_spills[to_spill] = respill_slot;
spilled_registers += to_spill; spilled_registers += to_spill;
continue; continue;
} }