[Mesa-dev] [PATCH 5/7] nir/search: Add support for "compact" expressions

Jason Ekstrand jason at jlekstrand.net
Fri May 27 01:30:35 UTC 2016


This form of expressions takes less space by replacing the potentially
64-bit pointers with 16-bit indices into an array of a union type.
---
 src/compiler/nir/nir_algebraic.py |  2 +-
 src/compiler/nir/nir_search.c     | 70 +++++++++++++++++++++++++++------------
 src/compiler/nir/nir_search.h     | 26 ++++++++++++++-
 3 files changed, 75 insertions(+), 23 deletions(-)

diff --git a/src/compiler/nir/nir_algebraic.py b/src/compiler/nir/nir_algebraic.py
index b4df8c8..9b89828 100644
--- a/src/compiler/nir/nir_algebraic.py
+++ b/src/compiler/nir/nir_algebraic.py
@@ -539,7 +539,7 @@ ${pass_name}_block(nir_block *block, const bool *condition_flags,
             const struct transform *xform = &${pass_name}_${opcode}_xforms[i];
             if (condition_flags[xform->condition_offset] &&
                 nir_replace_instr(alu, xform->search, xform->replace,
-                                  mem_ctx)) {
+                                  NULL, mem_ctx)) {
                progress = true;
                break;
             }
diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c
index 6e8c829d..fb73cdb 100644
--- a/src/compiler/nir/nir_search.c
+++ b/src/compiler/nir/nir_search.c
@@ -33,6 +33,7 @@ struct match_state {
    bool has_exact_alu;
    unsigned variables_seen;
    nir_alu_src variables[NIR_SEARCH_MAX_VARIABLES];
+   const nir_search_value_union *values;
 };
 
 static bool
@@ -95,6 +96,7 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
 
    switch (value->type) {
    case nir_search_value_expression:
+   case nir_search_value_compact_expression:
       if (!instr->src[src].src.is_ssa)
          return false;
 
@@ -238,23 +240,44 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
    }
 }
 
+static nir_search_expression
+value_to_expression(const nir_search_value *val, struct match_state *state)
+{
+   if (val->type == nir_search_value_expression) {
+      return *nir_search_value_as_expression(val);
+   } else {
+      assert(val->type == nir_search_value_compact_expression);
+      nir_search_compact_expression *compact =
+         nir_search_value_as_compact_expression(val);
+
+      nir_search_expression expr;
+      expr.value = compact->value;
+      expr.inexact = compact->inexact;
+      expr.opcode = compact->opcode;
+      for (unsigned i = 0; i < 4; i++)
+         expr.srcs[i] = &state->values[compact->srcs[i]].value;
+
+      return expr;
+   }
+}
+
 static bool
 match_expression(const nir_search_value *expr_val, nir_alu_instr *instr,
                  unsigned num_components, const uint8_t *swizzle,
                  struct match_state *state)
 {
-   nir_search_expression *expr = nir_search_value_as_expression(expr_val);
+   const nir_search_expression expr = value_to_expression(expr_val, state);
 
-   if (instr->op != expr->opcode)
+   if (instr->op != expr.opcode)
       return false;
 
    assert(instr->dest.dest.is_ssa);
 
-   if (expr->value.bit_size &&
-       instr->dest.dest.ssa.bit_size != expr->value.bit_size)
+   if (expr.value.bit_size &&
+       instr->dest.dest.ssa.bit_size != expr.value.bit_size)
       return false;
 
-   state->inexact_match = expr->inexact || state->inexact_match;
+   state->inexact_match = expr.inexact || state->inexact_match;
    state->has_exact_alu = instr->exact || state->has_exact_alu;
    if (state->inexact_match && state->has_exact_alu)
       return false;
@@ -282,7 +305,7 @@ match_expression(const nir_search_value *expr_val, nir_alu_instr *instr,
 
    bool matched = true;
    for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
-      if (!match_value(expr->srcs[i], instr, i, num_components,
+      if (!match_value(expr.srcs[i], instr, i, num_components,
                        swizzle, state)) {
          matched = false;
          break;
@@ -301,11 +324,11 @@ match_expression(const nir_search_value *expr_val, nir_alu_instr *instr,
        */
       state->variables_seen = variables_seen_stash;
 
-      if (!match_value(expr->srcs[0], instr, 1, num_components,
+      if (!match_value(expr.srcs[0], instr, 1, num_components,
                        swizzle, state))
          return false;
 
-      return match_value(expr->srcs[1], instr, 0, num_components,
+      return match_value(expr.srcs[1], instr, 0, num_components,
                          swizzle, state);
    } else {
       return false;
@@ -331,16 +354,17 @@ build_bitsize_tree(void *mem_ctx, struct match_state *state,
    bitsize_tree *tree = ralloc(mem_ctx, bitsize_tree);
 
    switch (value->type) {
-   case nir_search_value_expression: {
-      nir_search_expression *expr = nir_search_value_as_expression(value);
-      nir_op_info info = nir_op_infos[expr->opcode];
+   case nir_search_value_expression:
+   case nir_search_value_compact_expression: {
+      const nir_search_expression expr = value_to_expression(value, state);
+      nir_op_info info = nir_op_infos[expr.opcode];
       tree->num_srcs = info.num_inputs;
       tree->common_size = 0;
       for (unsigned i = 0; i < info.num_inputs; i++) {
          tree->is_src_sized[i] = !!nir_alu_type_get_type_size(info.input_types[i]);
          if (tree->is_src_sized[i])
             tree->src_size[i] = nir_alu_type_get_type_size(info.input_types[i]);
-         tree->srcs[i] = build_bitsize_tree(mem_ctx, state, expr->srcs[i]);
+         tree->srcs[i] = build_bitsize_tree(mem_ctx, state, expr.srcs[i]);
       }
       tree->is_dest_sized = !!nir_alu_type_get_type_size(info.output_type);
       if (tree->is_dest_sized)
@@ -437,13 +461,14 @@ construct_value(const nir_search_value *value,
                 nir_instr *instr, void *mem_ctx)
 {
    switch (value->type) {
-   case nir_search_value_expression: {
-      const nir_search_expression *expr = nir_search_value_as_expression(value);
+   case nir_search_value_expression:
+   case nir_search_value_compact_expression: {
+      const nir_search_expression expr = value_to_expression(value, state);
 
-      if (nir_op_infos[expr->opcode].output_size != 0)
-         num_components = nir_op_infos[expr->opcode].output_size;
+      if (nir_op_infos[expr.opcode].output_size != 0)
+         num_components = nir_op_infos[expr.opcode].output_size;
 
-      nir_alu_instr *alu = nir_alu_instr_create(mem_ctx, expr->opcode);
+      nir_alu_instr *alu = nir_alu_instr_create(mem_ctx, expr.opcode);
       nir_ssa_dest_init(&alu->instr, &alu->dest.dest, num_components,
                         bitsize->dest_size, NULL);
       alu->dest.write_mask = (1 << num_components) - 1;
@@ -456,14 +481,14 @@ construct_value(const nir_search_value *value,
        */
       alu->exact = state->has_exact_alu;
 
-      for (unsigned i = 0; i < nir_op_infos[expr->opcode].num_inputs; i++) {
+      for (unsigned i = 0; i < nir_op_infos[expr.opcode].num_inputs; i++) {
          /* If the source is an explicitly sized source, then we need to reset
           * the number of components to match.
           */
          if (nir_op_infos[alu->op].input_sizes[i] != 0)
             num_components = nir_op_infos[alu->op].input_sizes[i];
 
-         alu->src[i] = construct_value(expr->srcs[i],
+         alu->src[i] = construct_value(expr.srcs[i],
                                        num_components, bitsize->srcs[i],
                                        state, instr, mem_ctx);
       }
@@ -564,9 +589,11 @@ construct_value(const nir_search_value *value,
 
 nir_alu_instr *
 nir_replace_instr(nir_alu_instr *instr, const nir_search_value *search,
-                  const nir_search_value *replace, void *mem_ctx)
+                  const nir_search_value *replace,
+                  const nir_search_value_union *values, void *mem_ctx)
 {
-   assert(search->type == nir_search_value_expression);
+   assert(search->type == nir_search_value_expression ||
+          search->type == nir_search_value_compact_expression);
 
    uint8_t swizzle[4] = { 0, 0, 0, 0 };
 
@@ -579,6 +606,7 @@ nir_replace_instr(nir_alu_instr *instr, const nir_search_value *search,
    state.inexact_match = false;
    state.has_exact_alu = false;
    state.variables_seen = 0;
+   state.values = values;
 
    if (!match_expression(search, instr, instr->dest.dest.ssa.num_components,
                          swizzle, &state))
diff --git a/src/compiler/nir/nir_search.h b/src/compiler/nir/nir_search.h
index b97522a..1588628 100644
--- a/src/compiler/nir/nir_search.h
+++ b/src/compiler/nir/nir_search.h
@@ -34,6 +34,7 @@
 
 typedef enum {
    nir_search_value_expression,
+   nir_search_value_compact_expression,
    nir_search_value_variable,
    nir_search_value_constant,
 } nir_search_value_type;
@@ -95,15 +96,38 @@ typedef struct {
    const nir_search_value *srcs[4];
 } nir_search_expression;
 
+typedef struct {
+   nir_search_value value;
+
+   /* When set on a search expression, the expression will only match an SSA
+    * value that does *not* have the exact bit set.  If unset, the exact bit
+    * on the SSA value is ignored.
+    */
+   bool inexact:1;
+
+   nir_op opcode:15;
+   uint16_t srcs[4];
+} nir_search_compact_expression;
+
+typedef union {
+   nir_search_value value;
+   nir_search_variable variable;
+   nir_search_constant constant;
+   nir_search_compact_expression expression;
+} nir_search_value_union;
+
 NIR_DEFINE_CAST(nir_search_value_as_variable, nir_search_value,
                 nir_search_variable, value)
 NIR_DEFINE_CAST(nir_search_value_as_constant, nir_search_value,
                 nir_search_constant, value)
 NIR_DEFINE_CAST(nir_search_value_as_expression, nir_search_value,
                 nir_search_expression, value)
+NIR_DEFINE_CAST(nir_search_value_as_compact_expression, nir_search_value,
+                nir_search_compact_expression, value)
 
 nir_alu_instr *
 nir_replace_instr(nir_alu_instr *instr, const nir_search_value *search,
-                  const nir_search_value *replace, void *mem_ctx);
+                  const nir_search_value *replace,
+                  const nir_search_value_union *values, void *mem_ctx);
 
 #endif /* _NIR_SEARCH_ */
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list