Mesa (main): aco/spill: Reduce redundant std::map lookups

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


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

Author: Tony Wasserka <tony.wasserka at gmx.de>
Date:   Tue Jul 13 12:59:58 2021 +0200

aco/spill: Reduce redundant std::map lookups

The previous code checked for element containment first and then performed
another map lookup upon element access. Instead, map::find can be used to
retrieve an iterator usable for element access with no extra lookup needed.

Furthermore, pure containment checks have been simplified using map::count.

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 | 142 ++++++++++++++++++++++-------------------
 1 file changed, 76 insertions(+), 66 deletions(-)

diff --git a/src/amd/compiler/aco_spill.cpp b/src/amd/compiler/aco_spill.cpp
index cc4b9a54fd3..5514d0e2950 100644
--- a/src/amd/compiler/aco_spill.cpp
+++ b/src/amd/compiler/aco_spill.cpp
@@ -223,11 +223,13 @@ next_uses_per_block(spill_ctx& ctx, unsigned block_idx, std::set<uint32_t>& work
          unsigned pred_idx =
             instr->opcode == aco_opcode::p_phi ? block->logical_preds[i] : block->linear_preds[i];
          if (instr->operands[i].isTemp()) {
-            if (ctx.next_use_distances_end[pred_idx].find(instr->operands[i].getTemp()) ==
-                   ctx.next_use_distances_end[pred_idx].end() ||
-                ctx.next_use_distances_end[pred_idx][instr->operands[i].getTemp()] != distance)
+            auto insert_result = ctx.next_use_distances_end[pred_idx].insert(
+               std::make_pair(instr->operands[i].getTemp(), distance));
+            const bool inserted = insert_result.second;
+            std::pair<uint32_t, uint32_t>& entry_distance = insert_result.first->second;
+            if (inserted || entry_distance != distance)
                worklist.insert(pred_idx);
-            ctx.next_use_distances_end[pred_idx][instr->operands[i].getTemp()] = distance;
+            entry_distance = distance;
          }
       }
       idx--;
@@ -242,16 +244,19 @@ next_uses_per_block(spill_ctx& ctx, unsigned block_idx, std::set<uint32_t>& work
       for (unsigned pred_idx : preds) {
          if (ctx.program->blocks[pred_idx].loop_nest_depth > block->loop_nest_depth)
             distance += 0xFFFF;
-         if (ctx.next_use_distances_end[pred_idx].find(temp) !=
-             ctx.next_use_distances_end[pred_idx].end()) {
-            dom = get_dominator(dom, ctx.next_use_distances_end[pred_idx][temp].first, ctx.program,
-                                temp.is_linear());
-            distance = std::min(ctx.next_use_distances_end[pred_idx][temp].second, distance);
+         auto insert_result = ctx.next_use_distances_end[pred_idx].insert(
+            std::make_pair(temp, std::pair<uint32_t, uint32_t>{}));
+         const bool inserted = insert_result.second;
+         std::pair<uint32_t, uint32_t>& entry_distance = insert_result.first->second;
+
+         if (!inserted) {
+            dom = get_dominator(dom, entry_distance.first, ctx.program, temp.is_linear());
+            distance = std::min(entry_distance.second, distance);
          }
-         if (ctx.next_use_distances_end[pred_idx][temp] !=
-             std::pair<uint32_t, uint32_t>{dom, distance})
+         if (entry_distance != std::pair<uint32_t, uint32_t>{dom, distance}) {
             worklist.insert(pred_idx);
-         ctx.next_use_distances_end[pred_idx][temp] = {dom, distance};
+            entry_distance = {dom, distance};
+         }
       }
    }
 }
@@ -531,8 +536,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
             if (pair.first.type() == type &&
                 (pair.second.first >= loop_end ||
                  (ctx.remat.count(pair.first) && type == RegType::sgpr)) &&
-                pair.second.second > distance &&
-                ctx.spills_entry[block_idx].find(pair.first) == ctx.spills_entry[block_idx].end()) {
+                pair.second.second > distance && !ctx.spills_entry[block_idx].count(pair.first)) {
                to_spill = pair.first;
                distance = pair.second.second;
             }
@@ -547,8 +551,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
          }
 
          uint32_t spill_id;
-         if (ctx.spills_exit[block_idx - 1].find(to_spill) ==
-             ctx.spills_exit[block_idx - 1].end()) {
+         if (!ctx.spills_exit[block_idx - 1].count(to_spill)) {
             spill_id = ctx.allocate_spill_id(to_spill.regClass());
          } else {
             spill_id = ctx.spills_exit[block_idx - 1][to_spill];
@@ -573,7 +576,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
 
          for (std::pair<const Temp, std::pair<uint32_t, uint32_t>>& pair : next_use_distances) {
             if (pair.first.type() == type && pair.second.second > distance &&
-                ctx.spills_entry[block_idx].find(pair.first) == ctx.spills_entry[block_idx].end()) {
+                !ctx.spills_entry[block_idx].count(pair.first)) {
                to_spill = pair.first;
                distance = pair.second.second;
             }
@@ -592,9 +595,12 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
       /* keep variables spilled if they are alive and not used in the current block */
       unsigned pred_idx = block->linear_preds[0];
       for (std::pair<Temp, uint32_t> pair : ctx.spills_exit[pred_idx]) {
-         if (pair.first.type() == RegType::sgpr &&
-             next_use_distances.find(pair.first) != next_use_distances.end() &&
-             next_use_distances[pair.first].first != block_idx) {
+         if (pair.first.type() != RegType::sgpr) {
+            continue;
+         }
+         auto next_use_distance_it = next_use_distances.find(pair.first);
+         if (next_use_distance_it != next_use_distances.end() &&
+             next_use_distance_it->second.first != block_idx) {
             ctx.spills_entry[block_idx].insert(pair);
             spilled_registers.sgpr += pair.first.size();
          }
@@ -602,9 +608,12 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
       if (block->logical_preds.size() == 1) {
          pred_idx = block->logical_preds[0];
          for (std::pair<Temp, uint32_t> pair : ctx.spills_exit[pred_idx]) {
-            if (pair.first.type() == RegType::vgpr &&
-                next_use_distances.find(pair.first) != next_use_distances.end() &&
-                next_use_distances[pair.first].first != block_idx) {
+            if (pair.first.type() != RegType::vgpr) {
+               continue;
+            }
+            auto next_use_distance_it = next_use_distances.find(pair.first);
+            if (next_use_distance_it != next_use_distances.end() &&
+                next_use_distance_it->second.first != block_idx) {
                ctx.spills_entry[block_idx].insert(pair);
                spilled_registers.vgpr += pair.first.size();
             }
@@ -616,8 +625,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
       if (block->register_demand.sgpr - spilled_registers.sgpr > ctx.target_pressure.sgpr) {
          pred_idx = block->linear_preds[0];
          for (std::pair<Temp, uint32_t> pair : ctx.spills_exit[pred_idx]) {
-            if (pair.first.type() == RegType::sgpr &&
-                next_use_distances.find(pair.first) != next_use_distances.end() &&
+            if (pair.first.type() == RegType::sgpr && next_use_distances.count(pair.first) &&
                 ctx.spills_entry[block_idx].insert(pair).second) {
                spilled_registers.sgpr += pair.first.size();
             }
@@ -627,8 +635,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
           block->logical_preds.size() == 1) {
          pred_idx = block->logical_preds[0];
          for (std::pair<Temp, uint32_t> pair : ctx.spills_exit[pred_idx]) {
-            if (pair.first.type() == RegType::vgpr &&
-                next_use_distances.find(pair.first) != next_use_distances.end() &&
+            if (pair.first.type() == RegType::vgpr && next_use_distances.count(pair.first) &&
                 ctx.spills_entry[block_idx].insert(pair).second) {
                spilled_registers.vgpr += pair.first.size();
             }
@@ -656,12 +663,11 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
       uint32_t spill_id = 0;
       for (unsigned pred_idx : preds) {
          /* variable is not even live at the predecessor: probably from a phi */
-         if (ctx.next_use_distances_end[pred_idx].find(pair.first) ==
-             ctx.next_use_distances_end[pred_idx].end()) {
+         if (!ctx.next_use_distances_end[pred_idx].count(pair.first)) {
             spill = false;
             break;
          }
-         if (ctx.spills_exit[pred_idx].find(pair.first) == ctx.spills_exit[pred_idx].end()) {
+         if (!ctx.spills_exit[pred_idx].count(pair.first)) {
             if (!remat)
                spill = false;
          } else {
@@ -698,8 +704,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
             continue;
          }
 
-         if (ctx.spills_exit[preds[i]].find(phi->operands[i].getTemp()) ==
-             ctx.spills_exit[preds[i]].end())
+         if (!ctx.spills_exit[preds[i]].count(phi->operands[i].getTemp()))
             spill = false;
          else
             partial_spills.insert(phi->definitions[0].getTemp());
@@ -724,7 +729,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
       RegType type = reg_pressure.vgpr > ctx.target_pressure.vgpr ? RegType::vgpr : RegType::sgpr;
 
       while (it != partial_spills.end()) {
-         assert(ctx.spills_entry[block_idx].find(*it) == ctx.spills_entry[block_idx].end());
+         assert(!ctx.spills_entry[block_idx].count(*it));
 
          if (it->type() == type && next_use_distances[*it].second > distance) {
             distance = next_use_distances[*it].second;
@@ -767,11 +772,12 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
          if (!live.first.is_linear())
             continue;
          /* still spilled */
-         if (ctx.spills_entry[block_idx].find(live.first) != ctx.spills_entry[block_idx].end())
+         if (ctx.spills_entry[block_idx].count(live.first))
             continue;
 
          /* in register at end of predecessor */
-         if (ctx.spills_exit[pred_idx].find(live.first) == ctx.spills_exit[pred_idx].end()) {
+         auto spills_exit_it = ctx.spills_exit[pred_idx].find(live.first);
+         if (spills_exit_it == ctx.spills_exit[pred_idx].end()) {
             std::map<Temp, Temp>::iterator it = ctx.renames[pred_idx].find(live.first);
             if (it != ctx.renames[pred_idx].end())
                ctx.renames[block_idx].insert(*it);
@@ -780,8 +786,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
 
          /* variable is spilled at predecessor and live at current block: create reload instruction */
          Temp new_name = ctx.program->allocateTmp(live.first.regClass());
-         aco_ptr<Instruction> reload =
-            do_reload(ctx, live.first, new_name, ctx.spills_exit[pred_idx][live.first]);
+         aco_ptr<Instruction> reload = do_reload(ctx, live.first, new_name, spills_exit_it->second);
          instructions.emplace_back(std::move(reload));
          reg_demand.push_back(demand_before);
          ctx.renames[block_idx][live.first] = new_name;
@@ -801,11 +806,12 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
             if (live.first.is_linear())
                continue;
             /* still spilled */
-            if (ctx.spills_entry[block_idx].find(live.first) != ctx.spills_entry[block_idx].end())
+            if (ctx.spills_entry[block_idx].count(live.first))
                continue;
 
             /* in register at end of predecessor */
-            if (ctx.spills_exit[pred_idx].find(live.first) == ctx.spills_exit[pred_idx].end()) {
+            auto spills_exit_it = ctx.spills_exit[pred_idx].find(live.first);
+            if (spills_exit_it == ctx.spills_exit[pred_idx].end()) {
                std::map<Temp, Temp>::iterator it = ctx.renames[pred_idx].find(live.first);
                if (it != ctx.renames[pred_idx].end())
                   ctx.renames[block_idx].insert(*it);
@@ -816,7 +822,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
              * create reload instruction */
             Temp new_name = ctx.program->allocateTmp(live.first.regClass());
             aco_ptr<Instruction> reload =
-               do_reload(ctx, live.first, new_name, ctx.spills_exit[pred_idx][live.first]);
+               do_reload(ctx, live.first, new_name, spills_exit_it->second);
             instructions.emplace_back(std::move(reload));
             reg_demand.emplace_back(reg_demand.back());
             ctx.renames[block_idx][live.first] = new_name;
@@ -850,8 +856,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
 
       /* if the phi is not spilled, add to instructions */
       if (!phi->definitions[0].isTemp() ||
-          ctx.spills_entry[block_idx].find(phi->definitions[0].getTemp()) ==
-             ctx.spills_entry[block_idx].end()) {
+          !ctx.spills_entry[block_idx].count(phi->definitions[0].getTemp())) {
          instructions.emplace_back(std::move(phi));
          continue;
       }
@@ -935,8 +940,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
          }
 
          /* variable is dead at predecessor, it must be from a phi: this works because of CSSA form */
-         if (ctx.next_use_distances_end[pred_idx].find(pair.first) ==
-             ctx.next_use_distances_end[pred_idx].end())
+         if (!ctx.next_use_distances_end[pred_idx].count(pair.first))
             continue;
 
          /* add interferences between spilled variable and predecessors exit spills */
@@ -976,8 +980,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
    for (aco_ptr<Instruction>& phi : instructions) {
       assert(phi->opcode == aco_opcode::p_phi || phi->opcode == aco_opcode::p_linear_phi);
       assert(!phi->definitions[0].isTemp() ||
-             ctx.spills_entry[block_idx].find(phi->definitions[0].getTemp()) ==
-                ctx.spills_entry[block_idx].end());
+             !ctx.spills_entry[block_idx].count(phi->definitions[0].getTemp()));
 
       std::vector<unsigned>& preds =
          phi->opcode == aco_opcode::p_phi ? block->logical_preds : block->linear_preds;
@@ -987,15 +990,18 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
          unsigned pred_idx = preds[i];
 
          /* if the operand was reloaded, rename */
-         if (ctx.spills_exit[pred_idx].find(phi->operands[i].getTemp()) ==
-             ctx.spills_exit[pred_idx].end()) {
+         if (!ctx.spills_exit[pred_idx].count(phi->operands[i].getTemp())) {
             std::map<Temp, Temp>::iterator it =
                ctx.renames[pred_idx].find(phi->operands[i].getTemp());
-            if (it != ctx.renames[pred_idx].end())
+            if (it != ctx.renames[pred_idx].end()) {
                phi->operands[i].setTemp(it->second);
             /* prevent the definining instruction from being DCE'd if it could be rematerialized */
-            else if (ctx.remat.count(phi->operands[i].getTemp()))
-               ctx.remat_used[ctx.remat[phi->operands[i].getTemp()].instr] = true;
+            } else {
+               auto remat_it = ctx.remat.find(phi->operands[i].getTemp());
+               if (remat_it != ctx.remat.end()) {
+                  ctx.remat_used[remat_it->second.instr] = true;
+               }
+            }
             continue;
          }
 
@@ -1034,7 +1040,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
    for (std::pair<const Temp, std::pair<uint32_t, uint32_t>>& pair :
         ctx.next_use_distances_start[block_idx]) {
       /* skip spilled variables */
-      if (ctx.spills_entry[block_idx].find(pair.first) != ctx.spills_entry[block_idx].end())
+      if (ctx.spills_entry[block_idx].count(pair.first))
          continue;
       std::vector<unsigned> preds =
          pair.first.is_linear() ? block->linear_preds : block->logical_preds;
@@ -1042,15 +1048,14 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
       /* variable is dead at predecessor, it must be from a phi */
       bool is_dead = false;
       for (unsigned pred_idx : preds) {
-         if (ctx.next_use_distances_end[pred_idx].find(pair.first) ==
-             ctx.next_use_distances_end[pred_idx].end())
+         if (!ctx.next_use_distances_end[pred_idx].count(pair.first))
             is_dead = true;
       }
       if (is_dead)
          continue;
       for (unsigned pred_idx : preds) {
          /* the variable is not spilled at the predecessor */
-         if (ctx.spills_exit[pred_idx].find(pair.first) == ctx.spills_exit[pred_idx].end())
+         if (!ctx.spills_exit[pred_idx].count(pair.first))
             continue;
 
          /* variable is spilled at predecessor and has to be reloaded */
@@ -1076,7 +1081,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
       Temp rename = Temp();
       bool is_same = true;
       for (unsigned pred_idx : preds) {
-         if (ctx.renames[pred_idx].find(pair.first) == ctx.renames[pred_idx].end()) {
+         if (!ctx.renames[pred_idx].count(pair.first)) {
             if (rename == Temp())
                rename = pair.first;
             else
@@ -1100,7 +1105,7 @@ add_coupling_code(spill_ctx& ctx, Block* block, unsigned block_idx)
          rename = ctx.program->allocateTmp(pair.first.regClass());
          for (unsigned i = 0; i < phi->operands.size(); i++) {
             Temp tmp;
-            if (ctx.renames[preds[i]].find(pair.first) != ctx.renames[preds[i]].end()) {
+            if (ctx.renames[preds[i]].count(pair.first)) {
                tmp = ctx.renames[preds[i]][pair.first];
             } else if (preds[i] >= block_idx) {
                tmp = rename;
@@ -1174,13 +1179,18 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, RegisterDemand s
       for (Operand& op : instr->operands) {
          if (!op.isTemp())
             continue;
-         if (current_spills.find(op.getTemp()) == current_spills.end()) {
+         if (!current_spills.count(op.getTemp())) {
             /* the Operand is in register: check if it was renamed */
-            if (ctx.renames[block_idx].find(op.getTemp()) != ctx.renames[block_idx].end())
-               op.setTemp(ctx.renames[block_idx][op.getTemp()]);
-            /* prevent it's definining instruction from being DCE'd if it could be rematerialized */
-            else if (ctx.remat.count(op.getTemp()))
-               ctx.remat_used[ctx.remat[op.getTemp()].instr] = true;
+            auto rename_it = ctx.renames[block_idx].find(op.getTemp());
+            if (rename_it != ctx.renames[block_idx].end()) {
+               op.setTemp(rename_it->second);
+            } else {
+               /* prevent its definining instruction from being DCE'd if it could be rematerialized */
+               auto remat_it = ctx.remat.find(op.getTemp());
+               if (remat_it != ctx.remat.end()) {
+                  ctx.remat_used[remat_it->second.instr] = true;
+               }
+            }
             continue;
          }
          /* the Operand is spilled: add it to reloads */
@@ -1215,7 +1225,7 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, RegisterDemand s
                bool can_rematerialize = ctx.remat.count(pair.first);
                if (((pair.second > distance && can_rematerialize == do_rematerialize) ||
                     (can_rematerialize && !do_rematerialize && pair.second > idx)) &&
-                   current_spills.find(pair.first) == current_spills.end()) {
+                   !current_spills.count(pair.first)) {
                   to_spill = pair.first;
                   distance = pair.second;
                   do_rematerialize = can_rematerialize;
@@ -1235,7 +1245,7 @@ process_block(spill_ctx& ctx, unsigned block_idx, Block* block, RegisterDemand s
             spilled_registers += to_spill;
 
             /* rename if necessary */
-            if (ctx.renames[block_idx].find(to_spill) != ctx.renames[block_idx].end()) {
+            if (ctx.renames[block_idx].count(to_spill)) {
                to_spill = ctx.renames[block_idx][to_spill];
             }
 
@@ -1289,7 +1299,7 @@ spill_block(spill_ctx& ctx, unsigned block_idx)
                   !ctx.renames[block_idx].empty() || ctx.remat_used.size();
 
    for (auto it = current_spills.begin(); !process && it != current_spills.end(); ++it) {
-      if (ctx.next_use_distances_start[block_idx][it->first].first == block_idx)
+      if (ctx.next_use_distances_start[block_idx].at(it->first).first == block_idx)
          process = true;
    }
 



More information about the mesa-commit mailing list