nir: Add a SSA type gathering pass
[mesa.git] / src / compiler / nir / nir_gather_ssa_types.c
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
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
54 copy_types(unsigned a, unsigned b, BITSET_WORD *float_types,
55 BITSET_WORD *int_types, bool *progress)
56 {
57 /* If the bits do not agree then one of them is set but not both. Flag
58 * progress and set both bits.
59 */
60 if (float_types && (BITSET_TEST(float_types, a) !=
61 BITSET_TEST(float_types, b))) {
62 *progress = true;
63 BITSET_SET(float_types, a);
64 BITSET_SET(float_types, b);
65 }
66
67 if (int_types && (BITSET_TEST(int_types, a) !=
68 BITSET_TEST(int_types, b))) {
69 *progress = true;
70 BITSET_SET(int_types, a);
71 BITSET_SET(int_types, b);
72 }
73 }
74
75 /** Gather up ALU types for SSA values
76 *
77 * This pass attempts to determine, for each SSA value, the type of data (int
78 * or float) that will be stored in it. The pass is greedy in the sense that
79 * it just assigns intness or floatness to types without any attempt to sort
80 * out the interesting cases where a given type may be both.
81 *
82 * The output of the pass is a pair of bitsets which has the intness or
83 * floatness of each SSA value recorded by index. It is the responsibility of
84 * the caller to index the SSA defs using nir_index_ssa_defs and allocate the
85 * bitsets. Either bitset is allowed to be NULL in which case no data is
86 * recorded for that type.
87 */
88 void
89 nir_gather_ssa_types(nir_function_impl *impl,
90 BITSET_WORD *float_types,
91 BITSET_WORD *int_types)
92 {
93 bool progress;
94 do {
95 progress = false;
96
97 nir_foreach_block(block, impl) {
98 nir_foreach_instr(instr, block) {
99 switch (instr->type) {
100 case nir_instr_type_alu: {
101 nir_alu_instr *alu = nir_instr_as_alu(instr);
102 assert(alu->dest.dest.is_ssa);
103 const nir_op_info *info = &nir_op_infos[alu->op];
104 switch (alu->op) {
105 case nir_op_imov:
106 case nir_op_fmov:
107 case nir_op_vec2:
108 case nir_op_vec3:
109 case nir_op_vec4:
110 for (unsigned i = 0; i < info->num_inputs; i++) {
111 assert(alu->src[i].src.is_ssa);
112 copy_types(alu->src[i].src.ssa->index,
113 alu->dest.dest.ssa.index,
114 float_types, int_types, &progress);
115 }
116 break;
117
118 case nir_op_bcsel:
119 case nir_op_b32csel:
120 set_type(alu->src[0].src.ssa->index, nir_type_bool,
121 float_types, int_types, &progress);
122 copy_types(alu->src[1].src.ssa->index,
123 alu->dest.dest.ssa.index,
124 float_types, int_types, &progress);
125 copy_types(alu->src[2].src.ssa->index,
126 alu->dest.dest.ssa.index,
127 float_types, int_types, &progress);
128 break;
129
130 default:
131 for (unsigned i = 0; i < info->num_inputs; i++) {
132 assert(alu->src[i].src.is_ssa);
133 set_type(alu->src[i].src.ssa->index, info->input_types[i],
134 float_types, int_types, &progress);
135 }
136 set_type(alu->dest.dest.ssa.index, info->output_type,
137 float_types, int_types, &progress);
138 }
139 break;
140 }
141
142 case nir_instr_type_tex: {
143 nir_tex_instr *tex = nir_instr_as_tex(instr);
144 for (unsigned i = 0; i < tex->num_srcs; i++) {
145 assert(tex->src[i].src.is_ssa);
146 set_type(tex->src[i].src.ssa->index,
147 nir_tex_instr_src_type(tex, i),
148 float_types, int_types, &progress);
149 }
150 assert(tex->dest.is_ssa);
151 set_type(tex->dest.ssa.index, tex->dest_type,
152 float_types, int_types, &progress);
153 break;
154 }
155
156 case nir_instr_type_intrinsic: {
157 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
158 /* We could go nuts here, but we'll just handle a few simple
159 * cases and let everything else be untyped.
160 */
161 switch (intrin->intrinsic) {
162 case nir_intrinsic_load_deref: {
163 nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
164
165 assert(intrin->dest.is_ssa);
166 set_type(intrin->dest.ssa.index,
167 nir_get_nir_type_for_glsl_type(deref->type),
168 float_types, int_types, &progress);
169 break;
170 }
171
172 case nir_intrinsic_store_deref: {
173 nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
174
175 assert(intrin->src[1].is_ssa);
176 set_type(intrin->src[1].ssa->index,
177 nir_get_nir_type_for_glsl_type(deref->type),
178 float_types, int_types, &progress);
179 break;
180 }
181
182 default: {
183 /* For the most part, we leave other intrinsics alone. Most
184 * of them don't matter in OpenGL ES 2.0 drivers anyway.
185 * However, we should at least check if this is some sort of
186 * IO intrinsic and flag it's offset and index sources.
187 */
188 nir_src *offset_src = nir_get_io_offset_src(intrin);
189 if (offset_src) {
190 assert(offset_src->is_ssa);
191 set_type(offset_src->ssa->index, nir_type_int,
192 float_types, int_types, &progress);
193 }
194 break;
195 }
196 }
197 break;
198 }
199
200 case nir_instr_type_phi: {
201 nir_phi_instr *phi = nir_instr_as_phi(instr);
202 assert(phi->dest.is_ssa);
203 nir_foreach_phi_src(src, phi) {
204 assert(src->src.is_ssa);
205 copy_types(src->src.ssa->index, phi->dest.ssa.index,
206 float_types, int_types, &progress);
207 }
208 break;
209 }
210
211 default:
212 break;
213 }
214 }
215 }
216 } while (progress);
217 }