Mesa (main): aco/spill: Persist memory allocations of local next use maps

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Oct 1 09:57:11 UTC 2021


Module: Mesa
Branch: main
Commit: df6c395095e02ebf91a93b3174e4ce0137ad0b3e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=df6c395095e02ebf91a93b3174e4ce0137ad0b3e

Author: Tony Wasserka <tony.wasserka at gmx.de>
Date:   Mon Jul 19 19:32:38 2021 +0200

aco/spill: Persist memory allocations of local next use maps

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 <daniel at schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11925>

---

 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<std::map<Temp, Temp>> renames;
    std::vector<std::map<Temp, uint32_t>> spills_entry;
    std::vector<std::map<Temp, uint32_t>> spills_exit;
+
    std::vector<bool> processed;
    std::stack<Block*, std::vector<Block*>> loop_header;
    std::vector<std::map<Temp, std::pair<uint32_t, uint32_t>>> next_use_distances_start;
    std::vector<std::map<Temp, std::pair<uint32_t, uint32_t>>> next_use_distances_end;
+   std::vector<std::map<Temp, uint32_t>> local_next_use_distance; /* Working buffer */
    std::vector<std::pair<RegClass, std::unordered_set<uint32_t>>> interferences;
    std::vector<std::vector<uint32_t>> affinities;
    std::vector<bool> is_reloaded;
@@ -354,11 +356,13 @@ get_rematerialize_info(spill_ctx& ctx)
    }
 }
 
-std::vector<std::map<Temp, uint32_t>>
-local_next_uses(spill_ctx& ctx, Block* block)
+void
+update_local_next_uses(spill_ctx& ctx, Block* block,
+                std::vector<std::map<Temp, uint32_t>>& local_next_uses)
 {
-   std::vector<std::map<Temp, uint32_t>> local_next_uses(block->instructions.size());
+   local_next_uses.resize(block->instructions.size());
 
+   local_next_uses[block->instructions.size() - 1].clear();
    for (std::pair<const Temp, std::pair<uint32_t, uint32_t>>& 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<std::map<Temp, uint32_t>> local_next_use_distance;
    std::vector<aco_ptr<Instruction>> 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<Instruction>& 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<Temp, uint32_t> pair : local_next_use_distance[idx]) {
+            for (std::pair<Temp, uint32_t> pair : ctx.local_next_use_distance[idx]) {
                if (pair.first.type() != type)
                   continue;
                bool can_rematerialize = ctx.remat.count(pair.first);



More information about the mesa-commit mailing list