From 1a9a0a15f7cafdbdb3037bb109b6d77bf282d41c Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Fri, 5 Jun 2026 16:02:04 +0200 Subject: [PATCH] ir3: lower undef booleans to zero 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 Part-of: --- src/freedreno/ir3/ir3_context.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/freedreno/ir3/ir3_context.c b/src/freedreno/ir3/ir3_context.c index 0d47caba187..1d6acf25f1c 100644 --- a/src/freedreno/ir3/ir3_context.c +++ b/src/freedreno/ir3/ir3_context.c @@ -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);