1 /*
2 * Copyright (c) 2020 Etnaviv Project
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, sub license,
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
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the 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 NON-INFRINGEMENT. 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
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Jonathan Marek <jonathan@marek.ca>
25 */
26
27 #ifndef H_ETNAVIV_COMPILER_NIR
28 #define H_ETNAVIV_COMPILER_NIR
29
30 #include "compiler/nir/nir.h"
31 #include "etnaviv_asm.h"
32 #include "etnaviv_compiler.h"
33 #include "util/compiler.h"
34 #include "util/log.h"
35 #include "util/macros.h"
36
37 struct etna_compile {
38 nir_shader *nir;
39 nir_function_impl *impl;
40 #define is_fs(c) ((c)->nir->info.stage == MESA_SHADER_FRAGMENT)
41 const struct etna_specs *specs;
42 struct etna_shader_variant *variant;
43
44 /* block # to instr index */
45 unsigned *block_ptr;
46
47 /* Code generation */
48 int inst_ptr; /* current instruction pointer */
49 struct etna_inst code[ETNA_MAX_INSTRUCTIONS * ETNA_INST_SIZE];
50
51 /* constants */
52 uint64_t consts[ETNA_MAX_IMM];
53 unsigned const_count;
54
55 /* ra state */
56 struct ra_graph *g;
57 unsigned *live_map;
58 unsigned num_nodes;
59
60 /* There was an error during compilation */
61 bool error;
62 };
63
64 #define compile_error(ctx, args...) ({ \
65 mesa_loge(args); \
66 ctx->error = true; \
67 abort(); \
68 })
69
70 enum etna_pass_flags {
71 BYPASS_DST = BITFIELD_BIT(0),
72 BYPASS_SRC = BITFIELD_BIT(1),
73
74 /* source modifier */
75 SRC0_MOD_NEG = BITFIELD_BIT(2),
76 SRC1_MOD_NEG = BITFIELD_BIT(3),
77 SRC2_MOD_NEG = BITFIELD_BIT(4),
78 SRC0_MOD_ABS = BITFIELD_BIT(5),
79 SRC1_MOD_ABS = BITFIELD_BIT(6),
80 SRC2_MOD_ABS = BITFIELD_BIT(7),
81 };
82
83 #define PASS_FLAGS_IS_DEAD_MASK BITFIELD_RANGE(0, 2)
84 #define PASS_FLAGS_SRC_MOD_NEG_MASK BITFIELD_RANGE(2, 3)
85 #define PASS_FLAGS_SRC_MOD_ABS_MASK BITFIELD_RANGE(5, 3)
86
87 static_assert(PASS_FLAGS_IS_DEAD_MASK == (BYPASS_DST | BYPASS_SRC), "is_dead_mask is wrong");
88 static_assert(PASS_FLAGS_SRC_MOD_NEG_MASK == (SRC0_MOD_NEG | SRC1_MOD_NEG | SRC2_MOD_NEG), "src_mod_neg_mask is wrong");
89 static_assert(PASS_FLAGS_SRC_MOD_ABS_MASK == (SRC0_MOD_ABS | SRC1_MOD_ABS | SRC2_MOD_ABS), "src_mod_abs_mask is wrong");
90
is_dead_instruction(nir_instr * instr)91 static inline bool is_dead_instruction(nir_instr *instr)
92 {
93 return instr->pass_flags & PASS_FLAGS_IS_DEAD_MASK;
94 }
95
set_src_mod_abs(nir_instr * instr,unsigned idx)96 static inline void set_src_mod_abs(nir_instr *instr, unsigned idx)
97 {
98 assert(idx < 3);
99 instr->pass_flags |= (SRC0_MOD_ABS << idx);
100 }
101
set_src_mod_neg(nir_instr * instr,unsigned idx)102 static inline void set_src_mod_neg(nir_instr *instr, unsigned idx)
103 {
104 assert(idx < 3);
105 instr->pass_flags |= (SRC0_MOD_NEG << idx);
106 }
107
toggle_src_mod_neg(nir_instr * instr,unsigned idx)108 static inline void toggle_src_mod_neg(nir_instr *instr, unsigned idx)
109 {
110 assert(idx < 3);
111 instr->pass_flags ^= (SRC0_MOD_NEG << idx);
112 }
113
is_src_mod_abs(nir_instr * instr,unsigned idx)114 static inline bool is_src_mod_abs(nir_instr *instr, unsigned idx)
115 {
116 if (idx < 3)
117 return instr->pass_flags & (SRC0_MOD_ABS << idx);
118
119 return false;
120 }
121
is_src_mod_neg(nir_instr * instr,unsigned idx)122 static inline bool is_src_mod_neg(nir_instr *instr, unsigned idx)
123 {
124 if (idx < 3)
125 return instr->pass_flags & (SRC0_MOD_NEG << idx);
126
127 return false;
128 }
129
is_sysval(nir_instr * instr)130 static inline bool is_sysval(nir_instr *instr)
131 {
132 if (instr->type != nir_instr_type_intrinsic)
133 return false;
134
135 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
136 return intr->intrinsic == nir_intrinsic_load_front_face ||
137 intr->intrinsic == nir_intrinsic_load_frag_coord;
138 }
139
140 /* get unique ssa/reg index for nir_src */
141 static inline unsigned
src_index(nir_function_impl * impl,nir_src * src)142 src_index(nir_function_impl *impl, nir_src *src)
143 {
144 nir_intrinsic_instr *load = nir_load_reg_for_def(src->ssa);
145
146 if (load) {
147 nir_def *reg = load->src[0].ssa;
148 ASSERTED nir_intrinsic_instr *decl = nir_reg_get_decl(reg);
149 assert(nir_intrinsic_base(load) == 0);
150 assert(nir_intrinsic_num_array_elems(decl) == 0);
151
152 return reg->index;
153 }
154
155 return src->ssa->index;
156 }
157
158 /* get unique ssa/reg index for nir_def */
159 static inline unsigned
def_index(nir_function_impl * impl,nir_def * def)160 def_index(nir_function_impl *impl, nir_def *def)
161 {
162 nir_intrinsic_instr *store = nir_store_reg_for_def(def);
163
164 if (store) {
165 nir_def *reg = store->src[1].ssa;
166 ASSERTED nir_intrinsic_instr *decl = nir_reg_get_decl(reg);
167 assert(nir_intrinsic_base(store) == 0);
168 assert(nir_intrinsic_num_array_elems(decl) == 0);
169
170 return reg->index;
171 }
172
173 return def->index;
174 }
175
176 static inline void
update_swiz_mask(nir_alu_instr * alu,nir_def * def,unsigned * swiz,unsigned * mask)177 update_swiz_mask(nir_alu_instr *alu, nir_def *def, unsigned *swiz, unsigned *mask)
178 {
179 if (!swiz)
180 return;
181
182 bool is_vec = def != NULL;
183 unsigned swizzle = 0, write_mask = 0;
184 for (unsigned i = 0; i < alu->def.num_components; i++) {
185 /* src is different (only check for vecN) */
186 if (is_vec && alu->src[i].src.ssa != def)
187 continue;
188
189 unsigned src_swiz = is_vec ? alu->src[i].swizzle[0] : alu->src[0].swizzle[i];
190 swizzle |= (*swiz >> src_swiz * 2 & 3) << i * 2;
191 /* this channel isn't written through this chain */
192 if (*mask & (1 << src_swiz))
193 write_mask |= 1 << i;
194 }
195 *swiz = swizzle;
196 *mask = write_mask;
197 }
198
199 static nir_def *
real_def(nir_def * def,unsigned * swiz,unsigned * mask)200 real_def(nir_def *def, unsigned *swiz, unsigned *mask)
201 {
202 if (!def)
203 return def;
204
205 bool can_bypass_src = !nir_def_used_by_if(def);
206 nir_instr *p_instr = def->parent_instr;
207
208 /* if used by a vecN, the "real" destination becomes the vecN destination
209 * lower_alu guarantees that values used by a vecN are only used by that vecN
210 * we can apply the same logic to movs in a some cases too
211 */
212 nir_foreach_use(use_src, def) {
213 nir_instr *instr = nir_src_parent_instr(use_src);
214
215 /* src bypass check: for now only deal with tex src mov case
216 * note: for alu don't bypass mov for multiple uniform sources
217 */
218 switch (instr->type) {
219 case nir_instr_type_tex:
220 if (p_instr->type == nir_instr_type_alu &&
221 nir_instr_as_alu(p_instr)->op == nir_op_mov) {
222 break;
223 }
224 FALLTHROUGH;
225 default:
226 can_bypass_src = false;
227 break;
228 }
229
230 if (instr->type != nir_instr_type_alu)
231 continue;
232
233 nir_alu_instr *alu = nir_instr_as_alu(instr);
234
235 switch (alu->op) {
236 case nir_op_vec2:
237 case nir_op_vec3:
238 case nir_op_vec4:
239 assert(!nir_def_used_by_if(def));
240 nir_foreach_use(use_src, def)
241 assert(nir_src_parent_instr(use_src) == instr);
242
243 update_swiz_mask(alu, def, swiz, mask);
244 break;
245 case nir_op_mov: {
246 switch (def->parent_instr->type) {
247 case nir_instr_type_alu:
248 case nir_instr_type_tex:
249 break;
250 default:
251 continue;
252 }
253 if (nir_def_used_by_if(def) || list_length(&def->uses) > 1)
254 continue;
255
256 update_swiz_mask(alu, NULL, swiz, mask);
257 break;
258 };
259 default:
260 continue;
261 }
262
263 assert(!(instr->pass_flags & BYPASS_SRC));
264 instr->pass_flags |= BYPASS_DST;
265 return real_def(&alu->def, swiz, mask);
266 }
267
268 if (can_bypass_src && !(p_instr->pass_flags & BYPASS_DST)) {
269 p_instr->pass_flags |= BYPASS_SRC;
270 return NULL;
271 }
272
273 return def;
274 }
275
276 /* if instruction dest needs a register, return nir_def for it */
277 static inline nir_def *
def_for_instr(nir_instr * instr)278 def_for_instr(nir_instr *instr)
279 {
280 nir_def *def = NULL;
281
282 switch (instr->type) {
283 case nir_instr_type_alu:
284 def = &nir_instr_as_alu(instr)->def;
285 break;
286 case nir_instr_type_tex:
287 def = &nir_instr_as_tex(instr)->def;
288 break;
289 case nir_instr_type_intrinsic: {
290 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
291 if (intr->intrinsic == nir_intrinsic_load_uniform ||
292 intr->intrinsic == nir_intrinsic_load_ubo ||
293 intr->intrinsic == nir_intrinsic_load_input ||
294 intr->intrinsic == nir_intrinsic_load_instance_id ||
295 intr->intrinsic == nir_intrinsic_load_texture_scale ||
296 intr->intrinsic == nir_intrinsic_load_texture_size_etna)
297 def = &intr->def;
298 } break;
299 case nir_instr_type_deref:
300 return NULL;
301 default:
302 break;
303 }
304 return real_def(def, NULL, NULL);
305 }
306
307 struct live_def {
308 nir_instr *instr;
309 nir_def *def; /* cached def_for_instr */
310 unsigned live_start, live_end; /* live range */
311 };
312
313 unsigned
314 etna_live_defs(nir_function_impl *impl, struct live_def *defs, unsigned *live_map);
315
316 /* Swizzles and write masks can be used to layer virtual non-interfering
317 * registers on top of the real VEC4 registers. For example, the virtual
318 * VEC3_XYZ register and the virtual SCALAR_W register that use the same
319 * physical VEC4 base register do not interfere.
320 */
321 enum reg_class {
322 REG_CLASS_VIRT_SCALAR,
323 REG_CLASS_VIRT_VEC2,
324 REG_CLASS_VIRT_VEC3,
325 REG_CLASS_VEC4,
326 /* special vec2 class for fast transcendentals, limited to XY or ZW */
327 REG_CLASS_VIRT_VEC2T,
328 /* special classes for LOAD - contiguous components */
329 REG_CLASS_VIRT_VEC2C,
330 REG_CLASS_VIRT_VEC3C,
331 NUM_REG_CLASSES,
332 };
333
334 enum reg_type {
335 REG_TYPE_VEC4,
336 REG_TYPE_VIRT_VEC3_XYZ,
337 REG_TYPE_VIRT_VEC3_XYW,
338 REG_TYPE_VIRT_VEC3_XZW,
339 REG_TYPE_VIRT_VEC3_YZW,
340 REG_TYPE_VIRT_VEC2_XY,
341 REG_TYPE_VIRT_VEC2_XZ,
342 REG_TYPE_VIRT_VEC2_XW,
343 REG_TYPE_VIRT_VEC2_YZ,
344 REG_TYPE_VIRT_VEC2_YW,
345 REG_TYPE_VIRT_VEC2_ZW,
346 REG_TYPE_VIRT_SCALAR_X,
347 REG_TYPE_VIRT_SCALAR_Y,
348 REG_TYPE_VIRT_SCALAR_Z,
349 REG_TYPE_VIRT_SCALAR_W,
350 REG_TYPE_VIRT_VEC2T_XY,
351 REG_TYPE_VIRT_VEC2T_ZW,
352 REG_TYPE_VIRT_VEC2C_XY,
353 REG_TYPE_VIRT_VEC2C_YZ,
354 REG_TYPE_VIRT_VEC2C_ZW,
355 REG_TYPE_VIRT_VEC3C_XYZ,
356 REG_TYPE_VIRT_VEC3C_YZW,
357 NUM_REG_TYPES,
358 };
359
360 /* writemask when used as dest */
361 static const uint8_t
362 reg_writemask[NUM_REG_TYPES] = {
363 [REG_TYPE_VEC4] = 0xf,
364 [REG_TYPE_VIRT_SCALAR_X] = 0x1,
365 [REG_TYPE_VIRT_SCALAR_Y] = 0x2,
366 [REG_TYPE_VIRT_VEC2_XY] = 0x3,
367 [REG_TYPE_VIRT_VEC2T_XY] = 0x3,
368 [REG_TYPE_VIRT_VEC2C_XY] = 0x3,
369 [REG_TYPE_VIRT_SCALAR_Z] = 0x4,
370 [REG_TYPE_VIRT_VEC2_XZ] = 0x5,
371 [REG_TYPE_VIRT_VEC2_YZ] = 0x6,
372 [REG_TYPE_VIRT_VEC2C_YZ] = 0x6,
373 [REG_TYPE_VIRT_VEC3_XYZ] = 0x7,
374 [REG_TYPE_VIRT_VEC3C_XYZ] = 0x7,
375 [REG_TYPE_VIRT_SCALAR_W] = 0x8,
376 [REG_TYPE_VIRT_VEC2_XW] = 0x9,
377 [REG_TYPE_VIRT_VEC2_YW] = 0xa,
378 [REG_TYPE_VIRT_VEC3_XYW] = 0xb,
379 [REG_TYPE_VIRT_VEC2_ZW] = 0xc,
380 [REG_TYPE_VIRT_VEC2T_ZW] = 0xc,
381 [REG_TYPE_VIRT_VEC2C_ZW] = 0xc,
382 [REG_TYPE_VIRT_VEC3_XZW] = 0xd,
383 [REG_TYPE_VIRT_VEC3_YZW] = 0xe,
384 [REG_TYPE_VIRT_VEC3C_YZW] = 0xe,
385 };
386
reg_get_type(int virt_reg)387 static inline int reg_get_type(int virt_reg)
388 {
389 return virt_reg % NUM_REG_TYPES;
390 }
391
reg_get_base(struct etna_compile * c,int virt_reg)392 static inline int reg_get_base(struct etna_compile *c, int virt_reg)
393 {
394 /* offset by 1 to avoid reserved position register */
395 if (c->nir->info.stage == MESA_SHADER_FRAGMENT)
396 return (virt_reg / NUM_REG_TYPES + 1) % ETNA_MAX_TEMPS;
397 return virt_reg / NUM_REG_TYPES;
398 }
399
400 struct ra_regs *
401 etna_ra_setup(void *mem_ctx);
402
403 void
404 etna_ra_assign(struct etna_compile *c, nir_shader *shader);
405
406 unsigned
407 etna_ra_finish(struct etna_compile *c);
408
409 static inline void
emit_inst(struct etna_compile * c,struct etna_inst * inst)410 emit_inst(struct etna_compile *c, struct etna_inst *inst)
411 {
412 c->code[c->inst_ptr++] = *inst;
413 }
414
415 void
416 etna_emit_alu(struct etna_compile *c, nir_op op, struct etna_inst_dst dst,
417 struct etna_inst_src src[3], bool saturate);
418
419 void
420 etna_emit_tex(struct etna_compile *c, nir_texop op, unsigned texid, unsigned dst_swiz,
421 struct etna_inst_dst dst, struct etna_inst_src coord,
422 struct etna_inst_src src1, struct etna_inst_src src2);
423
424 void
425 etna_emit_jump(struct etna_compile *c, unsigned block, struct etna_inst_src condition);
426
427 void
428 etna_emit_discard(struct etna_compile *c, struct etna_inst_src condition);
429
430 #endif
431