mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-21 13:40:16 +01:00
aco/spill: Allow spilling live-through operands
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29730>
This commit is contained in:
parent
416a016127
commit
d6cb45dbb0
1 changed files with 51 additions and 8 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue