diff options
author | Daniel Schürmann <[email protected]> | 2020-01-13 15:13:19 +0100 |
---|---|---|
committer | Daniel Schürmann <[email protected]> | 2020-01-16 16:01:59 +0100 |
commit | 427e5eeb02053745f4f1c7a655058ce3d804c206 (patch) | |
tree | 93b97c2438387e3d4d7b3bb06a0cae936de2ea1e | |
parent | d098024c40ee6bd12804833b71a554380df2d51d (diff) |
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 <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3385>
-rw-r--r-- | src/amd/compiler/aco_register_allocation.cpp | 56 |
1 files 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<std::set<Temp>> live_out_ std::vector<aco_ptr<Instruction>>::reverse_iterator rit; for (rit = block.instructions.rbegin(); rit != block.instructions.rend(); ++rit) { aco_ptr<Instruction>& 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<Temp> affinity_related; /* affinity_related[0] is the last seen affinity-related temp */ @@ -1136,15 +1128,41 @@ void register_allocation(Program *program, std::vector<std::set<Temp>> 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<unsigned, unsigned>::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<unsigned, unsigned>::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; + } + } } } } |