From 427e5eeb02053745f4f1c7a655058ce3d804c206 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Sch=C3=BCrmann?= Date: Mon, 13 Jan 2020 15:13:19 +0100 Subject: [PATCH] aco: handle phi affinities transitively through parallelcopies This can coalesce most unnecessarily inserted parallelcopies from lowering to CSSA. v2: refactor loop a bit to make it more efficient and readable. Reviewed-by: Rhys Perry Part-of: --- src/amd/compiler/aco_register_allocation.cpp | 56 +++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/amd/compiler/aco_register_allocation.cpp b/src/amd/compiler/aco_register_allocation.cpp index a137a952d43..ec8838d97ed 100644 --- a/src/amd/compiler/aco_register_allocation.cpp +++ b/src/amd/compiler/aco_register_allocation.cpp @@ -1112,18 +1112,10 @@ void register_allocation(Program *program, std::vector> live_out_ std::vector>::reverse_iterator rit; for (rit = block.instructions.rbegin(); rit != block.instructions.rend(); ++rit) { aco_ptr& instr = *rit; - if (!is_phi(instr)) { - for (const Operand& op : instr->operands) { - if (op.isTemp()) - live.emplace(op.getTemp()); - } - if (instr->opcode == aco_opcode::p_create_vector) { - for (const Operand& op : instr->operands) { - if (op.isTemp() && op.getTemp().type() == instr->definitions[0].getTemp().type()) - vectors[op.tempId()] = instr.get(); - } - } - } else if (!instr->definitions[0].isKill() && !instr->definitions[0].isFixed()) { + if (is_phi(instr)) { + live.erase(instr->definitions[0].getTemp()); + if (instr->definitions[0].isKill() || instr->definitions[0].isFixed()) + continue; /* collect information about affinity-related temporaries */ std::vector affinity_related; /* affinity_related[0] is the last seen affinity-related temp */ @@ -1136,15 +1128,41 @@ void register_allocation(Program *program, std::vector> live_out_ } } phi_ressources.emplace_back(std::move(affinity_related)); + continue; } - /* erase from live */ - for (const Definition& def : instr->definitions) { - if (def.isTemp()) { - live.erase(def.getTemp()); - std::map::iterator it = temp_to_phi_ressources.find(def.tempId()); - if (it != temp_to_phi_ressources.end() && def.regClass() == phi_ressources[it->second][0].regClass()) - phi_ressources[it->second][0] = def.getTemp(); + /* add vector affinities */ + if (instr->opcode == aco_opcode::p_create_vector) { + for (const Operand& op : instr->operands) { + if (op.isTemp() && op.getTemp().type() == instr->definitions[0].getTemp().type()) + vectors[op.tempId()] = instr.get(); + } + } + + /* add operands to live variables */ + for (const Operand& op : instr->operands) { + if (op.isTemp()) + live.emplace(op.getTemp()); + } + + /* erase definitions from live */ + for (unsigned i = 0; i < instr->definitions.size(); i++) { + const Definition& def = instr->definitions[i]; + if (!def.isTemp()) + continue; + live.erase(def.getTemp()); + /* mark last-seen phi operand */ + std::map::iterator it = temp_to_phi_ressources.find(def.tempId()); + if (it != temp_to_phi_ressources.end() && def.regClass() == phi_ressources[it->second][0].regClass()) { + phi_ressources[it->second][0] = def.getTemp(); + /* try to coalesce phi affinities with parallelcopies */ + if (!def.isFixed() && instr->opcode == aco_opcode::p_parallelcopy) { + Operand op = instr->operands[i]; + if (op.isTemp() && op.isFirstKill() && def.regClass() == op.regClass()) { + phi_ressources[it->second].emplace_back(op.getTemp()); + temp_to_phi_ressources[op.tempId()] = it->second; + } + } } } } -- 2.30.2