mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-30 17:18:14 +00:00
shader: resolve getpc/add/addc long jumps through any scalar pair
This commit is contained in:
1 parent
154b175daf
commit
346e9a3c69
2 files changed
+33
-15
No files matched your search
@@ -69,10 +69,6 @@ BranchCondition ConditionForOpcode(Opcode opcode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRegister(const Decoder::Operand& operand, Decoder::OperandKind kind, uint32_t reg) {
|
|
||||||
return operand.kind == kind && operand.reg == reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScalarOperandCode(const Decoder::Operand& operand, uint32_t& code) {
|
bool ScalarOperandCode(const Decoder::Operand& operand, uint32_t& code) {
|
||||||
switch (operand.kind) {
|
switch (operand.kind) {
|
||||||
case Decoder::OperandKind::Sgpr: code = operand.reg; return true;
|
case Decoder::OperandKind::Sgpr: code = operand.reg; return true;
|
||||||
@@ -516,24 +512,22 @@ bool ResolveSetpcTarget(const Decoder::Program& program, uint32_t setpc_index, u
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& setpc = program.instructions[setpc_index];
|
const auto& setpc = program.instructions[setpc_index];
|
||||||
if (setpc.opcode != Opcode::S_SETPC_B64 || setpc.src0.kind != Decoder::OperandKind::Sgpr) {
|
uint32_t pc_code = 0;
|
||||||
|
if (setpc.opcode != Opcode::S_SETPC_B64 || !ScalarOperandCode(setpc.src0, pc_code)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto pc_reg = setpc.src0.reg;
|
|
||||||
if (setpc_index >= 2u) {
|
if (setpc_index >= 2u) {
|
||||||
const auto& arith = program.instructions[setpc_index - 1u];
|
const auto& arith = program.instructions[setpc_index - 1u];
|
||||||
const auto& getpc = program.instructions[setpc_index - 2u];
|
const auto& getpc = program.instructions[setpc_index - 2u];
|
||||||
if (getpc.opcode == Opcode::S_GETPC_B64 && getpc.dst.kind == Decoder::OperandKind::Sgpr &&
|
if (getpc.opcode == Opcode::S_GETPC_B64 && IsScalarCode(getpc.dst, pc_code) &&
|
||||||
getpc.dst.reg == pc_reg && arith.dst.kind == Decoder::OperandKind::Sgpr &&
|
IsScalarCode(arith.dst, pc_code)) {
|
||||||
arith.dst.reg == pc_reg) {
|
|
||||||
uint32_t imm = 0;
|
uint32_t imm = 0;
|
||||||
bool adds = arith.opcode == Opcode::S_ADD_U32 || arith.opcode == Opcode::S_ADD_I32;
|
bool adds = arith.opcode == Opcode::S_ADD_U32 || arith.opcode == Opcode::S_ADD_I32;
|
||||||
bool subs = arith.opcode == Opcode::S_SUB_U32 || arith.opcode == Opcode::S_SUB_I32;
|
bool subs = arith.opcode == Opcode::S_SUB_U32 || arith.opcode == Opcode::S_SUB_I32;
|
||||||
if ((adds || subs) &&
|
if ((adds || subs) &&
|
||||||
(IsRegister(arith.src0, Decoder::OperandKind::Sgpr, pc_reg) ||
|
(IsScalarCode(arith.src0, pc_code) || IsScalarCode(arith.src1, pc_code)) &&
|
||||||
IsRegister(arith.src1, Decoder::OperandKind::Sgpr, pc_reg)) &&
|
|
||||||
(IsImmediate(arith.src0, imm) || IsImmediate(arith.src1, imm))) {
|
(IsImmediate(arith.src0, imm) || IsImmediate(arith.src1, imm))) {
|
||||||
const auto base = InstructionEndPc(getpc);
|
const auto base = InstructionEndPc(getpc);
|
||||||
target = (adds ? base + imm : base - imm) & ~3u;
|
target = (adds ? base + imm : base - imm) & ~3u;
|
||||||
@@ -544,14 +538,14 @@ bool ResolveSetpcTarget(const Decoder::Program& program, uint32_t setpc_index, u
|
|||||||
|
|
||||||
if (setpc_index >= 1u) {
|
if (setpc_index >= 1u) {
|
||||||
const auto& getpc = program.instructions[setpc_index - 1u];
|
const auto& getpc = program.instructions[setpc_index - 1u];
|
||||||
if (getpc.opcode == Opcode::S_GETPC_B64 && getpc.dst.kind == Decoder::OperandKind::Sgpr &&
|
if (getpc.opcode == Opcode::S_GETPC_B64 && IsScalarCode(getpc.dst, pc_code)) {
|
||||||
getpc.dst.reg == pc_reg) {
|
|
||||||
target = InstructionEndPc(getpc);
|
target = InstructionEndPc(getpc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// Long jump: s_getpc_b64; s_add_u32 lo, imm; s_addc_u32 hi, 0.
|
||||||
|
return ResolvePcRelativeBase(program, setpc_index, pc_code, &target);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResolveSetpcTargets(const Decoder::Program& program, uint32_t setpc_index,
|
bool ResolveSetpcTargets(const Decoder::Program& program, uint32_t setpc_index,
|
||||||
|
|||||||
@@ -11272,6 +11272,29 @@ void TestNewShaderRecompilerSetpcBranch() {
|
|||||||
CheckSpirvBinaryValidates(result.spirv);
|
CheckSpirvBinaryValidates(result.spirv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestNewShaderRecompilerSetpcLongBranch() {
|
||||||
|
using namespace ShaderRecompiler;
|
||||||
|
const uint32_t shader[] = {
|
||||||
|
EncodeSop1(0x1f, 106, 0), // s_getpc_b64 vcc
|
||||||
|
EncodeSop2(0x00, 106, 106, 255), 0x14u, // s_add_u32 vcc_lo, vcc_lo, 0x14
|
||||||
|
EncodeSop2(0x04, 107, 107, 128), // s_addc_u32 vcc_hi, vcc_hi, 0
|
||||||
|
EncodeSop1(0x21, 125, 106), // s_swappc_b64 null, vcc
|
||||||
|
EncodeSMovB32(0, 129), // skipped
|
||||||
|
0xbf810000u, // s_endpgm at 0x18
|
||||||
|
};
|
||||||
|
|
||||||
|
Decoder::Program decoded;
|
||||||
|
Decoder::DecodeProgram(shader, decoded);
|
||||||
|
const auto graph = CFG::BuildGraph(decoded);
|
||||||
|
const auto* jump = graph.FindBlockByPc(0u);
|
||||||
|
const auto* target = graph.FindBlockByPc(0x18u);
|
||||||
|
Check(jump != nullptr && target != nullptr &&
|
||||||
|
jump->terminator.kind == CFG::TerminatorKind::Branch &&
|
||||||
|
jump->terminator.true_block == target->id,
|
||||||
|
"S_GETPC/S_ADD/S_ADDC long jump through VCC missed its target");
|
||||||
|
CheckSpirvBinaryValidates(RecompileForTest(shader, MakeCompileOptions(ShaderType::Compute)).spirv);
|
||||||
|
}
|
||||||
|
|
||||||
void TestFusedShaderHandoffPreservesRegisters() {
|
void TestFusedShaderHandoffPreservesRegisters() {
|
||||||
using namespace ShaderRecompiler;
|
using namespace ShaderRecompiler;
|
||||||
uint32_t front[] = {
|
uint32_t front[] = {
|
||||||
@@ -17365,6 +17388,7 @@ int main() {
|
|||||||
TestNewShaderRecompilerPixelImageSampleLodSelection();
|
TestNewShaderRecompilerPixelImageSampleLodSelection();
|
||||||
TestNewShaderRecompilerBranchConditionForms();
|
TestNewShaderRecompilerBranchConditionForms();
|
||||||
TestNewShaderRecompilerSetpcBranch();
|
TestNewShaderRecompilerSetpcBranch();
|
||||||
|
TestNewShaderRecompilerSetpcLongBranch();
|
||||||
TestGraphicsComputeGetreg();
|
TestGraphicsComputeGetreg();
|
||||||
TestMemoryFedScalarLeafCall();
|
TestMemoryFedScalarLeafCall();
|
||||||
TestFusedShaderHandoffPreservesRegisters();
|
TestFusedShaderHandoffPreservesRegisters();
|
||||||
|
|||||||
Reference in new issue
Block a user