aco: stop using instructions in ra_ctx::vectors

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31346>
This commit is contained in:
Rhys Perry
2024-09-18 11:48:17 +01:00
committed by Marge Bot
parent 87c9690d8d
commit 1e60509135
+34 -21
View File
@@ -83,6 +83,20 @@ struct PhysRegIterator {
bool operator<(PhysRegIterator oth) const { return reg < oth.reg; }
};
struct vector_info {
vector_info() : is_weak(false), num_parts(0), parts(NULL) {}
vector_info(Instruction* instr, unsigned start = 0, bool weak = false)
: is_weak(weak), num_parts(instr->operands.size() - start),
parts(instr->operands.begin() + start)
{}
/* If true, then we should stop trying to form a vector if anything goes wrong. Useful for when
* the cost of failing does not introduce copies. */
bool is_weak;
uint32_t num_parts;
Operand* parts;
};
struct ra_ctx {
Program* program;
@@ -92,7 +106,7 @@ struct ra_ctx {
std::vector<aco::unordered_map<uint32_t, Temp>> renames;
std::vector<uint32_t> loop_header;
aco::unordered_map<uint32_t, Temp> orig_names;
aco::unordered_map<uint32_t, Instruction*> vectors;
aco::unordered_map<uint32_t, vector_info> vectors;
aco::unordered_map<uint32_t, Instruction*> split_vectors;
aco_ptr<Instruction> pseudo_dummy;
aco_ptr<Instruction> phi_dummy;
@@ -1522,11 +1536,11 @@ compact_relocate_vars(ra_ctx& ctx, const std::vector<IDAndRegClass>& vars,
}
bool
is_mimg_vaddr_intact(ra_ctx& ctx, const RegisterFile& reg_file, Instruction* instr)
is_vector_intact(ra_ctx& ctx, const RegisterFile& reg_file, const vector_info& vec_info)
{
PhysReg first{512};
for (unsigned i = 0; i < instr->operands.size() - 3u; i++) {
Operand op = instr->operands[i + 3];
for (unsigned i = 0; i < vec_info.num_parts; i++) {
Operand op = vec_info.parts[i];
if (ctx.assignments[op.tempId()].assigned) {
PhysReg reg = ctx.assignments[op.tempId()].reg;
@@ -1534,7 +1548,7 @@ is_mimg_vaddr_intact(ra_ctx& ctx, const RegisterFile& reg_file, Instruction* ins
if (first.reg() == 512) {
PhysRegInterval bounds = get_reg_bounds(ctx, RegType::vgpr, false);
first = reg.advance(i * -4);
PhysRegInterval vec = PhysRegInterval{first, instr->operands.size() - 3u};
PhysRegInterval vec = PhysRegInterval{first, vec_info.num_parts};
if (!bounds.contains(vec)) /* not enough space for other operands */
return false;
} else {
@@ -1557,25 +1571,24 @@ std::optional<PhysReg>
get_reg_vector(ra_ctx& ctx, const RegisterFile& reg_file, Temp temp, aco_ptr<Instruction>& instr,
int operand)
{
Instruction* vec = ctx.vectors[temp.id()];
unsigned first_operand = vec->format == Format::MIMG ? 3 : 0;
unsigned our_offset = 0;
for (unsigned i = first_operand; i < vec->operands.size(); i++) {
Operand& op = vec->operands[i];
if (op.isTemp() && op.tempId() == temp.id())
break;
else
our_offset += op.bytes();
}
const vector_info& vec = ctx.vectors[temp.id()];
if (!vec.is_weak || is_vector_intact(ctx, reg_file, vec)) {
unsigned our_offset = 0;
for (unsigned i = 0; i < vec.num_parts; i++) {
const Operand& op = vec.parts[i];
if (op.isTemp() && op.tempId() == temp.id())
break;
else
our_offset += op.bytes();
}
if (vec->format != Format::MIMG || is_mimg_vaddr_intact(ctx, reg_file, vec)) {
unsigned their_offset = 0;
/* check for every operand of the vector
* - whether the operand is assigned and
* - we can use the register relative to that operand
*/
for (unsigned i = first_operand; i < vec->operands.size(); i++) {
Operand& op = vec->operands[i];
for (unsigned i = 0; i < vec.num_parts; i++) {
const Operand& op = vec.parts[i];
if (op.isTemp() && op.tempId() != temp.id() && op.getTemp().type() == temp.type() &&
ctx.assignments[op.tempId()].assigned) {
PhysReg reg = ctx.assignments[op.tempId()].reg;
@@ -1584,7 +1597,7 @@ get_reg_vector(ra_ctx& ctx, const RegisterFile& reg_file, Temp temp, aco_ptr<Ins
return reg;
/* return if MIMG vaddr components don't remain vector-aligned */
if (vec->format == Format::MIMG)
if (vec.is_weak)
return {};
}
their_offset += op.bytes();
@@ -2642,12 +2655,12 @@ get_affinities(ra_ctx& ctx)
for (const Operand& op : instr->operands) {
if (op.isTemp() && op.isFirstKill() &&
op.getTemp().type() == instr->definitions[0].getTemp().type())
ctx.vectors[op.tempId()] = instr.get();
ctx.vectors[op.tempId()] = vector_info(instr.get());
}
} else if (instr->format == Format::MIMG && instr->operands.size() > 4 &&
!instr->mimg().strict_wqm && ctx.program->gfx_level < GFX12) {
for (unsigned i = 3; i < instr->operands.size(); i++)
ctx.vectors[instr->operands[i].tempId()] = instr.get();
ctx.vectors[instr->operands[i].tempId()] = vector_info(instr.get(), 3, true);
} else if (instr->opcode == aco_opcode::p_split_vector &&
instr->operands[0].isFirstKillBeforeDef()) {
ctx.split_vectors[instr->operands[0].tempId()] = instr.get();