diff --git a/src/amd/compiler/aco_lower_to_hw_instr.cpp b/src/amd/compiler/aco_lower_to_hw_instr.cpp index a008cc04d7d..c048aa406b8 100644 --- a/src/amd/compiler/aco_lower_to_hw_instr.cpp +++ b/src/amd/compiler/aco_lower_to_hw_instr.cpp @@ -2233,6 +2233,19 @@ lower_to_hw_instr(Program* program) handle_operands(copy_operations, &ctx, program->gfx_level, pi); break; } + case aco_opcode::p_start_linear_vgpr: { + if (instr->operands.empty()) + break; + + Definition def(instr->definitions[0].physReg(), + RegClass::get(RegType::vgpr, instr->definitions[0].bytes())); + + std::map copy_operations; + copy_operations[def.physReg()] = {instr->operands[0], def, + instr->operands[0].bytes()}; + handle_operands(copy_operations, &ctx, program->gfx_level, pi); + break; + } case aco_opcode::p_exit_early_if: { /* don't bother with an early exit near the end of the program */ if ((block->instructions.size() - 1 - instr_idx) <= 4 && diff --git a/src/amd/compiler/aco_opcodes.py b/src/amd/compiler/aco_opcodes.py index d656c0d7de9..5fab419fe70 100644 --- a/src/amd/compiler/aco_opcodes.py +++ b/src/amd/compiler/aco_opcodes.py @@ -305,7 +305,7 @@ opcode("p_barrier", format=Format.PSEUDO_BARRIER) opcode("p_spill") opcode("p_reload") -# start/end linear vgprs +# Start/end linear vgprs. p_start_linear_vgpr can take an operand to copy from, into the linear vgpr opcode("p_start_linear_vgpr") opcode("p_end_linear_vgpr") diff --git a/src/amd/compiler/aco_register_allocation.cpp b/src/amd/compiler/aco_register_allocation.cpp index 95de8000412..1e8625efa26 100644 --- a/src/amd/compiler/aco_register_allocation.cpp +++ b/src/amd/compiler/aco_register_allocation.cpp @@ -1890,7 +1890,8 @@ handle_pseudo(ra_ctx& ctx, const RegisterFile& reg_file, Instruction* instr) case aco_opcode::p_create_vector: case aco_opcode::p_split_vector: case aco_opcode::p_parallelcopy: - case aco_opcode::p_wqm: break; + case aco_opcode::p_wqm: + case aco_opcode::p_start_linear_vgpr: break; default: return; } @@ -2943,7 +2944,9 @@ register_allocation(Program* program, std::vector& live_out_per_block, ra definition->setFixed(reg); } } else if (instr->opcode == aco_opcode::p_wqm || - instr->opcode == aco_opcode::p_parallelcopy) { + instr->opcode == aco_opcode::p_parallelcopy || + (instr->opcode == aco_opcode::p_start_linear_vgpr && + !instr->operands.empty())) { PhysReg reg = instr->operands[i].physReg(); if (instr->operands[i].isTemp() && instr->operands[i].getTemp().type() == definition->getTemp().type() && diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index b95e60be0b3..7a21f90b00f 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -585,6 +585,15 @@ validate_ir(Program* program) instr->operands[i].isUndefined(), "Operands of p_dual_src_export_gfx11 must be VGPRs or undef", instr.get()); } + } else if (instr->opcode == aco_opcode::p_start_linear_vgpr) { + check(instr->definitions.size() == 1, "Must have one definition", instr.get()); + check(instr->operands.size() <= 1, "Must have one or zero operands", instr.get()); + if (!instr->definitions.empty()) + check(instr->definitions[0].regClass().is_linear_vgpr(), + "Definition must be linear VGPR", instr.get()); + if (!instr->definitions.empty() && !instr->operands.empty()) + check(instr->definitions[0].bytes() == instr->operands[0].bytes(), + "Operand size must match definition", instr.get()); } break; }