aco/spill: add all live-in to merge block spill candidates
authorRhys Perry <pendingchaos02@gmail.com>
Wed, 30 Aug 2023 09:57:49 +0000 (10:57 +0100)
committerMarge Bot <emma+marge@anholt.net>
Wed, 30 Aug 2023 15:20:02 +0000 (15:20 +0000)
Previously, only already spilled live-in or phis were added to the spill
candidates. Because of branch definitions, this might not be enough.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9722
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24949>

src/amd/compiler/aco_spill.cpp

index 38e25db..a024d83 100644 (file)
@@ -660,7 +660,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
    }
 
    /* else: merge block */
-   std::set<Temp> partial_spills;
+   std::map<Temp, bool> partial_spills;
 
    /* keep variables spilled on all incoming paths */
    for (const std::pair<const Temp, std::pair<uint32_t, uint32_t>>& pair : next_use_distances) {
@@ -682,10 +682,11 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
             break;
          }
          if (!ctx.spills_exit[pred_idx].count(pair.first)) {
+            partial_spills.emplace(pair.first, false);
             if (!remat)
                spill = false;
          } else {
-            partial_spills.insert(pair.first);
+            partial_spills[pair.first] = true;
             /* it might be that on one incoming path, the variable has a different spill_id, but
              * add_couple_code() will take care of that. */
             spill_id = ctx.spills_exit[pred_idx][pair.first];
@@ -724,7 +725,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
          spilled_registers += phi->definitions[0].getTemp();
       } else {
          /* Phis might increase the register pressure. */
-         partial_spills.insert(phi->definitions[0].getTemp());
+         partial_spills[phi->definitions[0].getTemp()] = true;
       }
    }
 
@@ -734,17 +735,21 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx)
 
    while (reg_pressure.exceeds(ctx.target_pressure)) {
       assert(!partial_spills.empty());
-      std::set<Temp>::iterator it = partial_spills.begin();
+      std::map<Temp, bool>::iterator it = partial_spills.begin();
       Temp to_spill = Temp();
+      bool is_spilled_or_phi = false;
       unsigned distance = 0;
       RegType type = reg_pressure.vgpr > ctx.target_pressure.vgpr ? RegType::vgpr : RegType::sgpr;
 
       while (it != partial_spills.end()) {
-         assert(!ctx.spills_entry[block_idx].count(*it));
-
-         if (it->type() == type && next_use_distances.at(*it).second > distance) {
-            distance = next_use_distances.at(*it).second;
-            to_spill = *it;
+         assert(!ctx.spills_entry[block_idx].count(it->first));
+
+         if (it->first.type() == type && ((it->second && !is_spilled_or_phi) ||
+                                          (it->second == is_spilled_or_phi &&
+                                           next_use_distances.at(it->first).second > distance))) {
+            distance = next_use_distances.at(it->first).second;
+            to_spill = it->first;
+            is_spilled_or_phi = it->second;
          }
          ++it;
       }