shader: emit a real ballot for S_CMP on an exec mask

S_CMP_{EQ,LG}_U64 against a mask operand and zero is the idiom for 'are any
lanes live'. Treating it as a scalar compare loses the per-lane information, so
emit an actual ballot for that shape.
This commit is contained in:
Mac
2026-08-31 23:40:11 +05:30
parent 727e7d1930
commit d6d7b81099
@@ -22,6 +22,33 @@ Decoder::Operand ConditionOperand(Decoder::OperandKind kind) {
} // namespace
namespace {
bool IsMaskOperand(const Decoder::Operand& operand) {
return operand.kind == Decoder::OperandKind::VccLo ||
operand.kind == Decoder::OperandKind::ExecLo || operand.kind == Decoder::OperandKind::Sgpr;
}
bool IsZeroConstant(const Decoder::Operand& operand) {
return (operand.kind == Decoder::OperandKind::LiteralConstant ||
operand.kind == Decoder::OperandKind::IntegerInlineConstant) &&
operand.value == 0;
}
} // namespace
bool Translator::S_CMP_MASK_ANY(const Decoder::Instruction& inst, bool not_equal) {
if (!IsMaskOperand(inst.src0) || !IsZeroConstant(inst.src1)) {
return false;
}
const auto predicate = ReadMask(inst.src0);
const auto ballot = ir.Emit(IR::ValueOpcode::Ballot, {predicate});
const auto lo = ir.CompositeExtract(ballot, 0);
const auto hi = ir.CompositeExtract(ballot, 1);
const auto any =
ir.INotEqual(ir.BitwiseOr(lo, hi), IR::U32(IR::Value(0u)));
ir.SetScc(not_equal ? any : ir.LogicalNot(any));
return true;
}
void Translator::S_SAVEEXEC(const Decoder::Instruction& inst, IR::ValueOpcode operation,
bool negate_exec, bool negate_source, bool write_64) {
if (write_64) {