1 /*
2  * Copyright © 2019 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "nir.h"
25 #include "util/bitset.h"
26 
27 static void
set_type(unsigned idx,nir_alu_type type,BITSET_WORD * float_types,BITSET_WORD * int_types,bool * progress)28 set_type(unsigned idx, nir_alu_type type, BITSET_WORD *float_types,
29          BITSET_WORD *int_types, bool *progress)
30 {
31    switch (nir_alu_type_get_base_type(type)) {
32    case nir_type_bool:
33    case nir_type_int:
34    case nir_type_uint:
35       if (int_types && !BITSET_TEST(int_types, idx)) {
36          *progress = true;
37          BITSET_SET(int_types, idx);
38       }
39       break;
40 
41    case nir_type_float:
42       if (float_types && !BITSET_TEST(float_types, idx)) {
43          *progress = true;
44          BITSET_SET(float_types, idx);
45       }
46       break;
47 
48    default:
49       unreachable("Invalid base nir_alu_type");
50    }
51 }
52 
53 static void
copy_type(unsigned src,unsigned dst,bool src_is_sink,BITSET_WORD * types,bool * progress)54 copy_type(unsigned src, unsigned dst, bool src_is_sink,
55           BITSET_WORD *types, bool *progress)
56 {
57    if (!types)
58       return;
59 
60    if (BITSET_TEST(types, dst)) {
61       if (BITSET_TEST(types, src))
62          return;
63       BITSET_SET(types, src);
64       *progress = true;
65    } else if (BITSET_TEST(types, src) && !src_is_sink) {
66       BITSET_SET(types, dst);
67       *progress = true;
68    }
69 }
70 
71 static void
copy_types(nir_src src,nir_dest * dest,BITSET_WORD * float_types,BITSET_WORD * int_types,bool * progress)72 copy_types(nir_src src, nir_dest *dest, BITSET_WORD *float_types,
73            BITSET_WORD *int_types, bool *progress)
74 {
75    bool src_is_sink = nir_src_is_const(src) || nir_src_is_undef(src);
76    copy_type(src.ssa->index, dest->ssa.index, src_is_sink, float_types, progress);
77    copy_type(src.ssa->index, dest->ssa.index, src_is_sink, int_types, progress);
78 }
79 
80 /** Gather up ALU types for SSA values
81  *
82  * This pass attempts to determine, for each SSA value, the type of data (int
83  * or float) that will be stored in it.  The pass is greedy in the sense that
84  * it just assigns intness or floatness to types without any attempt to sort
85  * out the interesting cases where a given type may be both.
86  *
87  * The output of the pass is a pair of bitsets which has the intness or
88  * floatness of each SSA value recorded by index.  It is the responsibility of
89  * the caller to index the SSA defs using nir_index_ssa_defs and allocate the
90  * bitsets.  Either bitset is allowed to be NULL in which case no data is
91  * recorded for that type.
92  */
93 void
nir_gather_ssa_types(nir_function_impl * impl,BITSET_WORD * float_types,BITSET_WORD * int_types)94 nir_gather_ssa_types(nir_function_impl *impl,
95                      BITSET_WORD *float_types,
96                      BITSET_WORD *int_types)
97 {
98    bool progress;
99    do {
100       progress = false;
101 
102       nir_foreach_block(block, impl) {
103          nir_foreach_instr(instr, block) {
104             switch (instr->type) {
105             case nir_instr_type_alu: {
106                nir_alu_instr *alu = nir_instr_as_alu(instr);
107                assert(alu->dest.dest.is_ssa);
108                const nir_op_info *info = &nir_op_infos[alu->op];
109                switch (alu->op) {
110                case nir_op_mov:
111                case nir_op_vec2:
112                case nir_op_vec3:
113                case nir_op_vec4:
114                case nir_op_vec5:
115                case nir_op_vec8:
116                case nir_op_vec16:
117                   for (unsigned i = 0; i < info->num_inputs; i++) {
118                      copy_types(alu->src[i].src, &alu->dest.dest,
119                                 float_types, int_types, &progress);
120                   }
121                   break;
122 
123                case nir_op_bcsel:
124                case nir_op_b32csel:
125                   set_type(alu->src[0].src.ssa->index, nir_type_bool,
126                            float_types, int_types, &progress);
127                   copy_types(alu->src[1].src, &alu->dest.dest,
128                              float_types, int_types, &progress);
129                   copy_types(alu->src[2].src, &alu->dest.dest,
130                              float_types, int_types, &progress);
131                   break;
132 
133                default:
134                   for (unsigned i = 0; i < info->num_inputs; i++) {
135                      assert(alu->src[i].src.is_ssa);
136                      set_type(alu->src[i].src.ssa->index, info->input_types[i],
137                               float_types, int_types, &progress);
138                   }
139                   set_type(alu->dest.dest.ssa.index, info->output_type,
140                            float_types, int_types, &progress);
141                }
142                break;
143             }
144 
145             case nir_instr_type_tex: {
146                nir_tex_instr *tex = nir_instr_as_tex(instr);
147                for (unsigned i = 0; i < tex->num_srcs; i++) {
148                   assert(tex->src[i].src.is_ssa);
149                   set_type(tex->src[i].src.ssa->index,
150                            nir_tex_instr_src_type(tex, i),
151                            float_types, int_types, &progress);
152                }
153                assert(tex->dest.is_ssa);
154                set_type(tex->dest.ssa.index, tex->dest_type,
155                         float_types, int_types, &progress);
156                break;
157             }
158 
159             case nir_instr_type_intrinsic: {
160                nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
161                /* We could go nuts here, but we'll just handle a few simple
162                 * cases and let everything else be untyped.
163                 */
164                switch (intrin->intrinsic) {
165                case nir_intrinsic_load_deref: {
166                   nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
167 
168                   assert(intrin->dest.is_ssa);
169                   set_type(intrin->dest.ssa.index,
170                            nir_get_nir_type_for_glsl_type(deref->type),
171                            float_types, int_types, &progress);
172                   break;
173                }
174 
175                case nir_intrinsic_store_deref: {
176                   nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
177 
178                   assert(intrin->src[1].is_ssa);
179                   set_type(intrin->src[1].ssa->index,
180                            nir_get_nir_type_for_glsl_type(deref->type),
181                            float_types, int_types, &progress);
182                   break;
183                }
184 
185                case nir_intrinsic_load_input:
186                case nir_intrinsic_load_uniform:
187                   assert(intrin->dest.is_ssa);
188                   set_type(intrin->dest.ssa.index,
189                            nir_intrinsic_dest_type(intrin),
190                            float_types, int_types, &progress);
191                   break;
192 
193                case nir_intrinsic_store_output:
194                   assert(intrin->src[0].is_ssa);
195                   set_type(intrin->src[0].ssa->index,
196                            nir_intrinsic_src_type(intrin),
197                            float_types, int_types, &progress);
198                   break;
199 
200                default:
201                   break;
202                }
203 
204                /* For the most part, we leave other intrinsics alone.  Most
205                 * of them don't matter in OpenGL ES 2.0 drivers anyway.
206                 * However, we should at least check if this is some sort of
207                 * IO intrinsic and flag it's offset and index sources.
208                 */
209                nir_src *offset_src = nir_get_io_offset_src(intrin);
210                if (offset_src) {
211                   assert(offset_src->is_ssa);
212                   set_type(offset_src->ssa->index, nir_type_int,
213                            float_types, int_types, &progress);
214                }
215                break;
216             }
217 
218             case nir_instr_type_phi: {
219                nir_phi_instr *phi = nir_instr_as_phi(instr);
220                assert(phi->dest.is_ssa);
221                nir_foreach_phi_src(src, phi) {
222                   copy_types(src->src, &phi->dest,
223                              float_types, int_types, &progress);
224                }
225                break;
226             }
227 
228             default:
229                break;
230             }
231          }
232       }
233    } while (progress);
234 }
235