From bca5aab2befef7203472b207da9eb573a9c1477f Mon Sep 17 00:00:00 2001 From: Georg Lehmann Date: Sat, 7 Feb 2026 22:36:25 +0100 Subject: [PATCH] nir: let nir_analyze_fp_range take a nir_def This is midly worse for vector constants, but so much simpler. Reviewed-by: Rhys Perry Part-of: --- src/compiler/nir/nir_gather_tcs_info.c | 15 +----- src/compiler/nir/nir_range_analysis.c | 75 +++++++++----------------- src/compiler/nir/nir_range_analysis.h | 3 +- src/compiler/nir/nir_search_helpers.h | 54 +++++++++---------- 4 files changed, 53 insertions(+), 94 deletions(-) diff --git a/src/compiler/nir/nir_gather_tcs_info.c b/src/compiler/nir/nir_gather_tcs_info.c index 704365acaa8..c70114f4a38 100644 --- a/src/compiler/nir/nir_gather_tcs_info.c +++ b/src/compiler/nir/nir_gather_tcs_info.c @@ -458,19 +458,8 @@ nir_gather_tcs_info(const nir_shader *nir, nir_tcs_info *info, continue; } - /* nir_analyze_fp_range only accepts an ALU src, so we have to - * create a dummy ALU instruction. It's not inserted into - * the shader. - */ - nir_alu_instr *dummy_alu = - nir_alu_instr_create((nir_shader*)nir, nir_op_mov); - dummy_alu->def.num_components = 1; - dummy_alu->def.bit_size = scalar.def->bit_size; - dummy_alu->src[0].src.ssa = scalar.def; - dummy_alu->src[0].swizzle[0] = scalar.comp; - const struct fp_result_range r = - nir_analyze_fp_range(range_ht, dummy_alu, 0); + nir_analyze_fp_range(range_ht, scalar.def); switch (r.range) { case unknown: @@ -493,8 +482,6 @@ nir_gather_tcs_info(const nir_shader *nir, nir_tcs_info *info, tess_level_writes_gt_two |= BITFIELD_BIT(shift); break; } - - nir_instr_free(&dummy_alu->instr); } } } diff --git a/src/compiler/nir/nir_range_analysis.c b/src/compiler/nir/nir_range_analysis.c index ac90433a1c2..5aa22d211fd 100644 --- a/src/compiler/nir/nir_range_analysis.c +++ b/src/compiler/nir/nir_range_analysis.c @@ -151,24 +151,8 @@ nir_alu_src_type(const nir_alu_instr *instr, unsigned src) } static struct fp_result_range -analyze_constant(const struct nir_alu_instr *instr, unsigned src) +analyze_fp_constant(const nir_load_const_instr *const load) { - uint8_t swizzle[NIR_MAX_VEC_COMPONENTS] = { 0, 1, 2, 3, - 4, 5, 6, 7, - 8, 9, 10, 11, - 12, 13, 14, 15 }; - - /* If the source is an explicitly sized source, then we need to reset - * both the number of components and the swizzle. - */ - const unsigned num_components = nir_ssa_alu_instr_src_components(instr, src); - - for (unsigned i = 0; i < num_components; ++i) - swizzle[i] = instr->src[src].swizzle[i]; - - const nir_load_const_instr *const load = - nir_def_as_load_const(instr->src[src].src.ssa); - struct fp_result_range r = { unknown, false, false, false }; double min_value = NAN; @@ -180,8 +164,8 @@ analyze_constant(const struct nir_alu_instr *instr, unsigned src) r.is_a_number = true; r.is_finite = true; - for (unsigned i = 0; i < num_components; ++i) { - const double v = nir_const_value_as_float(load->value[swizzle[i]], + for (unsigned i = 0; i < load->def.num_components; ++i) { + const double v = nir_const_value_as_float(load->value[i], load->def.bit_size); if (floor(v) != v) @@ -402,28 +386,25 @@ union_ranges(enum fp_ranges a, enum fp_ranges b) struct fp_query { struct analysis_query head; - const nir_alu_instr *instr; - unsigned src; + const nir_def *def; }; static void -push_fp_query(struct analysis_state *state, const nir_alu_instr *alu, unsigned src) +push_fp_query(struct analysis_state *state, const nir_def *def) { struct fp_query *pushed_q = push_analysis_query(state, sizeof(struct fp_query)); - pushed_q->instr = alu; - pushed_q->src = src; + pushed_q->def = def; } static uintptr_t get_fp_key(struct analysis_query *q) { struct fp_query *fp_q = (struct fp_query *)q; - const nir_src *src = &fp_q->instr->src[fp_q->src].src; - if (!nir_def_is_alu(src->ssa)) + if (!nir_def_is_alu(fp_q->def)) return 0; - return (uintptr_t)nir_def_as_alu(src->ssa); + return (uintptr_t)fp_q->def; } static inline bool @@ -480,35 +461,27 @@ process_fp_query(struct analysis_state *state, struct analysis_query *aq, uint32 STATIC_ASSERT(last_range + 1 == 7); struct fp_query q = *(struct fp_query *)aq; - const nir_alu_instr *instr = q.instr; - unsigned src = q.src; + const nir_def *def = q.def; - if (nir_src_is_const(instr->src[src].src)) { - *result = pack_data(analyze_constant(instr, src)); + if (nir_def_is_const(def)) { + *result = pack_data(analyze_fp_constant(nir_def_as_load_const(def))); return; } - if (!nir_src_is_alu(instr->src[src].src)) { + if (!nir_def_is_alu(def)) { *result = pack_data((struct fp_result_range){ unknown, false, false, false }); return; } - const struct nir_alu_instr *const alu = - nir_def_as_alu(instr->src[src].src.ssa); + const nir_alu_instr *const alu = nir_def_as_alu(def); if (!aq->pushed_queries) { switch (alu->op) { case nir_op_bcsel: - push_fp_query(state, alu, 1); - push_fp_query(state, alu, 2); + push_fp_query(state, alu->src[1].src.ssa); + push_fp_query(state, alu->src[2].src.ssa); return; case nir_op_mov: - push_fp_query(state, alu, 0); - return; - case nir_op_vec2: - push_fp_query(state, alu, 0); - push_fp_query(state, alu, 1); - return; case nir_op_fabs: case nir_op_fexp2: case nir_op_frcp: @@ -536,7 +509,7 @@ process_fp_query(struct analysis_state *state, struct analysis_query *aq, uint32 case nir_op_fdot4_replicated: case nir_op_fdot8_replicated: case nir_op_fdot16_replicated: - push_fp_query(state, alu, 0); + push_fp_query(state, alu->src[0].src.ssa); return; case nir_op_fadd: case nir_op_fmax: @@ -544,15 +517,16 @@ process_fp_query(struct analysis_state *state, struct analysis_query *aq, uint32 case nir_op_fmul: case nir_op_fmulz: case nir_op_fpow: - push_fp_query(state, alu, 0); - push_fp_query(state, alu, 1); + case nir_op_vec2: + push_fp_query(state, alu->src[0].src.ssa); + push_fp_query(state, alu->src[1].src.ssa); return; case nir_op_ffma: case nir_op_ffmaz: case nir_op_flrp: - push_fp_query(state, alu, 0); - push_fp_query(state, alu, 1); - push_fp_query(state, alu, 2); + push_fp_query(state, alu->src[0].src.ssa); + push_fp_query(state, alu->src[1].src.ssa); + push_fp_query(state, alu->src[2].src.ssa); return; default: break; @@ -1347,8 +1321,7 @@ process_fp_query(struct analysis_state *state, struct analysis_query *aq, uint32 #undef _______ struct fp_result_range -nir_analyze_fp_range(struct hash_table *range_ht, - const nir_alu_instr *alu, unsigned src) +nir_analyze_fp_range(struct hash_table *range_ht, const nir_def *def) { struct fp_query query_alloc[64]; uint32_t result_alloc[64]; @@ -1361,7 +1334,7 @@ nir_analyze_fp_range(struct hash_table *range_ht, state.get_key = &get_fp_key; state.process_query = &process_fp_query; - push_fp_query(&state, alu, src); + push_fp_query(&state, def); return unpack_data(perform_analysis(&state)); } diff --git a/src/compiler/nir/nir_range_analysis.h b/src/compiler/nir/nir_range_analysis.h index f2cc2f94076..75b1ce3f0f0 100644 --- a/src/compiler/nir/nir_range_analysis.h +++ b/src/compiler/nir/nir_range_analysis.h @@ -55,8 +55,7 @@ extern "C" { #endif struct fp_result_range -nir_analyze_fp_range(struct hash_table *range_ht, - const nir_alu_instr *instr, unsigned src); +nir_analyze_fp_range(struct hash_table *range_ht, const nir_def *def); uint64_t nir_def_bits_used(const nir_def *def); diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index 508f05c6e5b..53557f2ce05 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -895,7 +895,7 @@ static inline bool is_integral(const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range r = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range r = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return r.is_integral; } @@ -908,7 +908,7 @@ is_finite(UNUSED const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.is_finite; } @@ -918,29 +918,29 @@ is_finite_not_zero(UNUSED const nir_search_state *state, const nir_alu_instr *in unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.is_finite && (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero); } -#define RELATION(r) \ - static inline bool \ - is_##r(const nir_search_state *state, const nir_alu_instr *instr, \ - unsigned src, UNUSED unsigned num_components, \ - UNUSED const uint8_t *swizzle) \ - { \ - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); \ - return v.range == r; \ - } \ - \ - static inline bool \ - is_a_number_##r(const nir_search_state *state, const nir_alu_instr *instr, \ - unsigned src, UNUSED unsigned num_components, \ - UNUSED const uint8_t *swizzle) \ - { \ - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); \ - return v.is_a_number && v.range == r; \ +#define RELATION(r) \ + static inline bool \ + is_##r(const nir_search_state *state, const nir_alu_instr *instr, \ + unsigned src, UNUSED unsigned num_components, \ + UNUSED const uint8_t *swizzle) \ + { \ + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); \ + return v.range == r; \ + } \ + \ + static inline bool \ + is_a_number_##r(const nir_search_state *state, const nir_alu_instr *instr, \ + unsigned src, UNUSED unsigned num_components, \ + UNUSED const uint8_t *swizzle) \ + { \ + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); \ + return v.is_a_number && v.range == r; \ } RELATION(lt_zero) @@ -953,7 +953,7 @@ static inline bool is_not_negative(const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero; } @@ -962,7 +962,7 @@ is_a_number_not_negative(const nir_search_state *state, const nir_alu_instr *ins unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.is_a_number && (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero); } @@ -971,7 +971,7 @@ static inline bool is_not_positive(const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.range == le_zero || v.range == lt_zero || v.range == eq_zero; } @@ -980,7 +980,7 @@ is_a_number_not_positive(const nir_search_state *state, const nir_alu_instr *ins unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.is_a_number && (v.range == le_zero || v.range == lt_zero || v.range == eq_zero); } @@ -989,7 +989,7 @@ static inline bool is_not_zero(const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero; } @@ -998,7 +998,7 @@ is_a_number_not_zero(const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.is_a_number && (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero); } @@ -1007,7 +1007,7 @@ static inline bool is_a_number(const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr, src); + const struct fp_result_range v = nir_analyze_fp_range(state->range_ht, instr->src[src].src.ssa); return v.is_a_number; }