From c23db0df1893ee755d7c4ed182ba734a019afe43 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 23 Sep 2019 15:40:46 -0700 Subject: [PATCH] nir: Keep the range analysis HT around intra-pass until we make a change. This lets us memoize range analysis work across instructions. Reduces runtime of shader-db on Intel by -30.0288% +/- 2.1693% (n=3). Fixes: 405de7ccb6cb ("nir/range-analysis: Rudimentary value range analysis pass") Reviewed-by: Ian Romanick Reviewed-by: Connor Abbott --- src/compiler/nir/nir_algebraic.py | 9 +++- src/compiler/nir/nir_opt_comparison_pre.c | 4 +- src/compiler/nir/nir_range_analysis.c | 13 ++---- src/compiler/nir/nir_range_analysis.h | 3 +- src/compiler/nir/nir_search.c | 6 ++- src/compiler/nir/nir_search.h | 3 +- src/compiler/nir/nir_search_helpers.h | 52 +++++++++++++---------- 7 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/compiler/nir/nir_algebraic.py b/src/compiler/nir/nir_algebraic.py index fe66952ba16..1645ec50fcd 100644 --- a/src/compiler/nir/nir_algebraic.py +++ b/src/compiler/nir/nir_algebraic.py @@ -1155,6 +1155,7 @@ ${pass_name}_pre_block(nir_block *block, uint16_t *states) static bool ${pass_name}_block(nir_builder *build, nir_block *block, + struct hash_table *range_ht, const uint16_t *states, const bool *condition_flags) { bool progress = false; @@ -1181,7 +1182,8 @@ ${pass_name}_block(nir_builder *build, nir_block *block, const struct transform *xform = &${pass_name}_state${i}_xforms[i]; if (condition_flags[xform->condition_offset] && !(xform->search->inexact && ignore_inexact) && - nir_replace_instr(build, alu, xform->search, xform->replace)) { + nir_replace_instr(build, alu, range_ht, xform->search, xform->replace)) { + _mesa_hash_table_clear(range_ht, NULL); progress = true; break; } @@ -1210,14 +1212,17 @@ ${pass_name}_impl(nir_function_impl *impl, const bool *condition_flags) */ uint16_t *states = calloc(impl->ssa_alloc, sizeof(*states)); + struct hash_table *range_ht = _mesa_pointer_hash_table_create(NULL); + nir_foreach_block(block, impl) { ${pass_name}_pre_block(block, states); } nir_foreach_block_reverse(block, impl) { - progress |= ${pass_name}_block(&build, block, states, condition_flags); + progress |= ${pass_name}_block(&build, block, range_ht, states, condition_flags); } + ralloc_free(range_ht); free(states); if (progress) { diff --git a/src/compiler/nir/nir_opt_comparison_pre.c b/src/compiler/nir/nir_opt_comparison_pre.c index a74dfa8939a..8e1a80338ed 100644 --- a/src/compiler/nir/nir_opt_comparison_pre.c +++ b/src/compiler/nir/nir_opt_comparison_pre.c @@ -325,8 +325,8 @@ comparison_pre_block(nir_block *block, struct block_queue *bq, nir_builder *bld) * and neither operand is immediate value 0, add it to the set. */ if (is_used_by_if(alu) && - is_not_const_zero(alu, 0, 1, swizzle) && - is_not_const_zero(alu, 1, 1, swizzle)) + is_not_const_zero(NULL, alu, 0, 1, swizzle) && + is_not_const_zero(NULL, alu, 1, 1, swizzle)) add_instruction_for_block(bi, alu); break; diff --git a/src/compiler/nir/nir_range_analysis.c b/src/compiler/nir/nir_range_analysis.c index 758d427f599..b40c87081c3 100644 --- a/src/compiler/nir/nir_range_analysis.c +++ b/src/compiler/nir/nir_range_analysis.c @@ -1028,14 +1028,9 @@ analyze_expression(const nir_alu_instr *instr, unsigned src, #undef _______ struct ssa_result_range -nir_analyze_range(const nir_alu_instr *instr, unsigned src) +nir_analyze_range(struct hash_table *range_ht, + const nir_alu_instr *instr, unsigned src) { - struct hash_table *ht = _mesa_pointer_hash_table_create(NULL); - - const struct ssa_result_range r = - analyze_expression(instr, src, ht, nir_alu_src_type(instr, src)); - - _mesa_hash_table_destroy(ht, NULL); - - return r; + return analyze_expression(instr, src, range_ht, + nir_alu_src_type(instr, src)); } diff --git a/src/compiler/nir/nir_range_analysis.h b/src/compiler/nir/nir_range_analysis.h index 240ae74cf6c..f5d12bfbf9f 100644 --- a/src/compiler/nir/nir_range_analysis.h +++ b/src/compiler/nir/nir_range_analysis.h @@ -42,6 +42,7 @@ struct ssa_result_range { }; extern struct ssa_result_range -nir_analyze_range(const nir_alu_instr *instr, unsigned src); +nir_analyze_range(struct hash_table *range_ht, + const nir_alu_instr *instr, unsigned src); #endif /* _NIR_RANGE_ANALYSIS_H_ */ diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c index de5a8d25ada..d126319b256 100644 --- a/src/compiler/nir/nir_search.c +++ b/src/compiler/nir/nir_search.c @@ -39,6 +39,7 @@ struct match_state { uint8_t comm_op_direction; unsigned variables_seen; nir_alu_src variables[NIR_SEARCH_MAX_VARIABLES]; + struct hash_table *range_ht; }; static bool @@ -297,7 +298,8 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src, instr->src[src].src.ssa->parent_instr->type != nir_instr_type_load_const) return false; - if (var->cond && !var->cond(instr, src, num_components, new_swizzle)) + if (var->cond && !var->cond(state->range_ht, instr, + src, num_components, new_swizzle)) return false; if (var->type != nir_type_invalid && @@ -621,6 +623,7 @@ UNUSED static void dump_value(const nir_search_value *val) nir_ssa_def * nir_replace_instr(nir_builder *build, nir_alu_instr *instr, + struct hash_table *range_ht, const nir_search_expression *search, const nir_search_value *replace) { @@ -634,6 +637,7 @@ nir_replace_instr(nir_builder *build, nir_alu_instr *instr, struct match_state state; state.inexact_match = false; state.has_exact_alu = false; + state.range_ht = range_ht; STATIC_ASSERT(sizeof(state.comm_op_direction) * 8 >= NIR_SEARCH_MAX_COMM_OPS); diff --git a/src/compiler/nir/nir_search.h b/src/compiler/nir/nir_search.h index ac37f1ac653..c86efc5ba3f 100644 --- a/src/compiler/nir/nir_search.h +++ b/src/compiler/nir/nir_search.h @@ -93,7 +93,7 @@ typedef struct { * variables to require, for example, power-of-two in order for the search * to match. */ - bool (*cond)(nir_alu_instr *instr, unsigned src, + bool (*cond)(struct hash_table *range_ht, nir_alu_instr *instr, unsigned src, unsigned num_components, const uint8_t *swizzle); /** Swizzle (for replace only) */ @@ -175,6 +175,7 @@ NIR_DEFINE_CAST(nir_search_value_as_expression, nir_search_value, nir_ssa_def * nir_replace_instr(struct nir_builder *b, nir_alu_instr *instr, + struct hash_table *range_ht, const nir_search_expression *search, const nir_search_value *replace); diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index e2a436be6b7..a52104c7109 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -33,7 +33,8 @@ #include static inline bool -is_pos_power_of_two(nir_alu_instr *instr, unsigned src, unsigned num_components, +is_pos_power_of_two(UNUSED struct hash_table *ht, nir_alu_instr *instr, + unsigned src, unsigned num_components, const uint8_t *swizzle) { /* only constant srcs: */ @@ -63,7 +64,8 @@ is_pos_power_of_two(nir_alu_instr *instr, unsigned src, unsigned num_components, } static inline bool -is_neg_power_of_two(nir_alu_instr *instr, unsigned src, unsigned num_components, +is_neg_power_of_two(UNUSED struct hash_table *ht, nir_alu_instr *instr, + unsigned src, unsigned num_components, const uint8_t *swizzle) { /* only constant srcs: */ @@ -87,7 +89,8 @@ is_neg_power_of_two(nir_alu_instr *instr, unsigned src, unsigned num_components, } static inline bool -is_zero_to_one(nir_alu_instr *instr, unsigned src, unsigned num_components, +is_zero_to_one(UNUSED struct hash_table *ht, nir_alu_instr *instr, unsigned src, + unsigned num_components, const uint8_t *swizzle) { /* only constant srcs: */ @@ -117,7 +120,8 @@ is_zero_to_one(nir_alu_instr *instr, unsigned src, unsigned num_components, * 1 while this function tests 0 < src < 1. */ static inline bool -is_gt_0_and_lt_1(nir_alu_instr *instr, unsigned src, unsigned num_components, +is_gt_0_and_lt_1(UNUSED struct hash_table *ht, nir_alu_instr *instr, + unsigned src, unsigned num_components, const uint8_t *swizzle) { /* only constant srcs: */ @@ -141,7 +145,8 @@ is_gt_0_and_lt_1(nir_alu_instr *instr, unsigned src, unsigned num_components, } static inline bool -is_not_const_zero(nir_alu_instr *instr, unsigned src, unsigned num_components, +is_not_const_zero(UNUSED struct hash_table *ht, nir_alu_instr *instr, + unsigned src, unsigned num_components, const uint8_t *swizzle) { if (nir_src_as_const_value(instr->src[src].src) == NULL) @@ -168,14 +173,15 @@ is_not_const_zero(nir_alu_instr *instr, unsigned src, unsigned num_components, } static inline bool -is_not_const(nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, +is_not_const(UNUSED struct hash_table *ht, nir_alu_instr *instr, unsigned src, + UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { return !nir_src_is_const(instr->src[src].src); } static inline bool -is_not_fmul(nir_alu_instr *instr, unsigned src, +is_not_fmul(struct hash_table *ht, nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { nir_alu_instr *src_alu = @@ -185,7 +191,7 @@ is_not_fmul(nir_alu_instr *instr, unsigned src, return true; if (src_alu->op == nir_op_fneg) - return is_not_fmul(src_alu, 0, 0, NULL); + return is_not_fmul(ht, src_alu, 0, 0, NULL); return src_alu->op != nir_op_fmul; } @@ -207,10 +213,10 @@ is_fsign(nir_alu_instr *instr, unsigned src, } static inline bool -is_not_const_and_not_fsign(nir_alu_instr *instr, unsigned src, +is_not_const_and_not_fsign(struct hash_table *ht, nir_alu_instr *instr, unsigned src, unsigned num_components, const uint8_t *swizzle) { - return is_not_const(instr, src, num_components, swizzle) && + return is_not_const(ht, instr, src, num_components, swizzle) && !is_fsign(instr, src, num_components, swizzle); } @@ -273,7 +279,8 @@ is_used_by_non_fsat(nir_alu_instr *instr) * of all its components is zero. */ static inline bool -is_upper_half_zero(nir_alu_instr *instr, unsigned src, +is_upper_half_zero(UNUSED struct hash_table *ht, + nir_alu_instr *instr, unsigned src, unsigned num_components, const uint8_t *swizzle) { if (nir_src_as_const_value(instr->src[src].src) == NULL) @@ -297,7 +304,8 @@ is_upper_half_zero(nir_alu_instr *instr, unsigned src, * of all its components is zero. */ static inline bool -is_lower_half_zero(nir_alu_instr *instr, unsigned src, +is_lower_half_zero(UNUSED struct hash_table *ht, + nir_alu_instr *instr, unsigned src, unsigned num_components, const uint8_t *swizzle) { if (nir_src_as_const_value(instr->src[src].src) == NULL) @@ -326,20 +334,20 @@ no_unsigned_wrap(nir_alu_instr *instr) } static inline bool -is_integral(nir_alu_instr *instr, unsigned src, +is_integral(struct hash_table *ht, nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct ssa_result_range r = nir_analyze_range(instr, src); + const struct ssa_result_range r = nir_analyze_range(ht, instr, src); return r.is_integral; } #define RELATION(r) \ static inline bool \ -is_ ## r (nir_alu_instr *instr, unsigned src, \ +is_ ## r (struct hash_table *ht, nir_alu_instr *instr, unsigned src, \ UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) \ { \ - const struct ssa_result_range v = nir_analyze_range(instr, src); \ + const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \ return v.range == r; \ } @@ -350,26 +358,26 @@ RELATION(ge_zero) RELATION(ne_zero) static inline bool -is_not_negative(nir_alu_instr *instr, unsigned src, +is_not_negative(struct hash_table *ht, nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct ssa_result_range v = nir_analyze_range(instr, src); + const struct ssa_result_range v = nir_analyze_range(ht, instr, src); return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero; } static inline bool -is_not_positive(nir_alu_instr *instr, unsigned src, +is_not_positive(struct hash_table *ht, nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct ssa_result_range v = nir_analyze_range(instr, src); + const struct ssa_result_range v = nir_analyze_range(ht, instr, src); return v.range == le_zero || v.range == lt_zero || v.range == eq_zero; } static inline bool -is_not_zero(nir_alu_instr *instr, unsigned src, +is_not_zero(struct hash_table *ht, nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) { - const struct ssa_result_range v = nir_analyze_range(instr, src); + const struct ssa_result_range v = nir_analyze_range(ht, instr, src); return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero; } -- 2.30.2