shader_jit_a64: Optimize conditional tests (#229)

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.
This commit is contained in:
Wunk 2024-08-15 01:45:20 -07:00 committed by GitHub
parent e55e619328
commit f248fefe06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 18 deletions

View file

@ -386,35 +386,33 @@ 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);
CMP(COND0, refx);
break;
case Instruction::FlowControlType::JustY:
MOV(XSCRATCH0, (instr.flow_control.refy.Value() ^ 1));
EOR(XSCRATCH0, XSCRATCH0, COND1);
CMP(COND1, refy);
break;
default:
UNREACHABLE();
break;
}
CMP(XSCRATCH0, 0);
}
void JitShader::Compile_UniformCondition(Instruction instr) {

View file

@ -94,6 +94,9 @@ private:
*/
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);