diff --git a/src/amd/compiler/aco_live_var_analysis.cpp b/src/amd/compiler/aco_live_var_analysis.cpp index bedc829a901..b91221839c6 100644 --- a/src/amd/compiler/aco_live_var_analysis.cpp +++ b/src/amd/compiler/aco_live_var_analysis.cpp @@ -50,6 +50,20 @@ get_live_changes(aco_ptr& instr) return changes; } +void +handle_def_fixed_to_op(RegisterDemand* demand, RegisterDemand demand_before, Instruction* instr, + int op_idx) +{ + /* Usually the register demand before an instruction would be considered part of the previous + * instruction, since it's not greater than the register demand for that previous instruction. + * Except, it can be greater in the case of an definition fixed to a non-killed operand: the RA + * needs to reserve space between the two instructions for the definition (containing a copy of + * the operand). + */ + demand_before += instr->definitions[0].getTemp(); + demand->update(demand_before); +} + RegisterDemand get_temp_registers(aco_ptr& instr) { @@ -67,6 +81,13 @@ get_temp_registers(aco_ptr& instr) temp_registers += op.getTemp(); } + int op_idx = get_op_fixed_to_def(instr.get()); + if (op_idx != -1 && !instr->operands[op_idx].isKill()) { + RegisterDemand before_instr; + before_instr -= get_live_changes(instr); + handle_def_fixed_to_op(&temp_registers, before_instr, instr.get(), op_idx); + } + return temp_registers; } @@ -183,6 +204,12 @@ process_live_temps_per_block(Program* program, live& lives, Block* block, unsign } } + int op_idx = get_op_fixed_to_def(insn); + if (op_idx != -1 && !insn->operands[op_idx].isKill()) { + RegisterDemand before_instr = new_demand; + handle_def_fixed_to_op(®ister_demand[idx], before_instr, insn, op_idx); + } + block_register_demand.update(register_demand[idx]); }