Skip to content
This repository was archived by the owner on Oct 29, 2024. It is now read-only.

Commit

Permalink
shader_jit_a64: Optimize conditional tests
Browse files Browse the repository at this point in the history
These conditional tests are a 1:1 translation from the x64 code but do
not have to be. Reference-values are known at emit-time and can be
embedded as an immediate into an `EOR` instruction rather than moved
into a register. The `TST` instruction can be utilized to more optimally
test and update the `EQ`/`NE` status flags.
  • Loading branch information
Wunkolo committed Aug 11, 2024
1 parent e55e619 commit dc83bd3
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 18 deletions.
36 changes: 18 additions & 18 deletions src/video_core/shader/shader_jit_a64_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,35 +386,35 @@ void JitShader::Compile_SanitizedMul(QReg src1, QReg src2, QReg scratch0) {
}

void JitShader::Compile_EvaluateCondition(Instruction instr) {
// Note: NXOR is used below to check for equality
const u8 refx = instr.flow_control.refx.Value();
const u8 refy = instr.flow_control.refy.Value();

switch (instr.flow_control.op) {
// Note: NXOR is used below to check for equality
case Instruction::FlowControlType::Or:
MOV(XSCRATCH0, (instr.flow_control.refx.Value() ^ 1));
MOV(XSCRATCH1, (instr.flow_control.refy.Value() ^ 1));
EOR(XSCRATCH0, XSCRATCH0, COND0);
EOR(XSCRATCH1, XSCRATCH1, COND1);
EOR(XSCRATCH0, COND0, refx ^ 1);
EOR(XSCRATCH1, COND1, refy ^ 1);
ORR(XSCRATCH0, XSCRATCH0, XSCRATCH1);
CMP(XSCRATCH0, 0);
break;

// Note: TST will AND two registers and set the EQ/NE flags on the result
case Instruction::FlowControlType::And:
MOV(XSCRATCH0, (instr.flow_control.refx.Value() ^ 1));
MOV(XSCRATCH1, (instr.flow_control.refy.Value() ^ 1));
EOR(XSCRATCH0, XSCRATCH0, COND0);
EOR(XSCRATCH1, XSCRATCH1, COND1);
AND(XSCRATCH0, XSCRATCH0, XSCRATCH1);
EOR(XSCRATCH0, COND0, refx ^ 1);
EOR(XSCRATCH1, COND1, refy ^ 1);
TST(XSCRATCH0, XSCRATCH1);
break;

case Instruction::FlowControlType::JustX:
MOV(XSCRATCH0, (instr.flow_control.refx.Value() ^ 1));
EOR(XSCRATCH0, XSCRATCH0, COND0);
EOR(XSCRATCH0, COND0, refx ^ 1);
CMP(XSCRATCH0, 0);
break;

case Instruction::FlowControlType::JustY:
MOV(XSCRATCH0, (instr.flow_control.refy.Value() ^ 1));
EOR(XSCRATCH0, XSCRATCH0, COND1);
EOR(XSCRATCH0, COND1, refy ^ 1);
CMP(XSCRATCH0, 0);
break;
default:
UNREACHABLE();
break;
}
CMP(XSCRATCH0, 0);
}

void JitShader::Compile_UniformCondition(Instruction instr) {
Expand Down
3 changes: 3 additions & 0 deletions src/video_core/shader/shader_jit_a64_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class JitShader : private oaknut::CodeBlock, private oaknut::CodeGenerator {
*/
void Compile_SanitizedMul(oaknut::QReg src1, oaknut::QReg src2, oaknut::QReg scratch0);

/**
* Emits the code to evaluate a conditional instruction and update the host's EQ/NE status-flags
*/
void Compile_EvaluateCondition(Instruction instr);
void Compile_UniformCondition(Instruction instr);

Expand Down

0 comments on commit dc83bd3

Please sign in to comment.