• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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