Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6ab8bec
[rocjitsu] Flag-Dependent Read/Write Liveness
theSK2005 Jun 17, 2026
a2fb929
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jun 25, 2026
5e897be
[rocjitsu] regen isa
accauble Jun 26, 2026
d335539
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jun 26, 2026
fc53413
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jun 29, 2026
80ade2a
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jul 1, 2026
87faec0
pre-commit fix
theSK2005 Jul 1, 2026
40717a1
added vop2 tests
theSK2005 Jul 1, 2026
995c5c7
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jul 1, 2026
88b74e6
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jul 7, 2026
98505bc
added check for dpp shift out of bounds where bound_ctrl == 0 which c…
theSK2005 Jul 7, 2026
a47f0ad
added VOP3 DPP coverage
theSK2005 Jul 9, 2026
33a0b6f
pre-commit fix
theSK2005 Jul 9, 2026
915a58f
derive VOP2/VOP2 destination ref from to_register_ref so width = 1 is…
theSK2005 Jul 10, 2026
7016060
added VOP3P and VOP33_SDST_ENC handling
theSK2005 Jul 10, 2026
9503713
updated implicit uses for DPP/SDWA to only add VGPRs to match the emu…
theSK2005 Jul 10, 2026
9b947e4
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jul 10, 2026
6849be2
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jul 14, 2026
32524c2
Merge branch 'develop' into users/skushwah/liveness-analysis-rw-flags
theSK2005 Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions emulation/rocjitsu/lib/python/amdisa/codegen/_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2120,6 +2120,51 @@ def _encoding_implicit_uses_impl(
'static_cast<uint16_t>(inst_.saddr), 2});'
'}'
)
# SDWA dst_unused:PRESERVE and DPP that keeps lanes (partial row/bank
# mask, or bound_ctrl == 0 with an edge-crossing dpp_ctrl) leave the old
# destination in place, so surface the preserved destination as a use.
# This matches what the executor actually restores: the non-VOPC SDWA/DPP
# merge only rewrites old vdst bytes/lanes via write_vgpr, so only a
# VGPR-class destination is preserved. SGPR destinations are fully
# written and never restored -- a VOP3_SDST_ENC carry (v_add_co_ci) and a
# VOP3 compare's SGPR mask alike -- so filter to RegClass::VGPR. The ref
# still comes from the decoded dst operand to get the real width.
#
# SDWA exists only on VOP1/VOP2; DPP additionally exists on VOP3/VOP3P/
# VOP3_SDST_ENC on gfx11+ (gated -- GCN/CDNA lack the dpp_* fields).
# VOPC/VOPCX stay omitted: their result lands in VCC/EXEC, which liveness
# does not track (see liveness.h).
enc = inst_enc.enc_name.upper()
has_sdwa = enc in ('ENC_VOP1', 'ENC_VOP2')
has_dpp = enc in ('ENC_VOP1', 'ENC_VOP2') or (
enc in ('ENC_VOP3', 'ENC_VOP3P', 'VOP3_SDST_ENC')
and self._supports_vop_dpp_encoding(enc)
)
if (has_sdwa or has_dpp) and 'vdst' in enc_field_names:
decls = ''
guards = []
if has_sdwa:
decls += (
'bool sdwa_preserve = sdwa_dst_sel_ != amdgpu::sdwa::DWORD && '
'sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE; '
)
guards.append('sdwa_preserve')
if has_dpp:
decls += (
'bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP && '
'(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF || '
'(dpp_bound_ctrl_ == 0 && '
'amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_))); '
)
guards.append('dpp_partial')
return (
decls + f'if ({" || ".join(guards)}) '
'for (int i = 0; i < num_dst_operands(); ++i) '
'if (const auto *dst = dst_operand(i)) '
'if (auto ref = dst->to_register_ref()) '
'if (ref->cls == RegClass::VGPR) '
'uses.expand(*ref);'
)
return ''

def _enc_field_at_bit(self, enc_name: str, bit_offset: int) -> str | None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ Vop1::Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exe
size_ += sizeof(MachineInst);
}

void Vop1::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop1::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down Expand Up @@ -168,6 +182,20 @@ Vop2::Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exe
literal_ = reinterpret_cast<const uint32_t *>(inst)[1];
}

void Vop2::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop2::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ class Smem : public IsaInstruction<Isa> {
class Vop1 : public IsaInstruction<Isa> {
public:
Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down Expand Up @@ -531,6 +532,7 @@ class Vopc : public IsaInstruction<Isa> {
class Vop2 : public IsaInstruction<Isa> {
public:
Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ Vop1::Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exe
size_ += sizeof(MachineInst);
}

void Vop1::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop1::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down Expand Up @@ -168,6 +182,20 @@ Vop2::Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exe
literal_ = reinterpret_cast<const uint32_t *>(inst)[1];
}

void Vop2::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop2::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ class Smem : public IsaInstruction<Isa> {
class Vop1 : public IsaInstruction<Isa> {
public:
Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down Expand Up @@ -515,6 +516,7 @@ class Vopc : public IsaInstruction<Isa> {
class Vop2 : public IsaInstruction<Isa> {
public:
Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ Vop1::Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exe
size_ += sizeof(MachineInst);
}

void Vop1::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop1::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down Expand Up @@ -168,6 +182,20 @@ Vop2::Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exe
literal_ = reinterpret_cast<const uint32_t *>(inst)[1];
}

void Vop2::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop2::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ class Smem : public IsaInstruction<Isa> {
class Vop1 : public IsaInstruction<Isa> {
public:
Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down Expand Up @@ -503,6 +504,7 @@ class Vopc : public IsaInstruction<Isa> {
class Vop2 : public IsaInstruction<Isa> {
public:
Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,20 @@ Vop1::Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exe
size_ += sizeof(MachineInst);
}

void Vop1::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop1::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down Expand Up @@ -162,6 +176,20 @@ Vop2::Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exe
literal_ = reinterpret_cast<const uint32_t *>(inst)[1];
}

void Vop2::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop2::default_encoding() {
return inst_.src0 != 250 && inst_.src0 != 255 && inst_.src0 != 249;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ class Smem : public IsaInstruction<Isa> {
class Vop1 : public IsaInstruction<Isa> {
public:
Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down Expand Up @@ -505,6 +506,7 @@ class Vopc : public IsaInstruction<Isa> {
class Vop2 : public IsaInstruction<Isa> {
public:
Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exec_fn);
void implicit_uses(RegisterSet &uses) const override;
bool default_encoding();
bool has_lit();
bool has_dpp();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,20 @@ Vop1::Vop1(std::string_view mnemonic, const Vop1MachineInst *inst, ExecuteFn exe
size_ += sizeof(MachineInst);
}

void Vop1::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop1::default_encoding() {
return (inst_.src0 != 250 && inst_.src0 != 233 && inst_.src0 != 234 && inst_.src0 != 255 &&
inst_.src0 != 254);
Expand Down Expand Up @@ -223,6 +237,20 @@ Vop2::Vop2(std::string_view mnemonic, const Vop2MachineInst *inst, ExecuteFn exe
literal_ = reinterpret_cast<const uint32_t *>(inst)[1];
}

void Vop2::implicit_uses(RegisterSet &uses) const {
bool sdwa_preserve =
sdwa_dst_sel_ != amdgpu::sdwa::DWORD && sdwa_dst_unused_ == amdgpu::sdwa::UNUSED_PRESERVE;
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (sdwa_preserve || dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop2::default_encoding() {
return (inst_.src0 != 250 && inst_.src0 != 233 && inst_.src0 != 234 && inst_.src0 != 255 &&
inst_.src0 != 254);
Expand Down Expand Up @@ -253,6 +281,18 @@ Vop3::Vop3(std::string_view mnemonic, const Vop3MachineInst *inst, ExecuteFn exe
size_ += sizeof(MachineInst);
}

void Vop3::implicit_uses(RegisterSet &uses) const {
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop3::has_lit_0() {
return (((inst_.src0 == 255) && (inst_.src1 != 255)) && (inst_.src2 != 255));
}
Expand Down Expand Up @@ -307,6 +347,18 @@ Vop3p::Vop3p(std::string_view mnemonic, const Vop3pMachineInst *inst, ExecuteFn
size_ += sizeof(MachineInst);
}

void Vop3p::implicit_uses(RegisterSet &uses) const {
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop3p::has_lit_0() {
return (((inst_.src0 == 255) && (inst_.src1 != 255)) && (inst_.src2 != 255));
}
Expand Down Expand Up @@ -444,6 +496,18 @@ Vop3SdstEnc::Vop3SdstEnc(std::string_view mnemonic, const Vop3SdstEncMachineInst
size_ += sizeof(MachineInst);
}

void Vop3SdstEnc::implicit_uses(RegisterSet &uses) const {
bool dpp_partial = inst_.src0 == amdgpu::SRC_DPP &&
(dpp_row_mask_ != 0xF || dpp_bank_mask_ != 0xF ||
(dpp_bound_ctrl_ == 0 && amdgpu::dpp::dpp_ctrl_produces_oob(dpp_ctrl_)));
if (dpp_partial)
for (int i = 0; i < num_dst_operands(); ++i)
if (const auto *dst = dst_operand(i))
if (auto ref = dst->to_register_ref())
if (ref->cls == RegClass::VGPR)
uses.expand(*ref);
}

bool Vop3SdstEnc::has_lit_0() {
return (((inst_.src0 == 255) && (inst_.src1 != 255)) && (inst_.src2 != 255));
}
Expand Down
Loading
Loading