nir: Keep the range analysis HT around intra-pass until we make a change.
authorEric Anholt <eric@anholt.net>
Mon, 23 Sep 2019 22:40:46 +0000 (15:40 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 4 Oct 2019 19:15:01 +0000 (19:15 +0000)
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 <ian.d.romanick@intel.com>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
src/compiler/nir/nir_algebraic.py
src/compiler/nir/nir_opt_comparison_pre.c
src/compiler/nir/nir_range_analysis.c
src/compiler/nir/nir_range_analysis.h
src/compiler/nir/nir_search.c
src/compiler/nir/nir_search.h
src/compiler/nir/nir_search_helpers.h

index fe66952ba16fce8623f563b27517100139023eb5..1645ec50fcd31a20168b4b0d60455225a352f7b7 100644 (file)
@@ -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) {
index a74dfa8939a1500846dc0cdf13c5ad230b726aaa..8e1a80338ed9dfaa18d8bd23ebf7b44fd16328ed 100644 (file)
@@ -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;
index 758d427f599d8c78678e9bcfd64db219efdda5a9..b40c87081c363f294fff6f47ef420eb5f4421c66 100644 (file)
@@ -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));
 }
index 240ae74cf6c4fe76e98f4ebcf18885f4253bed69..f5d12bfbf9f9cbcb311f2a30c31c1104b69af32a 100644 (file)
@@ -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_ */
index de5a8d25adaf6372db4664cdcf9e2c3484559867..d126319b256d472987f7927bec7515b6364b2fed 100644 (file)
@@ -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);
 
index ac37f1ac6534bb6ff31e249aaff0f27c0f6710a0..c86efc5ba3fffaee840857c3098292d991849b50 100644 (file)
@@ -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);
 
index e2a436be6b734824072b0c7d172a1f51f147f87d..a52104c7109007c47a142fbfc7f1a60d89f1e936 100644 (file)
@@ -33,7 +33,8 @@
 #include <math.h>
 
 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;
 }