2019-09-17 13:22:17 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2018 Valve Corporation
|
|
|
|
|
*
|
2024-04-08 09:02:30 +02:00
|
|
|
* SPDX-License-Identifier: MIT
|
2019-09-17 13:22:17 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "aco_ir.h"
|
|
|
|
|
|
2021-06-09 15:40:03 +02:00
|
|
|
#include <vector>
|
2019-09-17 13:22:17 +02:00
|
|
|
|
|
|
|
|
namespace aco {
|
|
|
|
|
namespace {
|
|
|
|
|
|
2025-02-12 12:37:34 +01:00
|
|
|
struct phi_info {
|
|
|
|
|
std::vector<std::pair<Definition, Operand>> copies;
|
|
|
|
|
PhysReg scratch_sgpr;
|
|
|
|
|
bool needs_scratch_reg = false;
|
2021-05-13 20:43:28 +02:00
|
|
|
};
|
2019-09-17 13:22:17 +02:00
|
|
|
|
|
|
|
|
struct ssa_elimination_ctx {
|
2025-02-12 12:25:46 +01:00
|
|
|
/* The outer vectors should be indexed by block index.
|
|
|
|
|
* The inner vectors store phi information for each block.
|
|
|
|
|
*/
|
|
|
|
|
std::vector<phi_info> phi_infos;
|
2019-09-17 13:22:17 +02:00
|
|
|
Program* program;
|
|
|
|
|
|
2025-02-12 12:25:46 +01:00
|
|
|
ssa_elimination_ctx(Program* program_) : phi_infos(program_->blocks.size()), program(program_) {}
|
2019-09-17 13:22:17 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
collect_phi_info(ssa_elimination_ctx& ctx)
|
|
|
|
|
{
|
|
|
|
|
for (Block& block : ctx.program->blocks) {
|
|
|
|
|
for (aco_ptr<Instruction>& phi : block.instructions) {
|
|
|
|
|
if (phi->opcode != aco_opcode::p_phi && phi->opcode != aco_opcode::p_linear_phi)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < phi->operands.size(); i++) {
|
|
|
|
|
if (phi->operands[i].isUndefined())
|
|
|
|
|
continue;
|
2021-02-04 15:55:23 +01:00
|
|
|
if (phi->operands[i].physReg() == phi->definitions[0].physReg())
|
2019-09-17 13:22:17 +02:00
|
|
|
continue;
|
|
|
|
|
|
2019-11-27 11:04:47 +01:00
|
|
|
assert(phi->definitions[0].size() == phi->operands[i].size());
|
2021-05-13 20:43:28 +02:00
|
|
|
|
2023-12-18 11:21:08 +01:00
|
|
|
Block::edge_vec& preds =
|
2021-05-13 20:43:28 +02:00
|
|
|
phi->opcode == aco_opcode::p_phi ? block.logical_preds : block.linear_preds;
|
2025-02-12 12:25:46 +01:00
|
|
|
auto& info = ctx.phi_infos[preds[i]];
|
2025-02-12 12:37:34 +01:00
|
|
|
info.copies.emplace_back(phi->definitions[0], phi->operands[i]);
|
|
|
|
|
if (phi->pseudo().needs_scratch_reg) {
|
|
|
|
|
info.needs_scratch_reg = true;
|
|
|
|
|
info.scratch_sgpr = phi->pseudo().scratch_sgpr;
|
|
|
|
|
}
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
insert_parallelcopies(ssa_elimination_ctx& ctx)
|
|
|
|
|
{
|
2025-02-12 12:25:46 +01:00
|
|
|
/* insert parallelcopies for the phis at the end of blocks just before the branch */
|
2021-05-13 20:43:28 +02:00
|
|
|
for (unsigned block_idx = 0; block_idx < ctx.program->blocks.size(); ++block_idx) {
|
2025-02-12 12:25:46 +01:00
|
|
|
auto& phi_info = ctx.phi_infos[block_idx];
|
|
|
|
|
if (phi_info.copies.empty())
|
2021-05-13 20:43:28 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
Block& block = ctx.program->blocks[block_idx];
|
2024-03-25 15:55:27 +01:00
|
|
|
aco_ptr<Instruction> pc{create_instruction(aco_opcode::p_parallelcopy, Format::PSEUDO,
|
2025-02-12 12:25:46 +01:00
|
|
|
phi_info.copies.size(), phi_info.copies.size())};
|
2019-09-17 13:22:17 +02:00
|
|
|
unsigned i = 0;
|
2025-02-12 12:25:46 +01:00
|
|
|
for (auto& pair : phi_info.copies) {
|
2025-02-12 12:37:34 +01:00
|
|
|
pc->definitions[i] = pair.first;
|
|
|
|
|
pc->operands[i] = pair.second;
|
2019-09-17 13:22:17 +02:00
|
|
|
i++;
|
|
|
|
|
}
|
2025-02-12 12:25:46 +01:00
|
|
|
pc->pseudo().scratch_sgpr = phi_info.scratch_sgpr;
|
|
|
|
|
pc->pseudo().needs_scratch_reg = phi_info.needs_scratch_reg;
|
2024-11-07 10:39:49 +01:00
|
|
|
auto it = std::prev(block.instructions.end());
|
2019-09-17 13:22:17 +02:00
|
|
|
block.instructions.insert(it, std::move(pc));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} /* end namespace */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ssa_elimination(Program* program)
|
|
|
|
|
{
|
|
|
|
|
ssa_elimination_ctx ctx(program);
|
|
|
|
|
|
|
|
|
|
/* Collect information about every phi-instruction */
|
|
|
|
|
collect_phi_info(ctx);
|
|
|
|
|
|
|
|
|
|
/* insert parallelcopies from SSA elimination */
|
|
|
|
|
insert_parallelcopies(ctx);
|
|
|
|
|
}
|
|
|
|
|
} // namespace aco
|