nvc0: use tile flags in a way compatible with nouveau
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_pc.c
1 /*
2 * Copyright 2010 Christoph Bumiller
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 shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #define NOUVEAU_DEBUG 1
24
25 #include "nvc0_pc.h"
26 #include "nvc0_program.h"
27
28 boolean
29 nvc0_insn_can_load(struct nv_instruction *nvi, int s,
30 struct nv_instruction *ld)
31 {
32 int i;
33
34 if (ld->opcode == NV_OP_MOV && ld->src[0]->value->reg.file == NV_FILE_IMM) {
35 if (s > 1 || !(nvc0_op_info_table[nvi->opcode].immediate & (1 << s)))
36 return FALSE;
37 if (!(nvc0_op_info_table[nvi->opcode].immediate & 4))
38 if (ld->src[0]->value->reg.imm.u32 & 0xfff)
39 return FALSE;
40 } else
41 if (!(nvc0_op_info_table[nvi->opcode].memory & (1 << s)))
42 return FALSE;
43
44 if (ld->indirect >= 0)
45 return FALSE;
46
47 for (i = 0; i < 3 && nvi->src[i]; ++i)
48 if (nvi->src[i]->value->reg.file == NV_FILE_IMM)
49 return FALSE;
50
51 return TRUE;
52 }
53
54 /* Return whether this instruction can be executed conditionally. */
55 boolean
56 nvc0_insn_is_predicateable(struct nv_instruction *nvi)
57 {
58 int s;
59
60 if (!nv_op_predicateable(nvi->opcode))
61 return FALSE;
62 if (nvi->predicate >= 0)
63 return FALSE;
64 for (s = 0; s < 4 && nvi->src[s]; ++s)
65 if (nvi->src[s]->value->reg.file == NV_FILE_IMM)
66 return FALSE;
67 return TRUE;
68 }
69
70 int
71 nvc0_insn_refcount(struct nv_instruction *nvi)
72 {
73 int rc = 0;
74 int i;
75 for (i = 0; i < 5 && nvi->def[i]; ++i) {
76 if (!nvi->def[i])
77 return rc;
78 rc += nvi->def[i]->refc;
79 }
80 return rc;
81 }
82
83 int
84 nvc0_pc_replace_value(struct nv_pc *pc,
85 struct nv_value *old_val,
86 struct nv_value *new_val)
87 {
88 int i, n, s;
89
90 if (old_val == new_val)
91 return old_val->refc;
92
93 for (i = 0, n = 0; i < pc->num_refs; ++i) {
94 if (pc->refs[i]->value == old_val) {
95 ++n;
96 for (s = 0; s < 6 && pc->refs[i]->insn->src[s]; ++s)
97 if (pc->refs[i]->insn->src[s] == pc->refs[i])
98 break;
99 assert(s < 6);
100 nv_reference(pc, pc->refs[i]->insn, s, new_val);
101 }
102 }
103 return n;
104 }
105
106 struct nv_value *
107 nvc0_pc_find_constant(struct nv_ref *ref)
108 {
109 struct nv_value *src;
110
111 if (!ref)
112 return NULL;
113
114 src = ref->value;
115 while (src->insn && src->insn->opcode == NV_OP_MOV) {
116 assert(!src->insn->src[0]->mod);
117 src = src->insn->src[0]->value;
118 }
119 if ((src->reg.file == NV_FILE_IMM) ||
120 (src->insn &&
121 src->insn->opcode == NV_OP_LD &&
122 src->insn->src[0]->value->reg.file >= NV_FILE_MEM_C(0) &&
123 src->insn->src[0]->value->reg.file <= NV_FILE_MEM_C(15)))
124 return src;
125 return NULL;
126 }
127
128 struct nv_value *
129 nvc0_pc_find_immediate(struct nv_ref *ref)
130 {
131 struct nv_value *src = nvc0_pc_find_constant(ref);
132
133 return (src && src->reg.file == NV_FILE_IMM) ? src : NULL;
134 }
135
136 static void
137 nv_pc_free_refs(struct nv_pc *pc)
138 {
139 int i;
140 for (i = 0; i < pc->num_refs; i += 64)
141 FREE(pc->refs[i]);
142 FREE(pc->refs);
143 }
144
145 static const char *
146 edge_name(ubyte type)
147 {
148 switch (type) {
149 case CFG_EDGE_FORWARD: return "forward";
150 case CFG_EDGE_BACK: return "back";
151 case CFG_EDGE_LOOP_ENTER: return "loop";
152 case CFG_EDGE_LOOP_LEAVE: return "break";
153 case CFG_EDGE_FAKE: return "fake";
154 default:
155 return "?";
156 }
157 }
158
159 void
160 nvc0_pc_pass_in_order(struct nv_basic_block *root, nv_pc_pass_func f,
161 void *priv)
162 {
163 struct nv_basic_block *bb[64], *bbb[16], *b;
164 int j, p, pp;
165
166 bb[0] = root;
167 p = 1;
168 pp = 0;
169
170 while (p > 0) {
171 b = bb[--p];
172 b->priv = 0;
173
174 for (j = 1; j >= 0; --j) {
175 if (!b->out[j])
176 continue;
177
178 switch (b->out_kind[j]) {
179 case CFG_EDGE_BACK:
180 continue;
181 case CFG_EDGE_FORWARD:
182 case CFG_EDGE_FAKE:
183 if (++b->out[j]->priv == b->out[j]->num_in)
184 bb[p++] = b->out[j];
185 break;
186 case CFG_EDGE_LOOP_ENTER:
187 bb[p++] = b->out[j];
188 break;
189 case CFG_EDGE_LOOP_LEAVE:
190 bbb[pp++] = b->out[j];
191 break;
192 default:
193 assert(0);
194 break;
195 }
196 }
197
198 f(priv, b);
199
200 if (!p) {
201 p = pp;
202 for (; pp > 0; --pp)
203 bb[pp - 1] = bbb[pp - 1];
204 }
205 }
206 }
207
208 static void
209 nv_do_print_function(void *priv, struct nv_basic_block *b)
210 {
211 struct nv_instruction *i;
212
213 debug_printf("=== BB %i ", b->id);
214 if (b->out[0])
215 debug_printf("[%s -> %i] ", edge_name(b->out_kind[0]), b->out[0]->id);
216 if (b->out[1])
217 debug_printf("[%s -> %i] ", edge_name(b->out_kind[1]), b->out[1]->id);
218 debug_printf("===\n");
219
220 i = b->phi;
221 if (!i)
222 i = b->entry;
223 for (; i; i = i->next)
224 nvc0_print_instruction(i);
225 }
226
227 void
228 nvc0_print_function(struct nv_basic_block *root)
229 {
230 if (root->subroutine)
231 debug_printf("SUBROUTINE %i\n", root->subroutine);
232 else
233 debug_printf("MAIN\n");
234
235 nvc0_pc_pass_in_order(root, nv_do_print_function, root);
236 }
237
238 void
239 nvc0_print_program(struct nv_pc *pc)
240 {
241 int i;
242 for (i = 0; i < pc->num_subroutines + 1; ++i)
243 if (pc->root[i])
244 nvc0_print_function(pc->root[i]);
245 }
246
247 #if NOUVEAU_DEBUG > 1
248 static void
249 nv_do_print_cfgraph(struct nv_pc *pc, FILE *f, struct nv_basic_block *b)
250 {
251 int i;
252
253 b->pass_seq = pc->pass_seq;
254
255 fprintf(f, "\t%i [shape=box]\n", b->id);
256
257 for (i = 0; i < 2; ++i) {
258 if (!b->out[i])
259 continue;
260 switch (b->out_kind[i]) {
261 case CFG_EDGE_FORWARD:
262 fprintf(f, "\t%i -> %i;\n", b->id, b->out[i]->id);
263 break;
264 case CFG_EDGE_LOOP_ENTER:
265 fprintf(f, "\t%i -> %i [color=green];\n", b->id, b->out[i]->id);
266 break;
267 case CFG_EDGE_LOOP_LEAVE:
268 fprintf(f, "\t%i -> %i [color=red];\n", b->id, b->out[i]->id);
269 break;
270 case CFG_EDGE_BACK:
271 fprintf(f, "\t%i -> %i;\n", b->id, b->out[i]->id);
272 continue;
273 case CFG_EDGE_FAKE:
274 fprintf(f, "\t%i -> %i [style=dotted];\n", b->id, b->out[i]->id);
275 break;
276 default:
277 assert(0);
278 break;
279 }
280 if (b->out[i]->pass_seq < pc->pass_seq)
281 nv_do_print_cfgraph(pc, f, b->out[i]);
282 }
283 }
284
285 /* Print the control flow graph of subroutine @subr (0 == MAIN) to a file. */
286 static void
287 nv_print_cfgraph(struct nv_pc *pc, const char *filepath, int subr)
288 {
289 FILE *f;
290
291 f = fopen(filepath, "a");
292 if (!f)
293 return;
294
295 fprintf(f, "digraph G {\n");
296
297 ++pc->pass_seq;
298
299 nv_do_print_cfgraph(pc, f, pc->root[subr]);
300
301 fprintf(f, "}\n");
302
303 fclose(f);
304 }
305 #endif
306
307 static INLINE void
308 nvc0_pc_print_binary(struct nv_pc *pc)
309 {
310 unsigned i;
311
312 NOUVEAU_DBG("nvc0_pc_print_binary(%u ops)\n", pc->emit_size / 8);
313
314 for (i = 0; i < pc->emit_size / 4; i += 2) {
315 debug_printf("0x%08x ", pc->emit[i + 0]);
316 debug_printf("0x%08x ", pc->emit[i + 1]);
317 if ((i % 16) == 15)
318 debug_printf("\n");
319 }
320 debug_printf("\n");
321 }
322
323 static int
324 nvc0_emit_program(struct nv_pc *pc)
325 {
326 uint32_t *code = pc->emit;
327 int n;
328
329 NOUVEAU_DBG("emitting program: size = %u\n", pc->emit_size);
330
331 for (n = 0; n < pc->num_blocks; ++n) {
332 struct nv_instruction *i;
333 struct nv_basic_block *b = pc->bb_list[n];
334
335 for (i = b->entry; i; i = i->next) {
336 nvc0_emit_instruction(pc, i);
337 pc->emit += 2;
338 pc->emit_pos += 2;
339 }
340 }
341 assert(pc->emit == &code[pc->emit_size / 4]);
342
343 pc->emit[0] = 0x00001de7;
344 pc->emit[1] = 0x80000000;
345 pc->emit_size += 8;
346
347 pc->emit = code;
348
349 #ifdef NOUVEAU_DEBUG
350 nvc0_pc_print_binary(pc);
351 #else
352 debug_printf("not printing binary\n");
353 #endif
354 return 0;
355 }
356
357 int
358 nvc0_generate_code(struct nvc0_translation_info *ti)
359 {
360 struct nv_pc *pc;
361 int ret;
362 int i;
363
364 pc = CALLOC_STRUCT(nv_pc);
365 if (!pc)
366 return 1;
367
368 pc->is_fragprog = ti->prog->type == PIPE_SHADER_FRAGMENT;
369
370 pc->root = CALLOC(ti->num_subrs + 1, sizeof(pc->root[0]));
371 if (!pc->root) {
372 FREE(pc);
373 return 1;
374 }
375 pc->num_subroutines = ti->num_subrs;
376
377 ret = nvc0_tgsi_to_nc(pc, ti);
378 if (ret)
379 goto out;
380 #if NOUVEAU_DEBUG > 1
381 nvc0_print_program(pc);
382 #endif
383
384 pc->opt_reload_elim = ti->require_stores ? FALSE : TRUE;
385
386 /* optimization */
387 ret = nvc0_pc_exec_pass0(pc);
388 if (ret)
389 goto out;
390 #ifdef NOUVEAU_DEBUG
391 nvc0_print_program(pc);
392 #endif
393
394 /* register allocation */
395 ret = nvc0_pc_exec_pass1(pc);
396 if (ret)
397 goto out;
398 #if NOUVEAU_DEBUG > 1
399 nv_print_program(pc);
400 nv_print_cfgraph(pc, "nvc0_shader_cfgraph.dot", 0);
401 #endif
402
403 /* prepare for emission */
404 ret = nvc0_pc_exec_pass2(pc);
405 if (ret)
406 goto out;
407 assert(!(pc->emit_size % 8));
408
409 pc->emit = CALLOC(pc->emit_size / 4 + 2, 4);
410 if (!pc->emit) {
411 ret = 3;
412 goto out;
413 }
414 ret = nvc0_emit_program(pc);
415 if (ret)
416 goto out;
417
418 ti->prog->code = pc->emit;
419 ti->prog->code_base = 0;
420 ti->prog->code_size = pc->emit_size;
421 ti->prog->parm_size = 0;
422
423 ti->prog->max_gpr = MAX2(4, pc->max_reg[NV_FILE_GPR] + 1);
424
425 ti->prog->relocs = pc->reloc_entries;
426 ti->prog->num_relocs = pc->num_relocs;
427
428 NOUVEAU_DBG("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
429
430 out:
431 nv_pc_free_refs(pc);
432
433 for (i = 0; i < pc->num_blocks; ++i)
434 FREE(pc->bb_list[i]);
435 if (pc->root)
436 FREE(pc->root);
437 if (ret) {
438 /* on success, these will be referenced by struct nvc0_program */
439 if (pc->emit)
440 FREE(pc->emit);
441 if (pc->immd_buf)
442 FREE(pc->immd_buf);
443 if (pc->reloc_entries)
444 FREE(pc->reloc_entries);
445 }
446 FREE(pc);
447 return ret;
448 }
449
450 static void
451 nvbb_insert_phi(struct nv_basic_block *b, struct nv_instruction *i)
452 {
453 if (!b->phi) {
454 i->prev = NULL;
455 b->phi = i;
456 i->next = b->entry;
457 if (b->entry) {
458 assert(!b->entry->prev && b->exit);
459 b->entry->prev = i;
460 } else {
461 b->entry = i;
462 b->exit = i;
463 }
464 } else {
465 assert(b->entry);
466 if (b->entry->opcode == NV_OP_PHI) { /* insert after entry */
467 assert(b->entry == b->exit);
468 b->entry->next = i;
469 i->prev = b->entry;
470 b->entry = i;
471 b->exit = i;
472 } else { /* insert before entry */
473 assert(b->entry->prev && b->exit);
474 i->next = b->entry;
475 i->prev = b->entry->prev;
476 b->entry->prev = i;
477 i->prev->next = i;
478 }
479 }
480 }
481
482 void
483 nvc0_insn_append(struct nv_basic_block *b, struct nv_instruction *i)
484 {
485 if (i->opcode == NV_OP_PHI) {
486 nvbb_insert_phi(b, i);
487 } else {
488 i->prev = b->exit;
489 if (b->exit)
490 b->exit->next = i;
491 b->exit = i;
492 if (!b->entry)
493 b->entry = i;
494 else
495 if (i->prev && i->prev->opcode == NV_OP_PHI)
496 b->entry = i;
497 }
498
499 i->bb = b;
500 b->num_instructions++;
501 }
502
503 void
504 nvc0_insn_insert_after(struct nv_instruction *at, struct nv_instruction *ni)
505 {
506 if (!at->next) {
507 nvc0_insn_append(at->bb, ni);
508 return;
509 }
510 ni->next = at->next;
511 ni->prev = at;
512 ni->next->prev = ni;
513 ni->prev->next = ni;
514 }
515
516 void
517 nvc0_insn_delete(struct nv_instruction *nvi)
518 {
519 struct nv_basic_block *b = nvi->bb;
520 int s;
521
522 /* debug_printf("REM: "); nv_print_instruction(nvi); */
523
524 for (s = 0; s < 6 && nvi->src[s]; ++s)
525 nv_reference(NULL, nvi, s, NULL);
526
527 if (nvi->next)
528 nvi->next->prev = nvi->prev;
529 else {
530 assert(nvi == b->exit);
531 b->exit = nvi->prev;
532 }
533
534 if (nvi->prev)
535 nvi->prev->next = nvi->next;
536
537 if (nvi == b->entry) {
538 /* PHIs don't get hooked to b->entry */
539 b->entry = nvi->next;
540 assert(!nvi->prev || nvi->prev->opcode == NV_OP_PHI);
541 }
542
543 if (nvi == b->phi) {
544 if (nvi->opcode != NV_OP_PHI)
545 NOUVEAU_DBG("NOTE: b->phi points to non-PHI instruction\n");
546
547 assert(!nvi->prev);
548 if (!nvi->next || nvi->next->opcode != NV_OP_PHI)
549 b->phi = NULL;
550 else
551 b->phi = nvi->next;
552 }
553 }
554
555 void
556 nvc0_insns_permute(struct nv_instruction *i1, struct nv_instruction *i2)
557 {
558 struct nv_basic_block *b = i1->bb;
559
560 assert(i1->opcode != NV_OP_PHI &&
561 i2->opcode != NV_OP_PHI);
562 assert(i1->next == i2);
563
564 if (b->exit == i2)
565 b->exit = i1;
566
567 if (b->entry == i1)
568 b->entry = i2;
569
570 i2->prev = i1->prev;
571 i1->next = i2->next;
572 i2->next = i1;
573 i1->prev = i2;
574
575 if (i2->prev)
576 i2->prev->next = i2;
577 if (i1->next)
578 i1->next->prev = i1;
579 }
580
581 void
582 nvc0_bblock_attach(struct nv_basic_block *parent,
583 struct nv_basic_block *b, ubyte edge_kind)
584 {
585 assert(b->num_in < 8);
586
587 if (parent->out[0]) {
588 assert(!parent->out[1]);
589 parent->out[1] = b;
590 parent->out_kind[1] = edge_kind;
591 } else {
592 parent->out[0] = b;
593 parent->out_kind[0] = edge_kind;
594 }
595
596 b->in[b->num_in] = parent;
597 b->in_kind[b->num_in++] = edge_kind;
598 }
599
600 /* NOTE: all BRKs are treated as conditional, so there are 2 outgoing BBs */
601
602 boolean
603 nvc0_bblock_dominated_by(struct nv_basic_block *b, struct nv_basic_block *d)
604 {
605 int j;
606
607 if (b == d)
608 return TRUE;
609
610 for (j = 0; j < b->num_in; ++j)
611 if ((b->in_kind[j] != CFG_EDGE_BACK) &&
612 !nvc0_bblock_dominated_by(b->in[j], d))
613 return FALSE;
614
615 return j ? TRUE : FALSE;
616 }
617
618 /* check if @bf (future) can be reached from @bp (past), stop at @bt */
619 boolean
620 nvc0_bblock_reachable_by(struct nv_basic_block *bf, struct nv_basic_block *bp,
621 struct nv_basic_block *bt)
622 {
623 struct nv_basic_block *q[NV_PC_MAX_BASIC_BLOCKS], *b;
624 int i, p, n;
625
626 p = 0;
627 n = 1;
628 q[0] = bp;
629
630 while (p < n) {
631 b = q[p++];
632
633 if (b == bf)
634 break;
635 if (b == bt)
636 continue;
637 assert(n <= (1024 - 2));
638
639 for (i = 0; i < 2; ++i) {
640 if (b->out[i] && !IS_WALL_EDGE(b->out_kind[i]) && !b->out[i]->priv) {
641 q[n] = b->out[i];
642 q[n++]->priv = 1;
643 }
644 }
645 }
646 for (--n; n >= 0; --n)
647 q[n]->priv = 0;
648
649 return (b == bf);
650 }
651
652 static struct nv_basic_block *
653 nvbb_find_dom_frontier(struct nv_basic_block *b, struct nv_basic_block *df)
654 {
655 struct nv_basic_block *out;
656 int i;
657
658 if (!nvc0_bblock_dominated_by(df, b)) {
659 for (i = 0; i < df->num_in; ++i) {
660 if (df->in_kind[i] == CFG_EDGE_BACK)
661 continue;
662 if (nvc0_bblock_dominated_by(df->in[i], b))
663 return df;
664 }
665 }
666 for (i = 0; i < 2 && df->out[i]; ++i) {
667 if (df->out_kind[i] == CFG_EDGE_BACK)
668 continue;
669 if ((out = nvbb_find_dom_frontier(b, df->out[i])))
670 return out;
671 }
672 return NULL;
673 }
674
675 struct nv_basic_block *
676 nvc0_bblock_dom_frontier(struct nv_basic_block *b)
677 {
678 struct nv_basic_block *df;
679 int i;
680
681 for (i = 0; i < 2 && b->out[i]; ++i)
682 if ((df = nvbb_find_dom_frontier(b, b->out[i])))
683 return df;
684 return NULL;
685 }