aco: unify different SALU types into single struct SALU_instruction

This removes
- SOP1_instruction
- SOP2_instruction
- SOPC_instruction
- SOPK_instruction
- SOPP_instruction

and their corresponding methods.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28370>
This commit is contained in:
Daniel Schürmann
2024-03-19 15:46:56 +01:00
committed by Marge Bot
parent 5d265257a0
commit 1187189235
18 changed files with 89 additions and 163 deletions

View File

@@ -44,7 +44,7 @@ struct constaddr_info {
struct asm_context { struct asm_context {
Program* program; Program* program;
enum amd_gfx_level gfx_level; enum amd_gfx_level gfx_level;
std::vector<std::pair<int, SOPP_instruction*>> branches; std::vector<std::pair<int, SALU_instruction*>> branches;
std::map<unsigned, constaddr_info> constaddrs; std::map<unsigned, constaddr_info> constaddrs;
std::map<unsigned, constaddr_info> resumeaddrs; std::map<unsigned, constaddr_info> resumeaddrs;
std::vector<struct aco_symbol>* symbols; std::vector<struct aco_symbol>* symbols;
@@ -155,7 +155,8 @@ void
emit_sopk_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction* instr) emit_sopk_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction* instr)
{ {
uint32_t opcode = ctx.opcode[(int)instr->opcode]; uint32_t opcode = ctx.opcode[(int)instr->opcode];
SOPK_instruction& sopk = instr->sopk(); SALU_instruction& sopk = instr->salu();
assert(sopk.imm <= UINT16_MAX);
if (instr->opcode == aco_opcode::s_subvector_loop_begin) { if (instr->opcode == aco_opcode::s_subvector_loop_begin) {
assert(ctx.gfx_level >= GFX10); assert(ctx.gfx_level >= GFX10);
@@ -211,7 +212,7 @@ emit_sopp_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction*
bool force_imm = false) bool force_imm = false)
{ {
uint32_t opcode = ctx.opcode[(int)instr->opcode]; uint32_t opcode = ctx.opcode[(int)instr->opcode];
SOPP_instruction& sopp = instr->sopp(); SALU_instruction& sopp = instr->salu();
uint32_t encoding = (0b101111111 << 23); uint32_t encoding = (0b101111111 << 23);
encoding |= opcode << 16; encoding |= opcode << 16;
@@ -1316,7 +1317,7 @@ fix_branches_gfx10(asm_context& ctx, std::vector<uint32_t>& out)
} }
void void
emit_long_jump(asm_context& ctx, SOPP_instruction* branch, bool backwards, emit_long_jump(asm_context& ctx, SALU_instruction* branch, bool backwards,
std::vector<uint32_t>& out) std::vector<uint32_t>& out)
{ {
Builder bld(ctx.program); Builder bld(ctx.program);
@@ -1384,7 +1385,7 @@ fix_branches(asm_context& ctx, std::vector<uint32_t>& out)
if (ctx.gfx_level == GFX10) if (ctx.gfx_level == GFX10)
fix_branches_gfx10(ctx, out); fix_branches_gfx10(ctx, out);
for (std::pair<int, SOPP_instruction*>& branch : ctx.branches) { for (std::pair<int, SALU_instruction*>& branch : ctx.branches) {
int offset = (int)ctx.program->blocks[branch.second->imm].offset - branch.first - 1; int offset = (int)ctx.program->blocks[branch.second->imm].offset - branch.first - 1;
if ((offset < INT16_MIN || offset > INT16_MAX) && !branch.second->pass_flags) { if ((offset < INT16_MIN || offset > INT16_MAX) && !branch.second->pass_flags) {
std::vector<uint32_t> long_jump; std::vector<uint32_t> long_jump;
@@ -1461,7 +1462,7 @@ align_block(asm_context& ctx, std::vector<uint32_t>& code, Block& block)
insert_code(ctx, code, loop_header->offset, nops.size(), nops.data()); insert_code(ctx, code, loop_header->offset, nops.size(), nops.data());
/* Change prefetch mode back to default (0x3). */ /* Change prefetch mode back to default (0x3). */
instr->sopp().imm = 0x3; instr->salu().imm = 0x3;
emit_instruction(ctx, code, instr.get()); emit_instruction(ctx, code, instr.get());
} }

View File

@@ -566,11 +566,11 @@ public:
<% <%
import itertools import itertools
formats = [("pseudo", [Format.PSEUDO], 'Pseudo_instruction', list(itertools.product(range(5), range(6))) + [(8, 1), (1, 8), (2, 6), (3, 6), (1, 6)]), formats = [("pseudo", [Format.PSEUDO], 'Pseudo_instruction', list(itertools.product(range(5), range(6))) + [(8, 1), (1, 8), (2, 6), (3, 6), (1, 6)]),
("sop1", [Format.SOP1], 'SOP1_instruction', [(0, 1), (1, 0), (1, 1), (2, 1), (3, 2)]), ("sop1", [Format.SOP1], 'SALU_instruction', [(0, 1), (1, 0), (1, 1), (2, 1), (3, 2)]),
("sop2", [Format.SOP2], 'SOP2_instruction', itertools.product([1, 2], [2, 3])), ("sop2", [Format.SOP2], 'SALU_instruction', itertools.product([1, 2], [2, 3])),
("sopk", [Format.SOPK], 'SOPK_instruction', itertools.product([0, 1, 2], [0, 1])), ("sopk", [Format.SOPK], 'SALU_instruction', itertools.product([0, 1, 2], [0, 1])),
("sopp", [Format.SOPP], 'SOPP_instruction', itertools.product([0, 1], [0, 1])), ("sopp", [Format.SOPP], 'SALU_instruction', itertools.product([0, 1], [0, 1])),
("sopc", [Format.SOPC], 'SOPC_instruction', [(1, 2)]), ("sopc", [Format.SOPC], 'SALU_instruction', [(1, 2)]),
("smem", [Format.SMEM], 'SMEM_instruction', [(0, 4), (0, 3), (1, 0), (1, 3), (1, 2), (1, 1), (0, 0)]), ("smem", [Format.SMEM], 'SMEM_instruction', [(0, 4), (0, 3), (1, 0), (1, 3), (1, 2), (1, 1), (0, 0)]),
("ds", [Format.DS], 'DS_instruction', [(1, 1), (1, 2), (1, 3), (0, 3), (0, 4)]), ("ds", [Format.DS], 'DS_instruction', [(1, 1), (1, 2), (1, 3), (0, 3), (0, 4)]),
("ldsdir", [Format.LDSDIR], 'LDSDIR_instruction', [(1, 1)]), ("ldsdir", [Format.LDSDIR], 'LDSDIR_instruction', [(1, 1)]),

View File

@@ -313,7 +313,7 @@ int
get_wait_states(aco_ptr<Instruction>& instr) get_wait_states(aco_ptr<Instruction>& instr)
{ {
if (instr->opcode == aco_opcode::s_nop) if (instr->opcode == aco_opcode::s_nop)
return instr->sopp().imm + 1; return instr->salu().imm + 1;
else if (instr->opcode == aco_opcode::p_constaddr) else if (instr->opcode == aco_opcode::p_constaddr)
return 3; /* lowered to 3 instructions in the assembler */ return 3; /* lowered to 3 instructions in the assembler */
else else
@@ -611,8 +611,8 @@ handle_instruction_gfx6(State& state, NOP_ctx_gfx6& ctx, aco_ptr<Instruction>& i
// TODO: try to schedule the NOP-causing instruction up to reduce the number of stall cycles // TODO: try to schedule the NOP-causing instruction up to reduce the number of stall cycles
if (NOPs) { if (NOPs) {
/* create NOP */ /* create NOP */
aco_ptr<SOPP_instruction> nop{ aco_ptr<SALU_instruction> nop{
create_instruction<SOPP_instruction>(aco_opcode::s_nop, Format::SOPP, 0, 0)}; create_instruction<SALU_instruction>(aco_opcode::s_nop, Format::SOPP, 0, 0)};
nop->imm = NOPs - 1; nop->imm = NOPs - 1;
new_instructions.emplace_back(std::move(nop)); new_instructions.emplace_back(std::move(nop));
} }
@@ -668,7 +668,7 @@ handle_instruction_gfx6(State& state, NOP_ctx_gfx6& ctx, aco_ptr<Instruction>& i
} }
} else if (instr->opcode == aco_opcode::s_setreg_b32 || } else if (instr->opcode == aco_opcode::s_setreg_b32 ||
instr->opcode == aco_opcode::s_setreg_imm32_b32) { instr->opcode == aco_opcode::s_setreg_imm32_b32) {
SOPK_instruction& sopk = instr->sopk(); SALU_instruction& sopk = instr->salu();
unsigned offset = (sopk.imm >> 6) & 0x1f; unsigned offset = (sopk.imm >> 6) & 0x1f;
unsigned size = ((sopk.imm >> 11) & 0x1f) + 1; unsigned size = ((sopk.imm >> 11) & 0x1f) + 1;
unsigned reg = sopk.imm & 0x3f; unsigned reg = sopk.imm & 0x3f;
@@ -900,8 +900,8 @@ handle_instruction_gfx10(State& state, NOP_ctx_gfx10& ctx, aco_ptr<Instruction>&
vm_vsrc = 0; vm_vsrc = 0;
sa_sdst = 0; sa_sdst = 0;
} else if (instr->opcode == aco_opcode::s_waitcnt_depctr) { } else if (instr->opcode == aco_opcode::s_waitcnt_depctr) {
vm_vsrc = (instr->sopp().imm >> 2) & 0x7; vm_vsrc = (instr->salu().imm >> 2) & 0x7;
sa_sdst = instr->sopp().imm & 0x1; sa_sdst = instr->salu().imm & 0x1;
} }
/* VMEMtoScalarWriteHazard /* VMEMtoScalarWriteHazard
@@ -918,12 +918,12 @@ handle_instruction_gfx10(State& state, NOP_ctx_gfx10& ctx, aco_ptr<Instruction>&
mark_read_regs_exec(state, instr, ctx.sgprs_read_by_DS); mark_read_regs_exec(state, instr, ctx.sgprs_read_by_DS);
} else if (instr->isSALU() || instr->isSMEM()) { } else if (instr->isSALU() || instr->isSMEM()) {
if (instr->opcode == aco_opcode::s_waitcnt) { if (instr->opcode == aco_opcode::s_waitcnt) {
wait_imm imm(state.program->gfx_level, instr->sopp().imm); wait_imm imm(state.program->gfx_level, instr->salu().imm);
if (imm.vm == 0) if (imm.vm == 0)
ctx.sgprs_read_by_VMEM.reset(); ctx.sgprs_read_by_VMEM.reset();
if (imm.lgkm == 0) if (imm.lgkm == 0)
ctx.sgprs_read_by_DS.reset(); ctx.sgprs_read_by_DS.reset();
} else if (instr->opcode == aco_opcode::s_waitcnt_vscnt && instr->sopk().imm == 0) { } else if (instr->opcode == aco_opcode::s_waitcnt_vscnt && instr->salu().imm == 0) {
ctx.sgprs_read_by_VMEM_store.reset(); ctx.sgprs_read_by_VMEM_store.reset();
} else if (vm_vsrc == 0) { } else if (vm_vsrc == 0) {
ctx.sgprs_read_by_VMEM.reset(); ctx.sgprs_read_by_VMEM.reset();
@@ -1002,11 +1002,11 @@ handle_instruction_gfx10(State& state, NOP_ctx_gfx10& ctx, aco_ptr<Instruction>&
} else if (instr->isSALU()) { } else if (instr->isSALU()) {
/* Reducing lgkmcnt count to 0 always mitigates the hazard. */ /* Reducing lgkmcnt count to 0 always mitigates the hazard. */
if (instr->opcode == aco_opcode::s_waitcnt_lgkmcnt) { if (instr->opcode == aco_opcode::s_waitcnt_lgkmcnt) {
const SOPK_instruction& sopk = instr->sopk(); const SALU_instruction& sopk = instr->salu();
if (sopk.imm == 0 && sopk.operands[0].physReg() == sgpr_null) if (sopk.imm == 0 && sopk.operands[0].physReg() == sgpr_null)
ctx.sgprs_read_by_SMEM.reset(); ctx.sgprs_read_by_SMEM.reset();
} else if (instr->opcode == aco_opcode::s_waitcnt) { } else if (instr->opcode == aco_opcode::s_waitcnt) {
wait_imm imm(state.program->gfx_level, instr->sopp().imm); wait_imm imm(state.program->gfx_level, instr->salu().imm);
if (imm.lgkm == 0) if (imm.lgkm == 0)
ctx.sgprs_read_by_SMEM.reset(); ctx.sgprs_read_by_SMEM.reset();
} else if (instr->format != Format::SOPP && instr->definitions.size()) { } else if (instr->format != Format::SOPP && instr->definitions.size()) {
@@ -1034,7 +1034,7 @@ handle_instruction_gfx10(State& state, NOP_ctx_gfx10& ctx, aco_ptr<Instruction>&
ctx.has_VMEM = ctx.has_DS = false; ctx.has_VMEM = ctx.has_DS = false;
} else if (instr->opcode == aco_opcode::s_waitcnt_vscnt) { } else if (instr->opcode == aco_opcode::s_waitcnt_vscnt) {
/* Only s_waitcnt_vscnt can mitigate the hazard */ /* Only s_waitcnt_vscnt can mitigate the hazard */
const SOPK_instruction& sopk = instr->sopk(); const SALU_instruction& sopk = instr->salu();
if (sopk.operands[0].physReg() == sgpr_null && sopk.imm == 0) if (sopk.operands[0].physReg() == sgpr_null && sopk.imm == 0)
ctx.has_VMEM = ctx.has_branch_after_VMEM = ctx.has_DS = ctx.has_branch_after_DS = false; ctx.has_VMEM = ctx.has_branch_after_VMEM = ctx.has_DS = ctx.has_branch_after_DS = false;
} }
@@ -1145,7 +1145,7 @@ parse_vdst_wait(aco_ptr<Instruction>& instr)
else if (instr->isLDSDIR()) else if (instr->isLDSDIR())
return instr->ldsdir().wait_vdst; return instr->ldsdir().wait_vdst;
else if (instr->opcode == aco_opcode::s_waitcnt_depctr) else if (instr->opcode == aco_opcode::s_waitcnt_depctr)
return (instr->sopp().imm >> 12) & 0xf; return (instr->salu().imm >> 12) & 0xf;
else else
return 15; return 15;
} }
@@ -1417,8 +1417,8 @@ handle_instruction_gfx11(State& state, NOP_ctx_gfx11& ctx, aco_ptr<Instruction>&
sa_sdst = 0; sa_sdst = 0;
} else if (instr->opcode == aco_opcode::s_waitcnt_depctr) { } else if (instr->opcode == aco_opcode::s_waitcnt_depctr) {
/* va_vdst already obtained through parse_vdst_wait(). */ /* va_vdst already obtained through parse_vdst_wait(). */
vm_vsrc = (instr->sopp().imm >> 2) & 0x7; vm_vsrc = (instr->salu().imm >> 2) & 0x7;
sa_sdst = instr->sopp().imm & 0x1; sa_sdst = instr->salu().imm & 0x1;
} }
if (instr->isLDSDIR()) { if (instr->isLDSDIR()) {
@@ -1539,12 +1539,12 @@ handle_instruction_gfx11(State& state, NOP_ctx_gfx11& ctx, aco_ptr<Instruction>&
ctx.vgpr_used_by_vmem_store.reset(); ctx.vgpr_used_by_vmem_store.reset();
ctx.vgpr_used_by_ds.reset(); ctx.vgpr_used_by_ds.reset();
} else if (instr->opcode == aco_opcode::s_waitcnt) { } else if (instr->opcode == aco_opcode::s_waitcnt) {
wait_imm imm(GFX11, instr->sopp().imm); wait_imm imm(GFX11, instr->salu().imm);
if (imm.vm == 0) if (imm.vm == 0)
ctx.vgpr_used_by_vmem_load.reset(); ctx.vgpr_used_by_vmem_load.reset();
if (imm.lgkm == 0) if (imm.lgkm == 0)
ctx.vgpr_used_by_ds.reset(); ctx.vgpr_used_by_ds.reset();
} else if (instr->opcode == aco_opcode::s_waitcnt_vscnt && instr->sopk().imm == 0) { } else if (instr->opcode == aco_opcode::s_waitcnt_vscnt && instr->salu().imm == 0) {
ctx.vgpr_used_by_vmem_store.reset(); ctx.vgpr_used_by_vmem_store.reset();
} }
if (instr->isLDSDIR()) { if (instr->isLDSDIR()) {

View File

@@ -498,7 +498,7 @@ process_instructions(exec_ctx& ctx, Block* block, std::vector<aco_ptr<Instructio
Definition dst = instr->definitions[0]; Definition dst = instr->definitions[0];
assert(dst.size() == bld.lm.size()); assert(dst.size() == bld.lm.size());
if (state == Exact) { if (state == Exact) {
instr.reset(create_instruction<SOP1_instruction>(bld.w64or32(Builder::s_mov), instr.reset(create_instruction<SALU_instruction>(bld.w64or32(Builder::s_mov),
Format::SOP1, 1, 1)); Format::SOP1, 1, 1));
instr->operands[0] = Operand::zero(); instr->operands[0] = Operand::zero();
instr->definitions[0] = dst; instr->definitions[0] = dst;
@@ -506,7 +506,7 @@ process_instructions(exec_ctx& ctx, Block* block, std::vector<aco_ptr<Instructio
std::pair<Operand, uint8_t>& exact_mask = info.exec[0]; std::pair<Operand, uint8_t>& exact_mask = info.exec[0];
assert(exact_mask.second & mask_type_exact); assert(exact_mask.second & mask_type_exact);
instr.reset(create_instruction<SOP2_instruction>(bld.w64or32(Builder::s_andn2), instr.reset(create_instruction<SALU_instruction>(bld.w64or32(Builder::s_andn2),
Format::SOP2, 2, 2)); Format::SOP2, 2, 2));
instr->operands[0] = Operand(exec, bld.lm); /* current exec */ instr->operands[0] = Operand(exec, bld.lm); /* current exec */
instr->operands[1] = Operand(exact_mask.first); instr->operands[1] = Operand(exact_mask.first);

View File

@@ -448,10 +448,10 @@ bool
parse_wait_instr(wait_ctx& ctx, wait_imm& imm, Instruction* instr) parse_wait_instr(wait_ctx& ctx, wait_imm& imm, Instruction* instr)
{ {
if (instr->opcode == aco_opcode::s_waitcnt_vscnt && instr->operands[0].physReg() == sgpr_null) { if (instr->opcode == aco_opcode::s_waitcnt_vscnt && instr->operands[0].physReg() == sgpr_null) {
imm.vs = std::min<uint8_t>(imm.vs, instr->sopk().imm); imm.vs = std::min<uint8_t>(imm.vs, instr->salu().imm);
return true; return true;
} else if (instr->opcode == aco_opcode::s_waitcnt) { } else if (instr->opcode == aco_opcode::s_waitcnt) {
imm.combine(wait_imm(ctx.gfx_level, instr->sopp().imm)); imm.combine(wait_imm(ctx.gfx_level, instr->salu().imm));
return true; return true;
} }
return false; return false;
@@ -463,7 +463,7 @@ parse_delay_alu(wait_ctx& ctx, alu_delay_info& delay, Instruction* instr)
if (instr->opcode != aco_opcode::s_delay_alu) if (instr->opcode != aco_opcode::s_delay_alu)
return false; return false;
unsigned imm[2] = {instr->sopp().imm & 0xf, (instr->sopp().imm >> 7) & 0xf}; unsigned imm[2] = {instr->salu().imm & 0xf, (instr->salu().imm >> 7) & 0xf};
for (unsigned i = 0; i < 2; ++i) { for (unsigned i = 0; i < 2; ++i) {
alu_delay_wait wait = (alu_delay_wait)imm[i]; alu_delay_wait wait = (alu_delay_wait)imm[i];
if (wait >= alu_delay_wait::VALU_DEP_1 && wait <= alu_delay_wait::VALU_DEP_4) if (wait >= alu_delay_wait::VALU_DEP_1 && wait <= alu_delay_wait::VALU_DEP_4)
@@ -570,7 +570,7 @@ kill(wait_imm& imm, alu_delay_info& delay, Instruction* instr, wait_ctx& ctx,
if (ctx.program->has_pops_overlapped_waves_wait && if (ctx.program->has_pops_overlapped_waves_wait &&
(ctx.gfx_level >= GFX11 ? instr->isEXP() && instr->exp().done (ctx.gfx_level >= GFX11 ? instr->isEXP() && instr->exp().done
: (instr->opcode == aco_opcode::s_sendmsg && : (instr->opcode == aco_opcode::s_sendmsg &&
instr->sopp().imm == sendmsg_ordered_ps_done))) { instr->salu().imm == sendmsg_ordered_ps_done))) {
if (ctx.vm_nonzero) if (ctx.vm_nonzero)
imm.vm = 0; imm.vm = 0;
if (ctx.gfx_level >= GFX10 && ctx.vs_nonzero) if (ctx.gfx_level >= GFX10 && ctx.vs_nonzero)
@@ -993,16 +993,16 @@ emit_waitcnt(wait_ctx& ctx, std::vector<aco_ptr<Instruction>>& instructions, wai
{ {
if (imm.vs != wait_imm::unset_counter) { if (imm.vs != wait_imm::unset_counter) {
assert(ctx.gfx_level >= GFX10); assert(ctx.gfx_level >= GFX10);
SOPK_instruction* waitcnt_vs = SALU_instruction* waitcnt_vs =
create_instruction<SOPK_instruction>(aco_opcode::s_waitcnt_vscnt, Format::SOPK, 1, 0); create_instruction<SALU_instruction>(aco_opcode::s_waitcnt_vscnt, Format::SOPK, 1, 0);
waitcnt_vs->operands[0] = Operand(sgpr_null, s1); waitcnt_vs->operands[0] = Operand(sgpr_null, s1);
waitcnt_vs->imm = imm.vs; waitcnt_vs->imm = imm.vs;
instructions.emplace_back(waitcnt_vs); instructions.emplace_back(waitcnt_vs);
imm.vs = wait_imm::unset_counter; imm.vs = wait_imm::unset_counter;
} }
if (!imm.empty()) { if (!imm.empty()) {
SOPP_instruction* waitcnt = SALU_instruction* waitcnt =
create_instruction<SOPP_instruction>(aco_opcode::s_waitcnt, Format::SOPP, 0, 0); create_instruction<SALU_instruction>(aco_opcode::s_waitcnt, Format::SOPP, 0, 0);
waitcnt->imm = imm.pack(ctx.gfx_level); waitcnt->imm = imm.pack(ctx.gfx_level);
instructions.emplace_back(waitcnt); instructions.emplace_back(waitcnt);
} }
@@ -1030,8 +1030,8 @@ emit_delay_alu(wait_ctx& ctx, std::vector<aco_ptr<Instruction>>& instructions,
imm |= ((uint32_t)alu_delay_wait::SALU_CYCLE_1 + cycles - 1) << (imm ? 7 : 0); imm |= ((uint32_t)alu_delay_wait::SALU_CYCLE_1 + cycles - 1) << (imm ? 7 : 0);
} }
SOPP_instruction* inst = SALU_instruction* inst =
create_instruction<SOPP_instruction>(aco_opcode::s_delay_alu, Format::SOPP, 0, 0); create_instruction<SALU_instruction>(aco_opcode::s_delay_alu, Format::SOPP, 0, 0);
inst->imm = imm; inst->imm = imm;
inst->pass_flags = (delay.valu_cycles | (delay.trans_cycles << 16)); inst->pass_flags = (delay.valu_cycles | (delay.trans_cycles << 16));
instructions.emplace_back(inst); instructions.emplace_back(inst);
@@ -1176,7 +1176,7 @@ insert_wait_states(Program* program)
continue; continue;
} }
uint16_t imm = instr->sopp().imm; uint16_t imm = instr->salu().imm;
int skip = i - prev_delay_alu - 1; int skip = i - prev_delay_alu - 1;
if (imm >> 7 || prev_delay_alu < 0 || skip >= 6) { if (imm >> 7 || prev_delay_alu < 0 || skip >= 6) {
if (imm >> 7 == 0) if (imm >> 7 == 0)
@@ -1185,7 +1185,7 @@ insert_wait_states(Program* program)
continue; continue;
} }
block.instructions[prev_delay_alu]->sopp().imm |= (skip << 4) | (imm << 7); block.instructions[prev_delay_alu]->salu().imm |= (skip << 4) | (imm << 7);
prev_delay_alu = -1; prev_delay_alu = -1;
} }
block.instructions.resize(i); block.instructions.resize(i);

View File

@@ -823,8 +823,8 @@ void
emit_sop2_instruction(isel_context* ctx, nir_alu_instr* instr, aco_opcode op, Temp dst, emit_sop2_instruction(isel_context* ctx, nir_alu_instr* instr, aco_opcode op, Temp dst,
bool writes_scc, uint8_t uses_ub = 0) bool writes_scc, uint8_t uses_ub = 0)
{ {
aco_ptr<SOP2_instruction> sop2{ aco_ptr<SALU_instruction> sop2{
create_instruction<SOP2_instruction>(op, Format::SOP2, 2, writes_scc ? 2 : 1)}; create_instruction<SALU_instruction>(op, Format::SOP2, 2, writes_scc ? 2 : 1)};
sop2->operands[0] = Operand(get_alu_src(ctx, instr->src[0])); sop2->operands[0] = Operand(get_alu_src(ctx, instr->src[0]));
sop2->operands[1] = Operand(get_alu_src(ctx, instr->src[1])); sop2->operands[1] = Operand(get_alu_src(ctx, instr->src[1]));
sop2->definitions[0] = Definition(dst); sop2->definitions[0] = Definition(dst);

View File

@@ -231,7 +231,7 @@ get_sync_info(const Instruction* instr)
*/ */
if (instr->opcode == aco_opcode::p_pops_gfx9_overlapped_wave_wait_done || if (instr->opcode == aco_opcode::p_pops_gfx9_overlapped_wave_wait_done ||
(instr->opcode == aco_opcode::s_wait_event && (instr->opcode == aco_opcode::s_wait_event &&
!(instr->sopp().imm & wait_event_imm_dont_wait_export_ready))) { !(instr->salu().imm & wait_event_imm_dont_wait_export_ready))) {
return memory_sync_info(storage_buffer | storage_image, semantic_acquire, scope_queuefamily); return memory_sync_info(storage_buffer | storage_image, semantic_acquire, scope_queuefamily);
} else if (instr->opcode == aco_opcode::p_pops_gfx9_ordered_section_done) { } else if (instr->opcode == aco_opcode::p_pops_gfx9_ordered_section_done) {
return memory_sync_info(storage_buffer | storage_image, semantic_release, scope_queuefamily); return memory_sync_info(storage_buffer | storage_image, semantic_release, scope_queuefamily);

View File

@@ -939,11 +939,7 @@ private:
struct Block; struct Block;
struct Instruction; struct Instruction;
struct Pseudo_instruction; struct Pseudo_instruction;
struct SOP1_instruction; struct SALU_instruction;
struct SOP2_instruction;
struct SOPK_instruction;
struct SOPP_instruction;
struct SOPC_instruction;
struct SMEM_instruction; struct SMEM_instruction;
struct DS_instruction; struct DS_instruction;
struct LDSDIR_instruction; struct LDSDIR_instruction;
@@ -1002,61 +998,13 @@ struct Instruction {
return *(Pseudo_instruction*)this; return *(Pseudo_instruction*)this;
} }
constexpr bool isPseudo() const noexcept { return format == Format::PSEUDO; } constexpr bool isPseudo() const noexcept { return format == Format::PSEUDO; }
SOP1_instruction& sop1() noexcept
{
assert(isSOP1());
return *(SOP1_instruction*)this;
}
const SOP1_instruction& sop1() const noexcept
{
assert(isSOP1());
return *(SOP1_instruction*)this;
}
constexpr bool isSOP1() const noexcept { return format == Format::SOP1; } constexpr bool isSOP1() const noexcept { return format == Format::SOP1; }
SOP2_instruction& sop2() noexcept
{
assert(isSOP2());
return *(SOP2_instruction*)this;
}
const SOP2_instruction& sop2() const noexcept
{
assert(isSOP2());
return *(SOP2_instruction*)this;
}
constexpr bool isSOP2() const noexcept { return format == Format::SOP2; } constexpr bool isSOP2() const noexcept { return format == Format::SOP2; }
SOPK_instruction& sopk() noexcept
{
assert(isSOPK());
return *(SOPK_instruction*)this;
}
const SOPK_instruction& sopk() const noexcept
{
assert(isSOPK());
return *(SOPK_instruction*)this;
}
constexpr bool isSOPK() const noexcept { return format == Format::SOPK; } constexpr bool isSOPK() const noexcept { return format == Format::SOPK; }
SOPP_instruction& sopp() noexcept
{
assert(isSOPP());
return *(SOPP_instruction*)this;
}
const SOPP_instruction& sopp() const noexcept
{
assert(isSOPP());
return *(SOPP_instruction*)this;
}
constexpr bool isSOPP() const noexcept { return format == Format::SOPP; } constexpr bool isSOPP() const noexcept { return format == Format::SOPP; }
SOPC_instruction& sopc() noexcept
{
assert(isSOPC());
return *(SOPC_instruction*)this;
}
const SOPC_instruction& sopc() const noexcept
{
assert(isSOPC());
return *(SOPC_instruction*)this;
}
constexpr bool isSOPC() const noexcept { return format == Format::SOPC; } constexpr bool isSOPC() const noexcept { return format == Format::SOPC; }
SMEM_instruction& smem() noexcept SMEM_instruction& smem() noexcept
{ {
assert(isSMEM()); assert(isSMEM());
@@ -1295,6 +1243,16 @@ struct Instruction {
isVOPD(); isVOPD();
} }
SALU_instruction& salu() noexcept
{
assert(isSALU());
return *(SALU_instruction*)this;
}
const SALU_instruction& salu() const noexcept
{
assert(isSALU());
return *(SALU_instruction*)this;
}
constexpr bool isSALU() const noexcept constexpr bool isSALU() const noexcept
{ {
return isSOP1() || isSOP2() || isSOPC() || isSOPK() || isSOPP(); return isSOP1() || isSOP2() || isSOPC() || isSOPK() || isSOPP();
@@ -1307,32 +1265,13 @@ struct Instruction {
}; };
static_assert(sizeof(Instruction) == 16, "Unexpected padding"); static_assert(sizeof(Instruction) == 16, "Unexpected padding");
struct SOPK_instruction : public Instruction { struct SALU_instruction : public Instruction {
uint16_t imm; /* In case of SOPP branch instructions, contains the Block index,
uint16_t padding; * and otherwise, for SOPP and SOPK the 16-bit signed immediate.
};
static_assert(sizeof(SOPK_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
struct SOPP_instruction : public Instruction {
/* In case of branch instructions, contains the Block index,
* and otherwise, the 16-bit signed immediate.
*/ */
uint32_t imm; uint32_t imm;
}; };
static_assert(sizeof(SOPP_instruction) == sizeof(Instruction) + 4, "Unexpected padding"); static_assert(sizeof(SALU_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
struct SOPC_instruction : public Instruction {
uint32_t padding;
};
static_assert(sizeof(SOPC_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
struct SOP1_instruction : public Instruction {};
static_assert(sizeof(SOP1_instruction) == sizeof(Instruction) + 0, "Unexpected padding");
struct SOP2_instruction : public Instruction {
uint32_t padding;
};
static_assert(sizeof(SOP2_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
/** /**
* Scalar Memory Format: * Scalar Memory Format:

View File

@@ -2895,7 +2895,7 @@ lower_to_hw_instr(Program* program)
bool is_break_continue = bool is_break_continue =
program->blocks[i].kind & (block_kind_break | block_kind_continue); program->blocks[i].kind & (block_kind_break | block_kind_continue);
bool discard_early_exit = bool discard_early_exit =
program->blocks[inst->sopp().imm].kind & block_kind_discard_early_exit; program->blocks[inst->salu().imm].kind & block_kind_discard_early_exit;
if ((inst->opcode != aco_opcode::s_cbranch_scc0 && if ((inst->opcode != aco_opcode::s_cbranch_scc0 &&
inst->opcode != aco_opcode::s_cbranch_scc1) || inst->opcode != aco_opcode::s_cbranch_scc1) ||
(!discard_early_exit && !is_break_continue)) (!discard_early_exit && !is_break_continue))

View File

@@ -104,7 +104,7 @@ class Format(IntEnum):
def get_builder_fields(self): def get_builder_fields(self):
if self == Format.SOPK: if self == Format.SOPK:
return [('uint16_t', 'imm', None)] return [('uint32_t', 'imm', '0')]
elif self == Format.SOPP: elif self == Format.SOPP:
return [('uint32_t', 'imm', '0')] return [('uint32_t', 'imm', '0')]
elif self == Format.SMEM: elif self == Format.SMEM:

View File

@@ -103,8 +103,8 @@ struct InstrHash {
case Format::SMEM: return hash_murmur_32<SMEM_instruction>(instr); case Format::SMEM: return hash_murmur_32<SMEM_instruction>(instr);
case Format::VINTRP: return hash_murmur_32<VINTRP_instruction>(instr); case Format::VINTRP: return hash_murmur_32<VINTRP_instruction>(instr);
case Format::DS: return hash_murmur_32<DS_instruction>(instr); case Format::DS: return hash_murmur_32<DS_instruction>(instr);
case Format::SOPP: return hash_murmur_32<SOPP_instruction>(instr); case Format::SOPP: return hash_murmur_32<SALU_instruction>(instr);
case Format::SOPK: return hash_murmur_32<SOPK_instruction>(instr); case Format::SOPK: return hash_murmur_32<SALU_instruction>(instr);
case Format::EXP: return hash_murmur_32<Export_instruction>(instr); case Format::EXP: return hash_murmur_32<Export_instruction>(instr);
case Format::MUBUF: return hash_murmur_32<MUBUF_instruction>(instr); case Format::MUBUF: return hash_murmur_32<MUBUF_instruction>(instr);
case Format::MIMG: return hash_murmur_32<MIMG_instruction>(instr); case Format::MIMG: return hash_murmur_32<MIMG_instruction>(instr);
@@ -209,8 +209,8 @@ struct InstrPred {
case Format::SOPK: { case Format::SOPK: {
if (a->opcode == aco_opcode::s_getreg_b32) if (a->opcode == aco_opcode::s_getreg_b32)
return false; return false;
SOPK_instruction& aK = a->sopk(); SALU_instruction& aK = a->salu();
SOPK_instruction& bK = b->sopk(); SALU_instruction& bK = b->salu();
return aK.imm == bK.imm; return aK.imm == bK.imm;
} }
case Format::SMEM: { case Format::SMEM: {

View File

@@ -2468,7 +2468,7 @@ optimize_cmp_subgroup_invocation(opt_ctx& ctx, aco_ptr<Instruction>& instr)
const uint64_t mask = BITFIELD64_RANGE(first_bit, num_bits); const uint64_t mask = BITFIELD64_RANGE(first_bit, num_bits);
if (wave_size == 64 && mask > 0x7fffffff && mask != -1ull) { if (wave_size == 64 && mask > 0x7fffffff && mask != -1ull) {
/* Mask can't be represented as a 64-bit constant or literal, use s_bfm_b64. */ /* Mask can't be represented as a 64-bit constant or literal, use s_bfm_b64. */
cpy = create_instruction<SOP2_instruction>(aco_opcode::s_bfm_b64, Format::SOP2, 2, 1); cpy = create_instruction<SALU_instruction>(aco_opcode::s_bfm_b64, Format::SOP2, 2, 1);
cpy->operands[0] = Operand::c32(num_bits); cpy->operands[0] = Operand::c32(num_bits);
cpy->operands[1] = Operand::c32(first_bit); cpy->operands[1] = Operand::c32(first_bit);
} else { } else {
@@ -5244,10 +5244,8 @@ try_convert_sopc_to_sopk(aco_ptr<Instruction>& instr)
return; return;
} }
static_assert(sizeof(SOPK_instruction) <= sizeof(SOPC_instruction),
"Invalid direct instruction cast.");
instr->format = Format::SOPK; instr->format = Format::SOPK;
SOPK_instruction* instr_sopk = &instr->sopk(); SALU_instruction* instr_sopk = &instr->salu();
instr_sopk->imm = instr_sopk->operands[1].constantValue() & 0xffff; instr_sopk->imm = instr_sopk->operands[1].constantValue() & 0xffff;
instr_sopk->opcode = sopk_opcode_for_sopc(instr_sopk->opcode); instr_sopk->opcode = sopk_opcode_for_sopc(instr_sopk->opcode);

View File

@@ -412,10 +412,10 @@ try_optimize_scc_nocompare(pr_opt_ctx& ctx, aco_ptr<Instruction>& instr)
* This means that the original instruction will be eliminated. * This means that the original instruction will be eliminated.
*/ */
if (wr_instr->format == Format::SOP2) { if (wr_instr->format == Format::SOP2) {
instr.reset(create_instruction<SOP2_instruction>(pulled_opcode, Format::SOP2, 2, 2)); instr.reset(create_instruction<SALU_instruction>(pulled_opcode, Format::SOP2, 2, 2));
instr->operands[1] = wr_instr->operands[1]; instr->operands[1] = wr_instr->operands[1];
} else if (wr_instr->format == Format::SOP1) { } else if (wr_instr->format == Format::SOP1) {
instr.reset(create_instruction<SOP1_instruction>(pulled_opcode, Format::SOP1, 1, 2)); instr.reset(create_instruction<SALU_instruction>(pulled_opcode, Format::SOP1, 1, 2));
} }
instr->definitions[0] = wr_instr->definitions[0]; instr->definitions[0] = wr_instr->definitions[0];
instr->definitions[1] = scc_def; instr->definitions[1] = scc_def;
@@ -526,7 +526,7 @@ try_eliminate_scc_copy(pr_opt_ctx& ctx, aco_ptr<Instruction>& instr)
Idx producer_idx = {wr_idx.block, wr_instr->pass_flags}; Idx producer_idx = {wr_idx.block, wr_instr->pass_flags};
Instruction* producer_instr = ctx.get(producer_idx); Instruction* producer_instr = ctx.get(producer_idx);
if (!producer_instr) if (!producer_instr || !producer_instr->isSALU())
return; return;
/* Verify that the operands of the producer instruction haven't been overwritten. */ /* Verify that the operands of the producer instruction haven't been overwritten. */
@@ -544,20 +544,10 @@ try_eliminate_scc_copy(pr_opt_ctx& ctx, aco_ptr<Instruction>& instr)
} }
/* Duplicate the original producer of the SCC */ /* Duplicate the original producer of the SCC */
if (producer_instr->isSOP1()) instr.reset(create_instruction<SALU_instruction>(producer_instr->opcode, producer_instr->format,
instr.reset(create_instruction<SOP1_instruction>(producer_instr->opcode, Format::SOP1, producer_instr->operands.size(),
producer_instr->operands.size(), producer_instr->definitions.size()));
producer_instr->definitions.size())); instr->salu().imm = producer_instr->salu().imm;
else if (producer_instr->isSOP2())
instr.reset(create_instruction<SOP2_instruction>(producer_instr->opcode, Format::SOP2,
producer_instr->operands.size(),
producer_instr->definitions.size()));
else if (producer_instr->isSOPC())
instr.reset(create_instruction<SOPC_instruction>(producer_instr->opcode, Format::SOPC,
producer_instr->operands.size(),
producer_instr->definitions.size()));
else
return;
/* The copy is no longer needed. */ /* The copy is no longer needed. */
if (--ctx.uses[wr_instr->definitions[0].tempId()] == 0) if (--ctx.uses[wr_instr->definitions[0].tempId()] == 0)

View File

@@ -285,12 +285,12 @@ print_instr_format_specific(enum amd_gfx_level gfx_level, const Instruction* ins
{ {
switch (instr->format) { switch (instr->format) {
case Format::SOPK: { case Format::SOPK: {
const SOPK_instruction& sopk = instr->sopk(); const SALU_instruction& sopk = instr->salu();
fprintf(output, " imm:%d", sopk.imm & 0x8000 ? (sopk.imm - 65536) : sopk.imm); fprintf(output, " imm:%d", sopk.imm & 0x8000 ? (sopk.imm - 65536) : sopk.imm);
break; break;
} }
case Format::SOPP: { case Format::SOPP: {
uint16_t imm = instr->sopp().imm; uint16_t imm = instr->salu().imm;
switch (instr->opcode) { switch (instr->opcode) {
case aco_opcode::s_waitcnt: { case aco_opcode::s_waitcnt: {
wait_imm unpacked(gfx_level, imm); wait_imm unpacked(gfx_level, imm);
@@ -400,7 +400,7 @@ print_instr_format_specific(enum amd_gfx_level gfx_level, const Instruction* ins
} }
default: { default: {
if (instr_info.classes[(int)instr->opcode] == instr_class::branch) if (instr_info.classes[(int)instr->opcode] == instr_class::branch)
fprintf(output, " block:BB%d", instr->sopp().imm); fprintf(output, " block:BB%d", imm);
else if (imm) else if (imm)
fprintf(output, " imm:%u", imm); fprintf(output, " imm:%u", imm);
break; break;

View File

@@ -2848,10 +2848,8 @@ optimize_encoding_sopk(Program* program, ra_ctx& ctx, RegisterFile& register_fil
return; return;
} }
static_assert(sizeof(SOPK_instruction) <= sizeof(SOP2_instruction),
"Invalid direct instruction cast.");
instr->format = Format::SOPK; instr->format = Format::SOPK;
SOPK_instruction* instr_sopk = &instr->sopk(); SALU_instruction* instr_sopk = &instr->salu();
instr_sopk->imm = instr_sopk->operands[literal_idx].constantValue() & 0xffff; instr_sopk->imm = instr_sopk->operands[literal_idx].constantValue() & 0xffff;
if (literal_idx == 0) if (literal_idx == 0)
@@ -3319,7 +3317,7 @@ register_allocation(Program* program, live& live_vars, ra_test_policy policy)
aco_ptr<Instruction> mov; aco_ptr<Instruction> mov;
if (can_sgpr) if (can_sgpr)
mov.reset(create_instruction<SOP1_instruction>(aco_opcode::s_mov_b32, mov.reset(create_instruction<SALU_instruction>(aco_opcode::s_mov_b32,
Format::SOP1, 1, 1)); Format::SOP1, 1, 1));
else else
mov.reset(create_instruction<VALU_instruction>(aco_opcode::v_mov_b32, mov.reset(create_instruction<VALU_instruction>(aco_opcode::v_mov_b32,

View File

@@ -424,7 +424,7 @@ bool
is_done_sendmsg(amd_gfx_level gfx_level, const Instruction* instr) is_done_sendmsg(amd_gfx_level gfx_level, const Instruction* instr)
{ {
if (gfx_level <= GFX10_3 && instr->opcode == aco_opcode::s_sendmsg) if (gfx_level <= GFX10_3 && instr->opcode == aco_opcode::s_sendmsg)
return (instr->sopp().imm & sendmsg_id_mask) == sendmsg_gs_done; return (instr->salu().imm & sendmsg_id_mask) == sendmsg_gs_done;
return false; return false;
} }
@@ -577,7 +577,7 @@ perform_hazard_query(hazard_query* query, Instruction* instr, bool upwards)
if (upwards) { if (upwards) {
if (instr->opcode == aco_opcode::p_pops_gfx9_add_exiting_wave_id || if (instr->opcode == aco_opcode::p_pops_gfx9_add_exiting_wave_id ||
(instr->opcode == aco_opcode::s_wait_event && (instr->opcode == aco_opcode::s_wait_event &&
!(instr->sopp().imm & wait_event_imm_dont_wait_export_ready))) { !(instr->salu().imm & wait_event_imm_dont_wait_export_ready))) {
return hazard_fail_unreorderable; return hazard_fail_unreorderable;
} }
} else { } else {

View File

@@ -355,15 +355,15 @@ do_reload(spill_ctx& ctx, Temp tmp, Temp new_name, uint32_t spill_id)
res.reset(create_instruction<VALU_instruction>( res.reset(create_instruction<VALU_instruction>(
instr->opcode, instr->format, instr->operands.size(), instr->definitions.size())); instr->opcode, instr->format, instr->operands.size(), instr->definitions.size()));
} else if (instr->isSOP1()) { } else if (instr->isSOP1()) {
res.reset(create_instruction<SOP1_instruction>( res.reset(create_instruction<SALU_instruction>(
instr->opcode, instr->format, instr->operands.size(), instr->definitions.size())); instr->opcode, instr->format, instr->operands.size(), instr->definitions.size()));
} else if (instr->isPseudo()) { } else if (instr->isPseudo()) {
res.reset(create_instruction<Pseudo_instruction>( res.reset(create_instruction<Pseudo_instruction>(
instr->opcode, instr->format, instr->operands.size(), instr->definitions.size())); instr->opcode, instr->format, instr->operands.size(), instr->definitions.size()));
} else if (instr->isSOPK()) { } else if (instr->isSOPK()) {
res.reset(create_instruction<SOPK_instruction>( res.reset(create_instruction<SALU_instruction>(
instr->opcode, instr->format, instr->operands.size(), instr->definitions.size())); instr->opcode, instr->format, instr->operands.size(), instr->definitions.size()));
res->sopk().imm = instr->sopk().imm; res->salu().imm = instr->salu().imm;
} }
for (unsigned i = 0; i < instr->operands.size(); i++) { for (unsigned i = 0; i < instr->operands.size(); i++) {
res->operands[i] = instr->operands[i]; res->operands[i] = instr->operands[i];

View File

@@ -350,9 +350,9 @@ get_wait_imm(Program* program, aco_ptr<Instruction>& instr)
if (instr->opcode == aco_opcode::s_endpgm) { if (instr->opcode == aco_opcode::s_endpgm) {
return wait_imm(0, 0, 0, 0); return wait_imm(0, 0, 0, 0);
} else if (instr->opcode == aco_opcode::s_waitcnt) { } else if (instr->opcode == aco_opcode::s_waitcnt) {
return wait_imm(GFX10_3, instr->sopp().imm); return wait_imm(GFX10_3, instr->salu().imm);
} else if (instr->opcode == aco_opcode::s_waitcnt_vscnt) { } else if (instr->opcode == aco_opcode::s_waitcnt_vscnt) {
return wait_imm(0, 0, 0, instr->sopk().imm); return wait_imm(0, 0, 0, instr->salu().imm);
} else { } else {
unsigned max_lgkm_cnt = program->gfx_level >= GFX10 ? 62 : 14; unsigned max_lgkm_cnt = program->gfx_level >= GFX10 ? 62 : 14;
unsigned max_exp_cnt = 6; unsigned max_exp_cnt = 6;