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