nir: Drop imov/fmov in favor of one mov instruction
[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_mov:
106 case nir_op_vec2:
107 case nir_op_vec3:
108 case nir_op_vec4:
109 for (unsigned i = 0; i < info->num_inputs; i++) {
110 assert(alu->src[i].src.is_ssa);
111 copy_types(alu->src[i].src.ssa->index,
112 alu->dest.dest.ssa.index,
113 float_types, int_types, &progress);
114 }
115 break;
116
117 case nir_op_bcsel:
118 case nir_op_b32csel:
119 set_type(alu->src[0].src.ssa->index, nir_type_bool,
120 float_types, int_types, &progress);
121 copy_types(alu->src[1].src.ssa->index,
122 alu->dest.dest.ssa.index,
123 float_types, int_types, &progress);
124 copy_types(alu->src[2].src.ssa->index,
125 alu->dest.dest.ssa.index,
126 float_types, int_types, &progress);
127 break;
128
129 default:
130 for (unsigned i = 0; i < info->num_inputs; i++) {
131 assert(alu->src[i].src.is_ssa);
132 set_type(alu->src[i].src.ssa->index, info->input_types[i],
133 float_types, int_types, &progress);
134 }
135 set_type(alu->dest.dest.ssa.index, info->output_type,
136 float_types, int_types, &progress);
137 }
138 break;
139 }
140
141 case nir_instr_type_tex: {
142 nir_tex_instr *tex = nir_instr_as_tex(instr);
143 for (unsigned i = 0; i < tex->num_srcs; i++) {
144 assert(tex->src[i].src.is_ssa);
145 set_type(tex->src[i].src.ssa->index,
146 nir_tex_instr_src_type(tex, i),
147 float_types, int_types, &progress);
148 }
149 assert(tex->dest.is_ssa);
150 set_type(tex->dest.ssa.index, tex->dest_type,
151 float_types, int_types, &progress);
152 break;
153 }
154
155 case nir_instr_type_intrinsic: {
156 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
157 /* We could go nuts here, but we'll just handle a few simple
158 * cases and let everything else be untyped.
159 */
160 switch (intrin->intrinsic) {
161 case nir_intrinsic_load_deref: {
162 nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
163
164 assert(intrin->dest.is_ssa);
165 set_type(intrin->dest.ssa.index,
166 nir_get_nir_type_for_glsl_type(deref->type),
167 float_types, int_types, &progress);
168 break;
169 }
170
171 case nir_intrinsic_store_deref: {
172 nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
173
174 assert(intrin->src[1].is_ssa);
175 set_type(intrin->src[1].ssa->index,
176 nir_get_nir_type_for_glsl_type(deref->type),
177 float_types, int_types, &progress);
178 break;
179 }
180
181 default: {
182 /* For the most part, we leave other intrinsics alone. Most
183 * of them don't matter in OpenGL ES 2.0 drivers anyway.
184 * However, we should at least check if this is some sort of
185 * IO intrinsic and flag it's offset and index sources.
186 */
187 nir_src *offset_src = nir_get_io_offset_src(intrin);
188 if (offset_src) {
189 assert(offset_src->is_ssa);
190 set_type(offset_src->ssa->index, nir_type_int,
191 float_types, int_types, &progress);
192 }
193 break;
194 }
195 }
196 break;
197 }
198
199 case nir_instr_type_phi: {
200 nir_phi_instr *phi = nir_instr_as_phi(instr);
201 assert(phi->dest.is_ssa);
202 nir_foreach_phi_src(src, phi) {
203 assert(src->src.is_ssa);
204 copy_types(src->src.ssa->index, phi->dest.ssa.index,
205 float_types, int_types, &progress);
206 }
207 break;
208 }
209
210 default:
211 break;
212 }
213 }
214 }
215 } while (progress);
216 }