Better conditions

This commit is contained in:
Lander Gallastegi 2025-04-01 11:47:22 +02:00 committed by Lander Gallastegi
parent 4224a95583
commit 2e6f3aae32

View File

@ -12,14 +12,27 @@ namespace Shader::Backend::X64 {
using namespace Xbyak; using namespace Xbyak;
using namespace Xbyak::util; using namespace Xbyak::util;
static void TestCondition(EmitContext& ctx, const IR::Inst* ref) { static void EmitCondition(EmitContext& ctx, const IR::Inst* ref, Label& label, bool invert) {
IR::Value cond = ref->Arg(0); IR::Value cond = ref->Arg(0);
Operand& op = ctx.Def(cond)[0]; if (cond.IsImmediate()) {
Reg8 tmp = op.isREG() ? op.getReg().cvt8() : ctx.TempGPReg(false).cvt8(); // If imediate, we evaluate at compile time
if (!op.isREG()) { if (cond.U1() != invert) {
ctx.Code().mov(tmp, op); ctx.Code().jmp(label);
}
} else {
Operand& op = ctx.Def(cond)[0];
if (op.isREG()) {
Reg8 reg = op.getReg().cvt8();
ctx.Code().test(reg, reg);
} else {
ctx.Code().test(op, 0xff);
}
if (invert) {
ctx.Code().jz(label);
} else {
ctx.Code().jnz(label);
}
} }
ctx.Code().test(tmp, tmp);
} }
template <typename ArgType> template <typename ArgType>
@ -120,22 +133,20 @@ static void Traverse(EmitContext& ctx, const IR::Program& program) {
case IR::AbstractSyntaxNode::Type::If: { case IR::AbstractSyntaxNode::Type::If: {
IR::Inst* ref = node.data.if_node.cond.InstRecursive(); IR::Inst* ref = node.data.if_node.cond.InstRecursive();
Label& merge = ctx.BlockLabel(node.data.if_node.merge); Label& merge = ctx.BlockLabel(node.data.if_node.merge);
TestCondition(ctx, ref); EmitCondition(ctx, ref, merge, true);
c.jz(merge);
break; break;
} }
case IR::AbstractSyntaxNode::Type::Repeat: { case IR::AbstractSyntaxNode::Type::Repeat: {
IR::Inst* ref = node.data.repeat.cond.InstRecursive(); IR::Inst* ref = node.data.repeat.cond.InstRecursive();
Label& loop_header = ctx.BlockLabel(node.data.repeat.loop_header); Label& loop_header = ctx.BlockLabel(node.data.repeat.loop_header);
TestCondition(ctx, ref); EmitCondition(ctx, ref, loop_header, false);
c.jnz(loop_header);
break; break;
} }
case IR::AbstractSyntaxNode::Type::Break: { case IR::AbstractSyntaxNode::Type::Break: {
IR::Inst* ref = node.data.break_node.cond.InstRecursive(); IR::Inst* ref = node.data.break_node.cond.InstRecursive();
Label& merge = ctx.BlockLabel(node.data.break_node.merge); Label& merge = ctx.BlockLabel(node.data.break_node.merge);
TestCondition(ctx, ref); EmitCondition(ctx, ref, merge, true);
c.jz(merge); +c.jz(merge);
break; break;
} }
case IR::AbstractSyntaxNode::Type::Return: { case IR::AbstractSyntaxNode::Type::Return: {