From d7cb169819a8ff9e04047069bf1b7542e9a1b392 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Sch=C3=BCrmann?= Date: Tue, 22 Jun 2021 12:20:07 +0200 Subject: [PATCH] aco/ra: refactor affinities into assignment struct This lets us get rid of an unordered_map<>. No fossil-db changes. Reviewed-by: Rhys Perry Part-of: --- src/amd/compiler/aco_register_allocation.cpp | 80 ++++++++++++++++------------ 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/src/amd/compiler/aco_register_allocation.cpp b/src/amd/compiler/aco_register_allocation.cpp index b96ea9c..816159a 100644 --- a/src/amd/compiler/aco_register_allocation.cpp +++ b/src/amd/compiler/aco_register_allocation.cpp @@ -48,9 +48,16 @@ void add_subdword_definition(Program* program, aco_ptr& instr, Phys struct assignment { PhysReg reg; RegClass rc; - uint8_t assigned = 0; + bool assigned = false; + uint32_t affinity = 0; assignment() = default; assignment(PhysReg reg_, RegClass rc_) : reg(reg_), rc(rc_), assigned(-1) {} + void set(const Definition& def) + { + assigned = true; + reg = def.physReg(); + rc = def.regClass(); + } }; struct ra_ctx { @@ -61,7 +68,6 @@ struct ra_ctx { std::vector> renames; std::vector loop_header; std::unordered_map orig_names; - std::unordered_map affinities; std::unordered_map vectors; std::unordered_map split_vectors; aco_ptr pseudo_dummy; @@ -1522,22 +1528,25 @@ get_reg(ra_ctx& ctx, RegisterFile& reg_file, Temp temp, if (split_vec != ctx.split_vectors.end()) { unsigned offset = 0; for (Definition def : split_vec->second->definitions) { - auto affinity_it = ctx.affinities.find(def.tempId()); - if (affinity_it != ctx.affinities.end() && ctx.assignments[affinity_it->second].assigned) { - PhysReg reg = ctx.assignments[affinity_it->second].reg; - reg.reg_b -= offset; - if (get_reg_specified(ctx, reg_file, temp.regClass(), instr, reg)) - return reg; + if (ctx.assignments[def.tempId()].affinity) { + assignment& affinity = ctx.assignments[ctx.assignments[def.tempId()].affinity]; + if (affinity.assigned) { + PhysReg reg = affinity.reg; + reg.reg_b -= offset; + if (get_reg_specified(ctx, reg_file, temp.regClass(), instr, reg)) + return reg; + } } offset += def.bytes(); } } - if (ctx.affinities.find(temp.id()) != ctx.affinities.end() && - ctx.assignments[ctx.affinities[temp.id()]].assigned) { - PhysReg reg = ctx.assignments[ctx.affinities[temp.id()]].reg; - if (get_reg_specified(ctx, reg_file, temp.regClass(), instr, reg)) - return reg; + if (ctx.assignments[temp.id()].affinity) { + assignment& affinity = ctx.assignments[ctx.assignments[temp.id()].affinity]; + if (affinity.assigned) { + if (get_reg_specified(ctx, reg_file, temp.regClass(), instr, affinity.reg)) + return affinity.reg; + } } std::pair res; @@ -1947,16 +1956,16 @@ handle_live_in(ra_ctx& ctx, Temp val, Block* block) create_instruction(opcode, Format::PSEUDO, preds.size(), 1)}; new_val = ctx.program->allocateTmp(val.regClass()); phi->definitions[0] = Definition(new_val); + ctx.assignments.emplace_back(); + assert(ctx.assignments.size() == ctx.program->peekAllocationId()); for (unsigned i = 0; i < preds.size(); i++) { /* update the operands so that it uses the new affinity */ phi->operands[i] = Operand(ops[i]); assert(ctx.assignments[ops[i].id()].assigned); + assert(ops[i].regClass() == new_val.regClass()); phi->operands[i].setFixed(ctx.assignments[ops[i].id()].reg); - if (ops[i].regClass() == new_val.regClass()) - ctx.affinities[new_val.id()] = ops[i].id(); + ctx.assignments.back().affinity = ops[i].id(); } - ctx.assignments.emplace_back(); - assert(ctx.assignments.size() == ctx.program->peekAllocationId()); block->instructions.insert(block->instructions.begin(), std::move(phi)); } @@ -2234,7 +2243,7 @@ get_affinities(ra_ctx& ctx, std::vector& live_out_per_block) assert(vec.size() > 1); for (unsigned i = 1; i < vec.size(); i++) if (vec[i].id() != vec[0].id()) - ctx.affinities[vec[i].id()] = vec[0].id(); + ctx.assignments[vec[i].id()].affinity = vec[0].id(); } } @@ -2272,11 +2281,11 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra if (definition.isKill() || definition.isFixed()) continue; - if (ctx.affinities.find(definition.tempId()) != ctx.affinities.end() && - ctx.assignments[ctx.affinities[definition.tempId()]].assigned) { - assert(ctx.assignments[ctx.affinities[definition.tempId()]].rc == - definition.regClass()); - PhysReg reg = ctx.assignments[ctx.affinities[definition.tempId()]].reg; + if (ctx.assignments[definition.tempId()].affinity && + ctx.assignments[ctx.assignments[definition.tempId()].affinity].assigned) { + assignment& affinity = ctx.assignments[ctx.assignments[definition.tempId()].affinity]; + assert(affinity.rc == definition.regClass()); + PhysReg reg = affinity.reg; if (reg == scc) { /* only use scc if all operands are already placed there */ bool use_scc = @@ -2291,7 +2300,7 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra if (!register_file.test(reg, definition.bytes())) { definition.setFixed(reg); register_file.fill(definition); - ctx.assignments[definition.tempId()] = {definition.physReg(), definition.regClass()}; + ctx.assignments[definition.tempId()].set(definition); } } } @@ -2351,8 +2360,7 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra /* if so, just update that phi's register */ register_file.clear(prev_phi->definitions[0]); prev_phi->definitions[0].setFixed(pc.second.physReg()); - ctx.assignments[prev_phi->definitions[0].tempId()] = {pc.second.physReg(), - pc.second.regClass()}; + ctx.assignments[prev_phi->definitions[0].tempId()].set(pc.second); register_file.fill(prev_phi->definitions[0]); continue; } @@ -2387,13 +2395,13 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra } register_file.fill(definition); - ctx.assignments[definition.tempId()] = {definition.physReg(), definition.regClass()}; + ctx.assignments[definition.tempId()].set(definition); } /* update phi affinities */ for (const Operand& op : phi->operands) { if (op.isTemp() && op.regClass() == phi->definitions[0].regClass()) - ctx.affinities[op.tempId()] = definition.tempId(); + ctx.assignments[op.tempId()].affinity = definition.tempId(); } instructions.emplace_back(std::move(*instr_it)); @@ -2490,10 +2498,14 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra instr->operands[0].physReg().byte() == 0 && instr->operands[1].physReg().byte() == 0 && instr->operands[2].physReg().byte() == 0) { unsigned def_id = instr->definitions[0].tempId(); - auto it = ctx.affinities.find(def_id); - if (it == ctx.affinities.end() || !ctx.assignments[it->second].assigned || - instr->operands[2].physReg() == ctx.assignments[it->second].reg || - register_file.test(ctx.assignments[it->second].reg, instr->operands[2].bytes())) { + bool use_vop2 = true; + if (ctx.assignments[def_id].affinity) { + assignment& affinity = ctx.assignments[ctx.assignments[def_id].affinity]; + if (affinity.assigned && affinity.reg != instr->operands[2].physReg() && + !register_file.test(affinity.reg, instr->operands[2].bytes())) + use_vop2 = false; + } + if (use_vop2) { instr->format = Format::VOP2; switch (instr->opcode) { case aco_opcode::v_mad_f32: instr->opcode = aco_opcode::v_mac_f32; break; @@ -2565,7 +2577,7 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra if (!definition.isTemp()) continue; - ctx.assignments[definition.tempId()] = {definition.physReg(), definition.regClass()}; + ctx.assignments[definition.tempId()].set(definition); register_file.fill(definition); } @@ -2629,7 +2641,7 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra ((definition->getTemp().type() == RegType::vgpr && definition->physReg() >= 256) || (definition->getTemp().type() != RegType::vgpr && definition->physReg() < 256))); ctx.defs_done.set(i); - ctx.assignments[definition->tempId()] = {definition->physReg(), definition->regClass()}; + ctx.assignments[definition->tempId()].set(*definition); register_file.fill(*definition); } -- 2.7.4