ir3: lower undef booleans to zero
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

We are generally fine with undefs. However, booleans are only allowed to
contain 0/1 but are stored in 16b registers. Undefs may cause such
registers to be uninitialized and contain values other than 0/1. This
especially happens with undef booleans in phi srcs, which are explicitly
left uninitialized. In general, such non-0/1 values don't cause problems
because we mostly use booleans by comparing them to 0. However, they do
cause problems in special cases like `inot(x)` which we lower to `sub(1,
x)` which only works if true==1.

Fixes misrenderings in "Kingdoms of Amalur: Reckoning".

Totals from 12 (0.01% of 176258) affected shaders:
Instrs: 14590 -> 14615 (+0.17%)
CodeSize: 29796 -> 29808 (+0.04%)
NOPs: 3091 -> 3098 (+0.23%); split: -0.03%, +0.26%
MOVs: 735 -> 748 (+1.77%)
(sy)-stall: 4509 -> 4508 (-0.02%)
Cat0: 3471 -> 3483 (+0.35%); split: -0.03%, +0.37%
Cat1: 1257 -> 1270 (+1.03%)

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/42051>
This commit is contained in:
Job Noorman 2026-06-05 16:02:04 +02:00 committed by Marge Bot
parent 46fce462fb
commit 1a9a0a15f7

View file

@ -15,6 +15,12 @@
#include "nir_intrinsics_indices.h"
#include "util/u_math.h"
static bool
should_lower_undef(nir_undef_instr *undef)
{
return undef->def.bit_size == 1;
}
struct ir3_context *
ir3_context_init(struct ir3_compiler *compiler, struct ir3_shader *shader,
struct ir3_shader_variant *so)
@ -113,6 +119,18 @@ ir3_context_init(struct ir3_compiler *compiler, struct ir3_shader *shader,
NIR_PASS(_, ctx->s, ir3_nir_lower_tex_prefetch, &so->prefetch_bary_type);
}
/* We are generally fine with undefs. However, booleans are only allowed to
* contain 0/1 but are stored in 16b registers. Undefs may cause such
* registers to be uninitialized and contain values other than 0/1. This
* especially happens with undef booleans in phi srcs, which are explicitly
* left uninitialized. In general, such non-0/1 values don't cause problems
* because we mostly use booleans by comparing them to 0. However, they do
* cause problems in special cases like `inot(x)` which we lower to `sub(1,
* x)` which only works if true==1. Lower 1b undefs to zero to make sure
* booleans always contain a valid value.
*/
NIR_PASS(_, ctx->s, nir_lower_undef_to_zero, should_lower_undef);
bool vectorized = false;
NIR_PASS(vectorized, ctx->s, nir_opt_vectorize, ir3_nir_vectorize_filter,
NULL);