diff --git a/src/amd/compiler/aco_spill.cpp b/src/amd/compiler/aco_spill.cpp index 38e25dba3df..a024d8384d2 100644 --- a/src/amd/compiler/aco_spill.cpp +++ b/src/amd/compiler/aco_spill.cpp @@ -660,7 +660,7 @@ init_live_in_vars(spill_ctx& ctx, Block* block, unsigned block_idx) } /* else: merge block */ - std::set partial_spills; + std::map partial_spills; /* keep variables spilled on all incoming paths */ for (const std::pair>& 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::iterator it = partial_spills.begin(); + std::map::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)); + assert(!ctx.spills_entry[block_idx].count(it->first)); - if (it->type() == type && next_use_distances.at(*it).second > distance) { - distance = next_use_distances.at(*it).second; - to_spill = *it; + 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; }