From eb4737a1ddd8156ccc84ed0f277f3f111facbaeb Mon Sep 17 00:00:00 2001 From: Georg Lehmann Date: Tue, 30 Dec 2025 20:29:20 +0100 Subject: [PATCH] nir: add nir_alu_instr_is_exact helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alyssa Rosenzweig Reviewed-by: Marek Olšák Part-of: --- .../instruction_selection/aco_select_nir_alu.cpp | 2 +- src/asahi/compiler/agx_compile.c | 3 ++- src/compiler/nir/nir.h | 6 ++++++ src/compiler/nir/nir_lower_flrp.c | 2 +- src/compiler/nir/nir_opt_intrinsics.c | 3 ++- src/compiler/nir/nir_opt_reassociate.c | 2 +- src/compiler/nir/nir_opt_varyings.c | 9 +++++---- src/compiler/nir/nir_print.c | 2 +- src/compiler/nir/nir_search.c | 4 ++-- src/gallium/auxiliary/nir/nir_to_tgsi.c | 2 +- src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp | 4 ++-- src/gallium/drivers/r300/compiler/nir_to_rc.c | 2 +- src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c | 2 +- src/intel/compiler/intel_nir_opt_peephole_ffma.c | 4 ++-- src/microsoft/compiler/nir_to_dxil.c | 2 +- 15 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp b/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp index 43bc6f16dd6..f406e724932 100644 --- a/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp +++ b/src/amd/compiler/instruction_selection/aco_select_nir_alu.cpp @@ -16,7 +16,7 @@ static Builder create_alu_builder(isel_context* ctx, nir_alu_instr* instr) { Builder bld(ctx->program, ctx->block); - bld.is_precise = instr->exact; + bld.is_precise = nir_alu_instr_is_exact(instr); bld.is_sz_preserve = nir_alu_instr_is_signed_zero_preserve(instr); bld.is_inf_preserve = nir_alu_instr_is_inf_preserve(instr); bld.is_nan_preserve = nir_alu_instr_is_nan_preserve(instr); diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 3ce4da3027c..4bb7aef0866 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -3677,7 +3677,8 @@ libagx_frcp(nir_builder *b, nir_def *x) static bool agx_nir_lower_fdiv(nir_builder *b, nir_alu_instr *alu, void *_) { - if (alu->op != nir_op_frcp || !alu->exact || alu->def.bit_size != 32) + if (alu->op != nir_op_frcp || !nir_alu_instr_is_exact(alu) || + alu->def.bit_size != 32) return false; b->cursor = nir_before_instr(&alu->instr); diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index b99817df304..702aa486484 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1599,6 +1599,12 @@ nir_alu_instr_is_signed_zero_inf_nan_preserve(nir_alu_instr *alu) return alu->fp_math_ctrl & nir_fp_preserve_sz_inf_nan; } +static inline bool +nir_alu_instr_is_exact(nir_alu_instr *alu) +{ + return alu->exact; +} + void nir_alu_src_copy(nir_alu_src *dest, const nir_alu_src *src); nir_component_mask_t diff --git a/src/compiler/nir/nir_lower_flrp.c b/src/compiler/nir/nir_lower_flrp.c index e723d271141..b266f7f59ec 100644 --- a/src/compiler/nir/nir_lower_flrp.c +++ b/src/compiler/nir/nir_lower_flrp.c @@ -390,7 +390,7 @@ convert_flrp_instruction(nir_builder *bld, * subtract, a multiply, and an FMA)... but in that case the other * formulation should have been used. */ - if (alu->exact) { + if (nir_alu_instr_is_exact(alu)) { if (have_ffma) replace_with_strict_ffma(bld, dead_flrp, alu); else diff --git a/src/compiler/nir/nir_opt_intrinsics.c b/src/compiler/nir/nir_opt_intrinsics.c index 561d66c95fe..3bc0304ea03 100644 --- a/src/compiler/nir/nir_opt_intrinsics.c +++ b/src/compiler/nir/nir_opt_intrinsics.c @@ -276,7 +276,8 @@ try_opt_exclusive_scan_to_inclusive(nir_builder *b, nir_intrinsic_instr *intrin) return false; /* Don't reassociate exact float operations. */ - if (nir_alu_type_get_base_type(nir_op_infos[alu->op].output_type) == nir_type_float && alu->exact) + if (nir_alu_type_get_base_type(nir_op_infos[alu->op].output_type) == nir_type_float && + nir_alu_instr_is_exact(alu)) return false; /* SPIR-V rules for fmax/fmin scans are *very* stupid. diff --git a/src/compiler/nir/nir_opt_reassociate.c b/src/compiler/nir/nir_opt_reassociate.c index 2f878234b50..3bf4d52b7c2 100644 --- a/src/compiler/nir/nir_opt_reassociate.c +++ b/src/compiler/nir/nir_opt_reassociate.c @@ -203,7 +203,7 @@ can_reassociate(nir_alu_instr *alu) return (props & NIR_OP_IS_2SRC_COMMUTATIVE) && ((props & NIR_OP_IS_ASSOCIATIVE) || - (!alu->exact && (props & NIR_OP_IS_INEXACT_ASSOCIATIVE))); + (!nir_alu_instr_is_exact(alu) && (props & NIR_OP_IS_INEXACT_ASSOCIATIVE))); } /* diff --git a/src/compiler/nir/nir_opt_varyings.c b/src/compiler/nir/nir_opt_varyings.c index 93f34399848..4bd635d5fdb 100644 --- a/src/compiler/nir/nir_opt_varyings.c +++ b/src/compiler/nir/nir_opt_varyings.c @@ -2923,7 +2923,8 @@ find_tes_triangle_interp_3fmul_2fadd(struct linkage_info *linkage, unsigned i) /* Only maximum of 3 loads expected. Also reject exact ops because we * are going to do an inexact transformation with it. */ - if (!fmul || fmul->op != nir_op_fmul || fmul->exact || num_fmuls == 3 || + if (!fmul || fmul->op != nir_op_fmul || nir_alu_instr_is_exact(fmul) || + num_fmuls == 3 || !gather_fmul_tess_coord(iter->instr, fmul, vertex_index, &tess_coord_swizzle, &tess_coord_used, &load_tess_coord)) @@ -2934,7 +2935,7 @@ find_tes_triangle_interp_3fmul_2fadd(struct linkage_info *linkage, unsigned i) /* The multiplication must only be used by fadd. Also reject exact ops. */ nir_alu_instr *fadd = get_single_use_as_alu(&fmul->def); - if (!fadd || fadd->op != nir_op_fadd || fadd->exact) + if (!fadd || fadd->op != nir_op_fadd || nir_alu_instr_is_exact(fadd)) return false; /* The 3 fmuls must only be used by 2 fadds. */ @@ -3015,7 +3016,7 @@ find_tes_triangle_interp_1fmul_2ffma(struct linkage_info *linkage, unsigned i) * with it. */ if (!alu || (alu->op != nir_op_fmul && alu->op != nir_op_ffma) || - alu->exact || + nir_alu_instr_is_exact(alu) || !gather_fmul_tess_coord(iter->instr, alu, vertex_index, &tess_coord_swizzle, &tess_coord_used, &load_tess_coord)) @@ -3119,7 +3120,7 @@ static bool can_move_alu_across_interp(struct linkage_info *linkage, nir_alu_instr *alu) { /* Exact ALUs can't be moved across interpolation. */ - if (alu->exact) + if (nir_alu_instr_is_exact(alu)) return false; /* Interpolation converts Infs to NaNs. If we turn a result of an ALU diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index 5054e24183b..393f3aeb6fd 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -489,7 +489,7 @@ print_alu_instr(nir_alu_instr *instr, print_state *state) print_def(&instr->def, state); fprintf(fp, " = %s", nir_op_infos[instr->op].name); - if (instr->exact) + if (nir_alu_instr_is_exact(instr)) fprintf(fp, "!"); if (instr->no_signed_wrap) fprintf(fp, ".nsw"); diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c index 671a0b75415..bbc712c05f9 100644 --- a/src/compiler/nir/nir_search.c +++ b/src/compiler/nir/nir_search.c @@ -392,8 +392,8 @@ match_expression(const nir_algebraic_table *table, const nir_search_expression * instr->def.bit_size != expr->value.bit_size) return false; - state->inexact_match = expr->inexact || expr->contract || state->inexact_match; - state->has_exact_alu = (instr->exact && !expr->ignore_exact) || state->has_exact_alu; + state->inexact_match |= expr->inexact || expr->contract; + state->has_exact_alu |= nir_alu_instr_is_exact(instr) && !expr->ignore_exact; if (state->inexact_match && state->has_exact_alu) return false; diff --git a/src/gallium/auxiliary/nir/nir_to_tgsi.c b/src/gallium/auxiliary/nir/nir_to_tgsi.c index b0c8cf18d8f..367079b647e 100644 --- a/src/gallium/auxiliary/nir/nir_to_tgsi.c +++ b/src/gallium/auxiliary/nir/nir_to_tgsi.c @@ -1449,7 +1449,7 @@ ntt_emit_alu(struct ntt_compile *c, nir_alu_instr *instr) if (instr->op == nir_op_fsat && nir_legacy_fsat_folds(instr)) return; - c->precise = instr->exact; + c->precise = nir_alu_instr_is_exact(instr); assert(num_srcs <= ARRAY_SIZE(src)); for (i = 0; i < num_srcs; i++) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp index 8a49bf60bd4..84f9e379e4d 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp @@ -3003,7 +3003,7 @@ Converter::visit(nir_alu_instr *insn) if (!oldPos) { oldPos = this->bb->getEntry(); - oldPos->precise = insn->exact; + oldPos->precise = nir_alu_instr_is_exact(insn); } if (unlikely(!oldPos)) @@ -3011,7 +3011,7 @@ Converter::visit(nir_alu_instr *insn) while (oldPos->next) { oldPos = oldPos->next; - oldPos->precise = insn->exact; + oldPos->precise = nir_alu_instr_is_exact(insn); } return true; diff --git a/src/gallium/drivers/r300/compiler/nir_to_rc.c b/src/gallium/drivers/r300/compiler/nir_to_rc.c index 824803ebb28..16c5bf7f04e 100644 --- a/src/gallium/drivers/r300/compiler/nir_to_rc.c +++ b/src/gallium/drivers/r300/compiler/nir_to_rc.c @@ -818,7 +818,7 @@ ntr_emit_alu(struct ntr_compile *c, nir_alu_instr *instr) if (instr->op == nir_op_fsat && nir_legacy_fsat_folds(instr)) return; - c->precise = instr->exact; + c->precise = nir_alu_instr_is_exact(instr); assert(num_srcs <= ARRAY_SIZE(src)); for (i = 0; i < num_srcs; i++) diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 2a2fa8f16a9..077159cdb4d 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -2234,7 +2234,7 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu) UNREACHABLE("unsupported opcode"); return; } - if (alu->exact) + if (nir_alu_instr_is_exact(alu)) spirv_builder_emit_decoration(&ctx->builder, result, SpvDecorationNoContraction); store_alu_result(ctx, alu, result, atype); diff --git a/src/intel/compiler/intel_nir_opt_peephole_ffma.c b/src/intel/compiler/intel_nir_opt_peephole_ffma.c index e6cb5df4f6f..eb62ef440df 100644 --- a/src/intel/compiler/intel_nir_opt_peephole_ffma.c +++ b/src/intel/compiler/intel_nir_opt_peephole_ffma.c @@ -74,7 +74,7 @@ get_mul_for_src(nir_alu_src *src, unsigned num_components, * value and what they don't care about is the add. Another reason is that * SPIR-V explicitly requires this behaviour. */ - if (!alu || alu->exact) + if (!alu || nir_alu_instr_is_exact(alu)) return NULL; switch (alu->op) { @@ -160,7 +160,7 @@ intel_nir_opt_peephole_ffma_instr(nir_builder *b, if (add->op != nir_op_fadd) return false; - if (add->exact) + if (nir_alu_instr_is_exact(add)) return false; diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c index a7d49adb748..1749cc8c49e 100644 --- a/src/microsoft/compiler/nir_to_dxil.c +++ b/src/microsoft/compiler/nir_to_dxil.c @@ -2275,7 +2275,7 @@ emit_binop(struct ntd_context *ctx, nir_alu_instr *alu, bool is_float_op = nir_alu_type_get_base_type(nir_op_infos[alu->op].output_type) == nir_type_float; enum dxil_opt_flags flags = 0; - if (is_float_op && !alu->exact) + if (is_float_op && !nir_alu_instr_is_exact(alu)) flags |= DXIL_UNSAFE_ALGEBRA; const struct dxil_value *v = dxil_emit_binop(&ctx->mod, opcode, op0, op1, flags);