1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2014 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Jason Ekstrand (jason@jlekstrand.net)
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#ifndef _NIR_SEARCH_
29bf215546Sopenharmony_ci#define _NIR_SEARCH_
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "nir.h"
32bf215546Sopenharmony_ci#include "nir_worklist.h"
33bf215546Sopenharmony_ci#include "util/u_dynarray.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#define NIR_SEARCH_MAX_VARIABLES 16
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cistruct nir_builder;
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_citypedef enum PACKED {
40bf215546Sopenharmony_ci   nir_search_value_expression,
41bf215546Sopenharmony_ci   nir_search_value_variable,
42bf215546Sopenharmony_ci   nir_search_value_constant,
43bf215546Sopenharmony_ci} nir_search_value_type;
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_citypedef struct {
46bf215546Sopenharmony_ci   nir_search_value_type type;
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   /**
49bf215546Sopenharmony_ci    * Bit size of the value. It is interpreted as follows:
50bf215546Sopenharmony_ci    *
51bf215546Sopenharmony_ci    * For a search expression:
52bf215546Sopenharmony_ci    * - If bit_size > 0, then the value only matches an SSA value with the
53bf215546Sopenharmony_ci    *   given bit size.
54bf215546Sopenharmony_ci    * - If bit_size <= 0, then the value matches any size SSA value.
55bf215546Sopenharmony_ci    *
56bf215546Sopenharmony_ci    * For a replace expression:
57bf215546Sopenharmony_ci    * - If bit_size > 0, then the value is constructed with the given bit size.
58bf215546Sopenharmony_ci    * - If bit_size == 0, then the value is constructed with the same bit size
59bf215546Sopenharmony_ci    *   as the search value.
60bf215546Sopenharmony_ci    * - If bit_size < 0, then the value is constructed with the same bit size
61bf215546Sopenharmony_ci    *   as variable (-bit_size - 1).
62bf215546Sopenharmony_ci    */
63bf215546Sopenharmony_ci   int8_t bit_size;
64bf215546Sopenharmony_ci} nir_search_value;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_citypedef struct {
67bf215546Sopenharmony_ci   nir_search_value value;
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   /** The variable index;  Must be less than NIR_SEARCH_MAX_VARIABLES */
70bf215546Sopenharmony_ci   uint8_t variable : 7;
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   /** Indicates that the given variable must be a constant
73bf215546Sopenharmony_ci    *
74bf215546Sopenharmony_ci    * This is only allowed in search expressions and indicates that the
75bf215546Sopenharmony_ci    * given variable is only allowed to match constant values.
76bf215546Sopenharmony_ci    */
77bf215546Sopenharmony_ci   bool is_constant : 1;
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   /** Indicates that the given variable must have a certain type
80bf215546Sopenharmony_ci    *
81bf215546Sopenharmony_ci    * This is only allowed in search expressions and indicates that the
82bf215546Sopenharmony_ci    * given variable is only allowed to match values that come from an ALU
83bf215546Sopenharmony_ci    * instruction with the given output type.  A type of nir_type_void
84bf215546Sopenharmony_ci    * means it can match any type.
85bf215546Sopenharmony_ci    *
86bf215546Sopenharmony_ci    * Note: A variable that is both constant and has a non-void type will
87bf215546Sopenharmony_ci    * never match anything.
88bf215546Sopenharmony_ci    */
89bf215546Sopenharmony_ci   nir_alu_type type;
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   /** Optional table->variable_cond[] fxn ptr index
92bf215546Sopenharmony_ci    *
93bf215546Sopenharmony_ci    * This is only allowed in search expressions, and allows additional
94bf215546Sopenharmony_ci    * constraints to be placed on the match.  Typically used for 'is_constant'
95bf215546Sopenharmony_ci    * variables to require, for example, power-of-two in order for the search
96bf215546Sopenharmony_ci    * to match.
97bf215546Sopenharmony_ci    */
98bf215546Sopenharmony_ci   int16_t cond_index;
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   /** Swizzle (for replace only) */
101bf215546Sopenharmony_ci   uint8_t swizzle[NIR_MAX_VEC_COMPONENTS];
102bf215546Sopenharmony_ci} nir_search_variable;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_citypedef struct {
105bf215546Sopenharmony_ci   nir_search_value value;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   nir_alu_type type;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   union {
110bf215546Sopenharmony_ci      uint64_t u;
111bf215546Sopenharmony_ci      int64_t i;
112bf215546Sopenharmony_ci      double d;
113bf215546Sopenharmony_ci   } data;
114bf215546Sopenharmony_ci} nir_search_constant;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_cienum nir_search_op {
117bf215546Sopenharmony_ci   nir_search_op_i2f = nir_last_opcode + 1,
118bf215546Sopenharmony_ci   nir_search_op_u2f,
119bf215546Sopenharmony_ci   nir_search_op_f2f,
120bf215546Sopenharmony_ci   nir_search_op_f2u,
121bf215546Sopenharmony_ci   nir_search_op_f2i,
122bf215546Sopenharmony_ci   nir_search_op_u2u,
123bf215546Sopenharmony_ci   nir_search_op_i2i,
124bf215546Sopenharmony_ci   nir_search_op_b2f,
125bf215546Sopenharmony_ci   nir_search_op_b2i,
126bf215546Sopenharmony_ci   nir_search_op_i2b,
127bf215546Sopenharmony_ci   nir_search_op_f2b,
128bf215546Sopenharmony_ci   nir_num_search_ops,
129bf215546Sopenharmony_ci};
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ciuint16_t nir_search_op_for_nir_op(nir_op op);
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_citypedef struct {
134bf215546Sopenharmony_ci   nir_search_value value;
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   /* When set on a search expression, the expression will only match an SSA
137bf215546Sopenharmony_ci    * value that does *not* have the exact bit set.  If unset, the exact bit
138bf215546Sopenharmony_ci    * on the SSA value is ignored.
139bf215546Sopenharmony_ci    */
140bf215546Sopenharmony_ci   bool inexact : 1;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   /** In a replacement, requests that the instruction be marked exact. */
143bf215546Sopenharmony_ci   bool exact : 1;
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   /** Don't make the replacement exact if the search expression is exact. */
146bf215546Sopenharmony_ci   bool ignore_exact : 1;
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   /* One of nir_op or nir_search_op */
149bf215546Sopenharmony_ci   uint16_t opcode : 13;
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   /* Commutative expression index.  This is assigned by opt_algebraic.py when
152bf215546Sopenharmony_ci    * search structures are constructed and is a unique (to this structure)
153bf215546Sopenharmony_ci    * index within the commutative operation bitfield used for searching for
154bf215546Sopenharmony_ci    * all combinations of expressions containing commutative operations.
155bf215546Sopenharmony_ci    */
156bf215546Sopenharmony_ci   int8_t comm_expr_idx;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   /* Number of commutative expressions in this expression including this one
159bf215546Sopenharmony_ci    * (if it is commutative).
160bf215546Sopenharmony_ci    */
161bf215546Sopenharmony_ci   uint8_t comm_exprs;
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   /* Index in table->values[] for the expression operands */
164bf215546Sopenharmony_ci   uint16_t srcs[4];
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   /** Optional table->expression_cond[] fxn ptr index
167bf215546Sopenharmony_ci    *
168bf215546Sopenharmony_ci    * This allows additional constraints on expression matching, it is
169bf215546Sopenharmony_ci    * typically used to match an expressions uses such as the number of times
170bf215546Sopenharmony_ci    * the expression is used, and whether its used by an if.
171bf215546Sopenharmony_ci    */
172bf215546Sopenharmony_ci   int16_t cond_index;
173bf215546Sopenharmony_ci} nir_search_expression;
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_cistruct per_op_table {
176bf215546Sopenharmony_ci   const uint16_t *filter;
177bf215546Sopenharmony_ci   unsigned num_filtered_states;
178bf215546Sopenharmony_ci   const uint16_t *table;
179bf215546Sopenharmony_ci};
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_cistruct transform {
182bf215546Sopenharmony_ci   uint16_t search; /* Index in table->values[] for the search expression. */
183bf215546Sopenharmony_ci   uint16_t replace; /* Index in table->values[] for the replace value. */
184bf215546Sopenharmony_ci   unsigned condition_offset;
185bf215546Sopenharmony_ci};
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_citypedef union {
188bf215546Sopenharmony_ci   nir_search_value value; /* base type of the union, first element of each variant struct */
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   nir_search_constant constant;
191bf215546Sopenharmony_ci   nir_search_variable variable;
192bf215546Sopenharmony_ci   nir_search_expression expression;
193bf215546Sopenharmony_ci} nir_search_value_union;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_citypedef bool (*nir_search_expression_cond)(const nir_alu_instr *instr);
196bf215546Sopenharmony_citypedef bool (*nir_search_variable_cond)(struct hash_table *range_ht,
197bf215546Sopenharmony_ci                                         const nir_alu_instr *instr,
198bf215546Sopenharmony_ci                                         unsigned src, unsigned num_components,
199bf215546Sopenharmony_ci                                         const uint8_t *swizzle);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci/* Generated data table for an algebraic optimization pass. */
202bf215546Sopenharmony_citypedef struct {
203bf215546Sopenharmony_ci   /** Array of all transforms in the pass. */
204bf215546Sopenharmony_ci   const struct transform *transforms;
205bf215546Sopenharmony_ci   /** Mapping from automaton state index to location in *transforms. */
206bf215546Sopenharmony_ci   const uint16_t *transform_offsets;
207bf215546Sopenharmony_ci   const struct per_op_table *pass_op_table;
208bf215546Sopenharmony_ci   const nir_search_value_union *values;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   /**
211bf215546Sopenharmony_ci    * Array of condition functions for expressions, referenced by
212bf215546Sopenharmony_ci    * nir_search_expression->cond.
213bf215546Sopenharmony_ci    */
214bf215546Sopenharmony_ci   const nir_search_expression_cond *expression_cond;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   /**
217bf215546Sopenharmony_ci    * Array of condition functions for variables, referenced by
218bf215546Sopenharmony_ci    * nir_search_variable->cond.
219bf215546Sopenharmony_ci    */
220bf215546Sopenharmony_ci   const nir_search_variable_cond *variable_cond;
221bf215546Sopenharmony_ci} nir_algebraic_table;
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci/* Note: these must match the start states created in
224bf215546Sopenharmony_ci * TreeAutomaton._build_table()
225bf215546Sopenharmony_ci */
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci/* WILDCARD_STATE = 0 is set by zeroing the state array */
228bf215546Sopenharmony_cistatic const uint16_t CONST_STATE = 1;
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ciNIR_DEFINE_CAST(nir_search_value_as_variable, nir_search_value,
231bf215546Sopenharmony_ci                nir_search_variable, value,
232bf215546Sopenharmony_ci                type, nir_search_value_variable)
233bf215546Sopenharmony_ciNIR_DEFINE_CAST(nir_search_value_as_constant, nir_search_value,
234bf215546Sopenharmony_ci                nir_search_constant, value,
235bf215546Sopenharmony_ci                type, nir_search_value_constant)
236bf215546Sopenharmony_ciNIR_DEFINE_CAST(nir_search_value_as_expression, nir_search_value,
237bf215546Sopenharmony_ci                nir_search_expression, value,
238bf215546Sopenharmony_ci                type, nir_search_value_expression)
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_cinir_ssa_def *
241bf215546Sopenharmony_cinir_replace_instr(struct nir_builder *b, nir_alu_instr *instr,
242bf215546Sopenharmony_ci                  struct hash_table *range_ht,
243bf215546Sopenharmony_ci                  struct util_dynarray *states,
244bf215546Sopenharmony_ci                  const nir_algebraic_table *table,
245bf215546Sopenharmony_ci                  const nir_search_expression *search,
246bf215546Sopenharmony_ci                  const nir_search_value *replace,
247bf215546Sopenharmony_ci                  nir_instr_worklist *algebraic_worklist);
248bf215546Sopenharmony_cibool
249bf215546Sopenharmony_cinir_algebraic_impl(nir_function_impl *impl,
250bf215546Sopenharmony_ci                   const bool *condition_flags,
251bf215546Sopenharmony_ci                   const nir_algebraic_table *table);
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci#endif /* _NIR_SEARCH_ */
254