From 992b35704efc027844d84bd582a6e76d98d34c3b Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Thu, 14 May 2026 23:58:56 -0700 Subject: [PATCH] nir/instr_set: Consider normalization when calculating hash The nir_instrs_equal normalizes the some indices but hash_intrinsic wasn't normalizing them. Reorganize the code so both do it using the same helper. Fixes: b2bc57551aab ("nir/instr_set: allow cse with fp_math_ctrl mismatches for intrinsics") Assisted-by: Pi coding agent (GPT-5.5) Reviewed-by: Georg Lehmann Part-of: --- src/compiler/nir/nir_instr_set.c | 69 +++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c index 5aec3f3e100..c14b9bc3825 100644 --- a/src/compiler/nir/nir_instr_set.c +++ b/src/compiler/nir/nir_instr_set.c @@ -231,6 +231,38 @@ hash_phi(uint32_t hash, const nir_phi_instr *instr) return hash; } +/* Returns either the original indices or the provided buffer, if some + * change was necessary. + */ +static const int * +normalized_intrinsic_const_indices(const nir_intrinsic_instr *instr, + int const_index[NIR_INTRINSIC_MAX_CONST_INDEX]) +{ + const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic]; + + if (!nir_intrinsic_has_fp_math_ctrl(instr) && + !nir_intrinsic_has_io_semantics(instr)) + return instr->const_index; + + memcpy(const_index, instr->const_index, + info->num_index_slots * sizeof(instr->const_index[0])); + + /* Keep this in sync with nir_instr_set_add_or_rewrite(): these bits are + * merged into the rewritten instruction instead of preventing equality. + */ + if (nir_intrinsic_has_fp_math_ctrl(instr)) { + unsigned offset = info->index_map[NIR_INTRINSIC_FP_MATH_CTRL] - 1; + const_index[offset] = 0; + } else if (nir_intrinsic_has_io_semantics(instr)) { + unsigned offset = info->index_map[NIR_INTRINSIC_IO_SEMANTICS] - 1; + nir_io_semantics sem = nir_intrinsic_io_semantics(instr); + sem.no_signed_zero = false; + memcpy(&const_index[offset], &sem, sizeof(sem)); + } + + return const_index; +} + static uint32_t hash_intrinsic(uint32_t hash, const nir_intrinsic_instr *instr) { @@ -242,7 +274,10 @@ hash_intrinsic(uint32_t hash, const nir_intrinsic_instr *instr) hash = XXH32(v, sizeof(v), hash); } - hash = XXH32(instr->const_index, info->num_index_slots * sizeof(instr->const_index[0]), hash); + int const_index[NIR_INTRINSIC_MAX_CONST_INDEX]; + const int *normalized = + normalized_intrinsic_const_indices(instr, const_index); + hash = XXH32(normalized, info->num_index_slots * sizeof(normalized[0]), hash); for (unsigned i = 0; i < nir_intrinsic_infos[instr->intrinsic].num_srcs; i++) hash = hash_src(hash, &instr->src[i]); @@ -748,30 +783,16 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2) return false; } - /* Compare indices, but allow fp_math_ctrl mismatches. */ - for (unsigned i = 0; i < info->num_indices; i++) { - nir_intrinsic_index_flag index = info->indices[i]; + int const_index1[NIR_INTRINSIC_MAX_CONST_INDEX]; + int const_index2[NIR_INTRINSIC_MAX_CONST_INDEX]; + const int *normalized1 = + normalized_intrinsic_const_indices(intrinsic1, const_index1); + const int *normalized2 = + normalized_intrinsic_const_indices(intrinsic2, const_index2); - if (index == NIR_INTRINSIC_FP_MATH_CTRL) { - continue; - } else if (index == NIR_INTRINSIC_IO_SEMANTICS) { - nir_io_semantics sem1 = nir_intrinsic_io_semantics(intrinsic1); - nir_io_semantics sem2 = nir_intrinsic_io_semantics(intrinsic2); - sem1.no_signed_zero = false; - sem2.no_signed_zero = false; - - if (memcmp(&sem1, &sem2, sizeof(sem1))) - return false; - } else { - unsigned size = nir_intrinsic_index_size(index); - unsigned offset = info->index_map[index] - 1; - - if (memcmp(&intrinsic1->const_index[offset], - &intrinsic2->const_index[offset], - sizeof(intrinsic1->const_index[0]) * size)) - return false; - } - } + if (memcmp(normalized1, normalized2, + info->num_index_slots * sizeof(intrinsic1->const_index[0]))) + return false; return true; }