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 {
Program* program;
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> resumeaddrs;
std::vector<struct aco_symbol>* symbols;
@ -155,7 +155,8 @@ void
emit_sopk_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction* instr)
{
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) {
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)
{
uint32_t opcode = ctx.opcode[(int)instr->opcode];
SOPP_instruction& sopp = instr->sopp();
SALU_instruction& sopp = instr->salu();
uint32_t encoding = (0b101111111 << 23);
encoding |= opcode << 16;
@ -1316,7 +1317,7 @@ fix_branches_gfx10(asm_context& ctx, std::vector<uint32_t>& out)
}
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)
{
Builder bld(ctx.program);
@ -1384,7 +1385,7 @@ fix_branches(asm_context& ctx, std::vector<uint32_t>& out)
if (ctx.gfx_level == GFX10)
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;
if ((offset < INT16_MIN || offset > INT16_MAX) && !branch.second->pass_flags) {
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());
/* Change prefetch mode back to default (0x3). */
instr->sopp().imm = 0x3;
instr->salu().imm = 0x3;
emit_instruction(ctx, code, instr.get());
}

View file

@ -566,11 +566,11 @@ public:
<%
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)]),
("sop1", [Format.SOP1], 'SOP1_instruction', [(0, 1), (1, 0), (1, 1), (2, 1), (3, 2)]),
("sop2", [Format.SOP2], 'SOP2_instruction', itertools.product([1, 2], [2, 3])),
("sopk", [Format.SOPK], 'SOPK_instruction', itertools.product([0, 1, 2], [0, 1])),
("sopp", [Format.SOPP], 'SOPP_instruction', itertools.product([0, 1], [0, 1])),
("sopc", [Format.SOPC], 'SOPC_instruction', [(1, 2)]),
("sop1", [Format.SOP1], 'SALU_instruction', [(0, 1), (1, 0), (1, 1), (2, 1), (3, 2)]),
("sop2", [Format.SOP2], 'SALU_instruction', itertools.product([1, 2], [2, 3])),
("sopk", [Format.SOPK], 'SALU_instruction', itertools.product([0, 1, 2], [0, 1])),
("sopp", [Format.SOPP], 'SALU_instruction', itertools.product([0, 1], [0, 1])),
("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)]),
("ds", [Format.DS], 'DS_instruction', [(1, 1), (1, 2), (1, 3), (0, 3), (0, 4)]),
("ldsdir", [Format.LDSDIR], 'LDSDIR_instruction', [(1, 1)]),

View file

@ -313,7 +313,7 @@ int
get_wait_states(aco_ptr<Instruction>& instr)
{
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)
return 3; /* lowered to 3 instructions in the assembler */
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
if (NOPs) {
/* create NOP */
aco_ptr<SOPP_instruction> nop{
create_instruction<SOPP_instruction>(aco_opcode::s_nop, Format::SOPP, 0, 0)};
aco_ptr<SALU_instruction> nop{
create_instruction<SALU_instruction>(aco_opcode::s_nop, Format::SOPP, 0, 0)};
nop->imm = NOPs - 1;
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 ||
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 size = ((sopk.imm >> 11) & 0x1f) + 1;
unsigned reg = sopk.imm & 0x3f;
@ -900,8 +900,8 @@ handle_instruction_gfx10(State& state, NOP_ctx_gfx10& ctx, aco_ptr<Instruction>&
vm_vsrc = 0;
sa_sdst = 0;
} else if (instr->opcode == aco_opcode::s_waitcnt_depctr) {
vm_vsrc = (instr->sopp().imm >> 2) & 0x7;
sa_sdst = instr->sopp().imm & 0x1;
vm_vsrc = (instr->salu().imm >> 2) & 0x7;
sa_sdst = instr->salu().imm & 0x1;
}
/* 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);
} else if (instr->isSALU() || instr->isSMEM()) {
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)
ctx.sgprs_read_by_VMEM.reset();
if (imm.lgkm == 0)
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();
} else if (vm_vsrc == 0) {
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()) {
/* Reducing lgkmcnt count to 0 always mitigates the hazard. */
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)
ctx.sgprs_read_by_SMEM.reset();
} 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)
ctx.sgprs_read_by_SMEM.reset();
} 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;
} else if (instr->opcode == aco_opcode::s_waitcnt_vscnt) {
/* 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)
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())
return instr->ldsdir().wait_vdst;
else if (instr->opcode == aco_opcode::s_waitcnt_depctr)
return (instr->sopp().imm >> 12) & 0xf;
return (instr->salu().imm >> 12) & 0xf;
else
return 15;
}
@ -1417,8 +1417,8 @@ handle_instruction_gfx11(State& state, NOP_ctx_gfx11& ctx, aco_ptr<Instruction>&
sa_sdst = 0;
} else if (instr->opcode == aco_opcode::s_waitcnt_depctr) {
/* va_vdst already obtained through parse_vdst_wait(). */
vm_vsrc = (instr->sopp().imm >> 2) & 0x7;
sa_sdst = instr->sopp().imm & 0x1;
vm_vsrc = (instr->salu().imm >> 2) & 0x7;
sa_sdst = instr->salu().imm & 0x1;
}
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_ds.reset();
} 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)
ctx.vgpr_used_by_vmem_load.reset();
if (imm.lgkm == 0)
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();
}
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];
assert(dst.size() == bld.lm.size());
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));
instr->operands[0] = Operand::zero();
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];
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));
instr->operands[0] = Operand(exec, bld.lm); /* current exec */
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)
{
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;
} 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 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)
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) {
alu_delay_wait wait = (alu_delay_wait)imm[i];
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 &&
(ctx.gfx_level >= GFX11 ? instr->isEXP() && instr->exp().done
: (instr->opcode == aco_opcode::s_sendmsg &&
instr->sopp().imm == sendmsg_ordered_ps_done))) {
instr->salu().imm == sendmsg_ordered_ps_done))) {
if (ctx.vm_nonzero)
imm.vm = 0;
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) {
assert(ctx.gfx_level >= GFX10);
SOPK_instruction* waitcnt_vs =
create_instruction<SOPK_instruction>(aco_opcode::s_waitcnt_vscnt, Format::SOPK, 1, 0);
SALU_instruction* waitcnt_vs =
create_instruction<SALU_instruction>(aco_opcode::s_waitcnt_vscnt, Format::SOPK, 1, 0);
waitcnt_vs->operands[0] = Operand(sgpr_null, s1);
waitcnt_vs->imm = imm.vs;
instructions.emplace_back(waitcnt_vs);
imm.vs = wait_imm::unset_counter;
}
if (!imm.empty()) {
SOPP_instruction* waitcnt =
create_instruction<SOPP_instruction>(aco_opcode::s_waitcnt, Format::SOPP, 0, 0);
SALU_instruction* waitcnt =
create_instruction<SALU_instruction>(aco_opcode::s_waitcnt, Format::SOPP, 0, 0);
waitcnt->imm = imm.pack(ctx.gfx_level);
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);
}
SOPP_instruction* inst =
create_instruction<SOPP_instruction>(aco_opcode::s_delay_alu, Format::SOPP, 0, 0);
SALU_instruction* inst =
create_instruction<SALU_instruction>(aco_opcode::s_delay_alu, Format::SOPP, 0, 0);
inst->imm = imm;
inst->pass_flags = (delay.valu_cycles | (delay.trans_cycles << 16));
instructions.emplace_back(inst);
@ -1176,7 +1176,7 @@ insert_wait_states(Program* program)
continue;
}
uint16_t imm = instr->sopp().imm;
uint16_t imm = instr->salu().imm;
int skip = i - prev_delay_alu - 1;
if (imm >> 7 || prev_delay_alu < 0 || skip >= 6) {
if (imm >> 7 == 0)
@ -1185,7 +1185,7 @@ insert_wait_states(Program* program)
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;
}
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,
bool writes_scc, uint8_t uses_ub = 0)
{
aco_ptr<SOP2_instruction> sop2{
create_instruction<SOP2_instruction>(op, Format::SOP2, 2, writes_scc ? 2 : 1)};
aco_ptr<SALU_instruction> sop2{
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[1] = Operand(get_alu_src(ctx, instr->src[1]));
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 ||
(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);
} else if (instr->opcode == aco_opcode::p_pops_gfx9_ordered_section_done) {
return memory_sync_info(storage_buffer | storage_image, semantic_release, scope_queuefamily);

View file

@ -939,11 +939,7 @@ private:
struct Block;
struct Instruction;
struct Pseudo_instruction;
struct SOP1_instruction;
struct SOP2_instruction;
struct SOPK_instruction;
struct SOPP_instruction;
struct SOPC_instruction;
struct SALU_instruction;
struct SMEM_instruction;
struct DS_instruction;
struct LDSDIR_instruction;
@ -1002,61 +998,13 @@ struct Instruction {
return *(Pseudo_instruction*)this;
}
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; }
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; }
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; }
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; }
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; }
SMEM_instruction& smem() noexcept
{
assert(isSMEM());
@ -1295,6 +1243,16 @@ struct Instruction {
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
{
return isSOP1() || isSOP2() || isSOPC() || isSOPK() || isSOPP();
@ -1307,32 +1265,13 @@ struct Instruction {
};
static_assert(sizeof(Instruction) == 16, "Unexpected padding");
struct SOPK_instruction : public Instruction {
uint16_t imm;
uint16_t padding;
};
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.
struct SALU_instruction : public Instruction {
/* In case of SOPP branch instructions, contains the Block index,
* and otherwise, for SOPP and SOPK the 16-bit signed immediate.
*/
uint32_t imm;
};
static_assert(sizeof(SOPP_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");
static_assert(sizeof(SALU_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
/**
* Scalar Memory Format:

View file

@ -2895,7 +2895,7 @@ lower_to_hw_instr(Program* program)
bool is_break_continue =
program->blocks[i].kind & (block_kind_break | block_kind_continue);
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 &&
inst->opcode != aco_opcode::s_cbranch_scc1) ||
(!discard_early_exit && !is_break_continue))

View file

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

View file

@ -103,8 +103,8 @@ struct InstrHash {
case Format::SMEM: return hash_murmur_32<SMEM_instruction>(instr);
case Format::VINTRP: return hash_murmur_32<VINTRP_instruction>(instr);
case Format::DS: return hash_murmur_32<DS_instruction>(instr);
case Format::SOPP: return hash_murmur_32<SOPP_instruction>(instr);
case Format::SOPK: return hash_murmur_32<SOPK_instruction>(instr);
case Format::SOPP: return hash_murmur_32<SALU_instruction>(instr);
case Format::SOPK: return hash_murmur_32<SALU_instruction>(instr);
case Format::EXP: return hash_murmur_32<Export_instruction>(instr);
case Format::MUBUF: return hash_murmur_32<MUBUF_instruction>(instr);
case Format::MIMG: return hash_murmur_32<MIMG_instruction>(instr);
@ -209,8 +209,8 @@ struct InstrPred {
case Format::SOPK: {
if (a->opcode == aco_opcode::s_getreg_b32)
return false;
SOPK_instruction& aK = a->sopk();
SOPK_instruction& bK = b->sopk();
SALU_instruction& aK = a->salu();
SALU_instruction& bK = b->salu();
return aK.imm == bK.imm;
}
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);
if (wave_size == 64 && mask > 0x7fffffff && mask != -1ull) {
/* 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[1] = Operand::c32(first_bit);
} else {
@ -5244,10 +5244,8 @@ try_convert_sopc_to_sopk(aco_ptr<Instruction>& instr)
return;
}
static_assert(sizeof(SOPK_instruction) <= sizeof(SOPC_instruction),
"Invalid direct instruction cast.");
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->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.
*/
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];
} 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[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};
Instruction* producer_instr = ctx.get(producer_idx);
if (!producer_instr)
if (!producer_instr || !producer_instr->isSALU())
return;
/* 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 */
if (producer_instr->isSOP1())
instr.reset(create_instruction<SOP1_instruction>(producer_instr->opcode, Format::SOP1,
producer_instr->operands.size(),
producer_instr->definitions.size()));
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;
instr.reset(create_instruction<SALU_instruction>(producer_instr->opcode, producer_instr->format,
producer_instr->operands.size(),
producer_instr->definitions.size()));
instr->salu().imm = producer_instr->salu().imm;
/* The copy is no longer needed. */
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) {
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);
break;
}
case Format::SOPP: {
uint16_t imm = instr->sopp().imm;
uint16_t imm = instr->salu().imm;
switch (instr->opcode) {
case aco_opcode::s_waitcnt: {
wait_imm unpacked(gfx_level, imm);
@ -400,7 +400,7 @@ print_instr_format_specific(enum amd_gfx_level gfx_level, const Instruction* ins
}
default: {
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)
fprintf(output, " imm:%u", imm);
break;

View file

@ -2848,10 +2848,8 @@ optimize_encoding_sopk(Program* program, ra_ctx& ctx, RegisterFile& register_fil
return;
}
static_assert(sizeof(SOPK_instruction) <= sizeof(SOP2_instruction),
"Invalid direct instruction cast.");
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;
if (literal_idx == 0)
@ -3319,7 +3317,7 @@ register_allocation(Program* program, live& live_vars, ra_test_policy policy)
aco_ptr<Instruction> mov;
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));
else
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)
{
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;
}
@ -577,7 +577,7 @@ perform_hazard_query(hazard_query* query, Instruction* instr, bool upwards)
if (upwards) {
if (instr->opcode == aco_opcode::p_pops_gfx9_add_exiting_wave_id ||
(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;
}
} 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>(
instr->opcode, instr->format, instr->operands.size(), instr->definitions.size()));
} 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()));
} else if (instr->isPseudo()) {
res.reset(create_instruction<Pseudo_instruction>(
instr->opcode, instr->format, instr->operands.size(), instr->definitions.size()));
} 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()));
res->sopk().imm = instr->sopk().imm;
res->salu().imm = instr->salu().imm;
}
for (unsigned i = 0; i < instr->operands.size(); 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) {
return wait_imm(0, 0, 0, 0);
} 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) {
return wait_imm(0, 0, 0, instr->sopk().imm);
return wait_imm(0, 0, 0, instr->salu().imm);
} else {
unsigned max_lgkm_cnt = program->gfx_level >= GFX10 ? 62 : 14;
unsigned max_exp_cnt = 6;