From df6c395095e02ebf91a93b3174e4ce0137ad0b3e Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Mon, 19 Jul 2021 19:32:38 +0200 Subject: [PATCH] aco/spill: Persist memory allocations of local next use maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function local_next_uses allocated one next-use map per instruction in the current block. Since the function is called once per block, this caused an excessive amount of memory allocations to take place. With this change, the memory for next-use maps is allocated only once and then reused for later blocks. Reviewed-by: Daniel Schürmann Part-of: --- src/amd/compiler/aco_spill.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/amd/compiler/aco_spill.cpp b/src/amd/compiler/aco_spill.cpp index fcb0eafbb2b..1965b53f4f7 100644 --- a/src/amd/compiler/aco_spill.cpp +++ b/src/amd/compiler/aco_spill.cpp @@ -55,10 +55,12 @@ struct spill_ctx { std::vector> renames; std::vector> spills_entry; std::vector> spills_exit; + std::vector processed; std::stack> loop_header; std::vector>> next_use_distances_start; std::vector>> next_use_distances_end; + std::vector> local_next_use_distance; /* Working buffer */ std::vector>> interferences; std::vector> affinities; std::vector is_reloaded; @@ -354,11 +356,13 @@ get_rematerialize_info(spill_ctx& ctx) } } -std::vector> -local_next_uses(spill_ctx& ctx, Block* block) +void +update_local_next_uses(spill_ctx& ctx, Block* block, + std::vector>& local_next_uses) { - std::vector> local_next_uses(block->instructions.size()); + local_next_uses.resize(block->instructions.size()); + local_next_uses[block->instructions.size() - 1].clear(); for (std::pair>& pair : ctx.next_use_distances_end[block->index]) { local_next_uses[block->instructions.size() - 1].insert( @@ -391,7 +395,6 @@ local_next_uses(spill_ctx& ctx, Block* block) } } } - return local_next_uses; } RegisterDemand @@ -1117,7 +1120,6 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, { assert(!ctx.processed[block_idx]); - std::vector> local_next_use_distance; std::vector> instructions; unsigned idx = 0; @@ -1127,8 +1129,11 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, instructions.emplace_back(std::move(block->instructions[idx++])); } - if (block->register_demand.exceeds(ctx.target_pressure)) - local_next_use_distance = local_next_uses(ctx, block); + if (block->register_demand.exceeds(ctx.target_pressure)) { + update_local_next_uses(ctx, block, ctx.local_next_use_distance); + } else { + /* We won't use local_next_use_distance, so no initialization needed */ + } while (idx < block->instructions.size()) { aco_ptr& instr = block->instructions[idx]; @@ -1163,7 +1168,7 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, RegisterDemand new_demand = ctx.register_demand[block_idx][idx]; new_demand.update(get_demand_before(ctx, block_idx, idx)); - assert(!local_next_use_distance.empty()); + assert(!ctx.local_next_use_distance.empty()); /* if reg pressure is too high, spill variable with furthest next use */ while ((new_demand - spilled_registers).exceeds(ctx.target_pressure)) { @@ -1174,7 +1179,7 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, if (new_demand.vgpr - spilled_registers.vgpr > ctx.target_pressure.vgpr) type = RegType::vgpr; - for (std::pair pair : local_next_use_distance[idx]) { + for (std::pair pair : ctx.local_next_use_distance[idx]) { if (pair.first.type() != type) continue; bool can_rematerialize = ctx.remat.count(pair.first);