diff --git a/src/amd/compiler/aco_spill.cpp b/src/amd/compiler/aco_spill.cpp index bf4c8c9da0d..c52004c4a86 100644 --- a/src/amd/compiler/aco_spill.cpp +++ b/src/amd/compiler/aco_spill.cpp @@ -171,13 +171,14 @@ void next_uses_per_block(spill_ctx& ctx, unsigned block_idx, uint32_t& worklist) { Block* block = &ctx.program->blocks[block_idx]; - std::unordered_map> next_uses = - ctx.next_use_distances_end[block_idx]; + ctx.next_use_distances_start[block_idx] = ctx.next_use_distances_end[block_idx]; + auto& next_use_distances_start = ctx.next_use_distances_start[block_idx]; /* to compute the next use distance at the beginning of the block, we have to add the block's * size */ - for (std::unordered_map>::iterator it = next_uses.begin(); - it != next_uses.end(); ++it) + for (std::unordered_map>::iterator it = + next_use_distances_start.begin(); + it != next_use_distances_start.end(); ++it) it->second.second = it->second.second + block->instructions.size(); int idx = block->instructions.size() - 1; @@ -189,7 +190,7 @@ next_uses_per_block(spill_ctx& ctx, unsigned block_idx, uint32_t& worklist) for (const Definition& def : instr->definitions) { if (def.isTemp()) - next_uses.erase(def.getTemp()); + next_use_distances_start.erase(def.getTemp()); } for (const Operand& op : instr->operands) { @@ -199,24 +200,24 @@ next_uses_per_block(spill_ctx& ctx, unsigned block_idx, uint32_t& worklist) if (op.regClass().type() == RegType::vgpr && op.regClass().is_linear()) continue; if (op.isTemp()) - next_uses[op.getTemp()] = {block_idx, idx}; + next_use_distances_start[op.getTemp()] = {block_idx, idx}; } idx--; } - assert(block_idx != 0 || next_uses.empty()); - ctx.next_use_distances_start[block_idx] = next_uses; + assert(block_idx != 0 || next_use_distances_start.empty()); + std::unordered_set phi_defs; while (idx >= 0) { aco_ptr& instr = block->instructions[idx]; assert(instr->opcode == aco_opcode::p_linear_phi || instr->opcode == aco_opcode::p_phi); std::pair distance{block_idx, 0}; - auto it = instr->definitions[0].isTemp() ? next_uses.find(instr->definitions[0].getTemp()) - : next_uses.end(); - if (it != next_uses.end()) { + auto it = instr->definitions[0].isTemp() ? next_use_distances_start.find(instr->definitions[0].getTemp()) + : next_use_distances_start.end(); + if (it != next_use_distances_start.end() && + phi_defs.insert(instr->definitions[0].getTemp()).second) { distance = it->second; - next_uses.erase(it); } for (unsigned i = 0; i < instr->operands.size(); i++) { @@ -236,8 +237,11 @@ next_uses_per_block(spill_ctx& ctx, unsigned block_idx, uint32_t& worklist) } /* all remaining live vars must be live-out at the predecessors */ - for (std::pair>& pair : next_uses) { + for (std::pair>& pair : next_use_distances_start) { Temp temp = pair.first; + if (phi_defs.count(temp)) { + continue; + } uint32_t distance = pair.second.second; uint32_t dom = pair.second.first; std::vector& preds = temp.is_linear() ? block->linear_preds : block->logical_preds;