From 8a450fb0ffb230c6ee3ef96faa8ce629085a3204 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 19 Feb 2026 21:57:38 -0500 Subject: [PATCH] nir/lower_subgroups: generalize vote lowering We currently have code to lower quad votes to a ballot. The same idea works for subgroup votes. Generalize the quad vote code and use it to lower vote_all/vote_eq for backends setting a new lower_vote option. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Georg Lehmann Part-of: --- src/compiler/nir/nir.h | 1 + src/compiler/nir/nir_lower_subgroups.c | 28 +++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 3b64f419990..ff6a139227e 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5787,6 +5787,7 @@ typedef struct nir_lower_subgroups_options { uint8_t ballot_bit_size; uint8_t ballot_components; bool lower_to_scalar : 1; + bool lower_vote : 1; bool lower_vote_trivial : 1; bool lower_vote_feq : 1; bool lower_vote_ieq : 1; diff --git a/src/compiler/nir/nir_lower_subgroups.c b/src/compiler/nir/nir_lower_subgroups.c index bede202b9e6..1e1c52b704d 100644 --- a/src/compiler/nir/nir_lower_subgroups.c +++ b/src/compiler/nir/nir_lower_subgroups.c @@ -980,15 +980,19 @@ build_subgroup_gt_mask(nir_builder *b, } static nir_def * -build_quad_vote_any(nir_builder *b, nir_def *src, - const nir_lower_subgroups_options *options) +build_vote(nir_builder *b, nir_def *src, + const nir_lower_subgroups_options *options, + unsigned cluster_size, bool all) { nir_def *ballot = nir_ballot(b, options->ballot_components, options->ballot_bit_size, - src); - nir_def *mask = build_cluster_mask(b, 4, options); + all ? nir_inot(b, src) : src); + if (cluster_size) { + nir_def *mask = build_cluster_mask(b, cluster_size, options); + ballot = nir_iand(b, ballot, mask); + } - return nir_ine_imm(b, nir_iand(b, ballot, mask), 0); + return all ? nir_ieq_imm(b, ballot, 0) : nir_ine_imm(b, ballot, 0); } static nir_def * @@ -1088,8 +1092,12 @@ lower_subgroups_instr(nir_builder *b, nir_instr *instr, void *_options) switch (intrin->intrinsic) { case nir_intrinsic_vote_any: case nir_intrinsic_vote_all: - if (options->lower_vote_trivial) + if (options->lower_vote_trivial) { return intrin->src[0].ssa; + } else if (options->lower_vote) { + return build_vote(b, intrin->src[0].ssa, options, 0, + intrin->intrinsic == nir_intrinsic_vote_all); + } break; case nir_intrinsic_vote_feq: @@ -1337,14 +1345,10 @@ lower_subgroups_instr(nir_builder *b, nir_instr *instr, void *_options) break; case nir_intrinsic_quad_vote_any: - if (options->lower_quad_vote) - return build_quad_vote_any(b, intrin->src[0].ssa, options); - break; case nir_intrinsic_quad_vote_all: if (options->lower_quad_vote) { - nir_def *not_src = nir_inot(b, intrin->src[0].ssa); - nir_def *any_not = build_quad_vote_any(b, not_src, options); - return nir_inot(b, any_not); + return build_vote(b, intrin->src[0].ssa, options, 4, + intrin->intrinsic == nir_intrinsic_quad_vote_all); } break;