radeon: make texture logging more useful
[mesa.git] / src / gallium / drivers / r600 / sb / sb_bc_parser.cpp
1 /*
2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Vadim Girlin
25 */
26
27 #define BCP_DEBUG 0
28
29 #if BCP_DEBUG
30 #define BCP_DUMP(q) do { q } while (0)
31 #else
32 #define BCP_DUMP(q)
33 #endif
34
35 extern "C" {
36 #include "r600_pipe.h"
37 #include "r600_shader.h"
38 }
39
40 #include <stack>
41
42 #include "sb_bc.h"
43 #include "sb_shader.h"
44 #include "sb_pass.h"
45
46 namespace r600_sb {
47
48 int bc_parser::decode() {
49
50 dw = bc->bytecode;
51 bc_ndw = bc->ndw;
52 max_cf = 0;
53
54 dec = new bc_decoder(ctx, dw, bc_ndw);
55
56 shader_target t = TARGET_UNKNOWN;
57
58 if (pshader) {
59 switch (bc->type) {
60 case TGSI_PROCESSOR_FRAGMENT: t = TARGET_PS; break;
61 case TGSI_PROCESSOR_VERTEX: t = TARGET_VS; break;
62 case TGSI_PROCESSOR_COMPUTE: t = TARGET_COMPUTE; break;
63 default: assert(!"unknown shader target"); return -1; break;
64 }
65 } else {
66 if (bc->type == TGSI_PROCESSOR_COMPUTE)
67 t = TARGET_COMPUTE;
68 else
69 t = TARGET_FETCH;
70 }
71
72 sh = new shader(ctx, t, bc->debug_id);
73 sh->safe_math = sb_context::safe_math || (t == TARGET_COMPUTE);
74
75 int r = decode_shader();
76
77 delete dec;
78
79 sh->ngpr = bc->ngpr;
80 sh->nstack = bc->nstack;
81
82 return r;
83 }
84
85 int bc_parser::decode_shader() {
86 int r = 0;
87 unsigned i = 0;
88 bool eop = false;
89
90 sh->init();
91
92 do {
93 eop = false;
94 if ((r = decode_cf(i, eop)))
95 return r;
96
97 } while (!eop || (i >> 1) <= max_cf);
98
99 return 0;
100 }
101
102 int bc_parser::prepare() {
103 int r = 0;
104 if ((r = parse_decls()))
105 return r;
106 if ((r = prepare_ir()))
107 return r;
108 return 0;
109 }
110
111 int bc_parser::parse_decls() {
112
113 if (!pshader) {
114 if (gpr_reladdr)
115 sh->add_gpr_array(0, bc->ngpr, 0x0F);
116
117 // compute shaders have some values preloaded in R0, R1
118 sh->add_input(0 /* GPR */, true /* preloaded */, 0x0F /* mask */);
119 sh->add_input(1 /* GPR */, true /* preloaded */, 0x0F /* mask */);
120 return 0;
121 }
122
123 if (pshader->indirect_files & ~(1 << TGSI_FILE_CONSTANT)) {
124
125 assert(pshader->num_arrays);
126
127 if (pshader->num_arrays) {
128 for (unsigned i = 0; i < pshader->num_arrays; ++i) {
129 r600_shader_array &a = pshader->arrays[i];
130 sh->add_gpr_array(a.gpr_start, a.gpr_count, a.comp_mask);
131 }
132 } else {
133 sh->add_gpr_array(0, pshader->bc.ngpr, 0x0F);
134 }
135 }
136
137 if (sh->target == TARGET_VS)
138 sh->add_input(0, 1, 0x0F);
139
140 bool ps_interp = ctx.hw_class >= HW_CLASS_EVERGREEN
141 && sh->target == TARGET_PS;
142
143 unsigned linear = 0, persp = 0, centroid = 1;
144
145 for (unsigned i = 0; i < pshader->ninput; ++i) {
146 r600_shader_io & in = pshader->input[i];
147 bool preloaded = sh->target == TARGET_PS && !(ps_interp && in.spi_sid);
148 sh->add_input(in.gpr, preloaded, /*in.write_mask*/ 0x0F);
149 if (ps_interp && in.spi_sid) {
150 if (in.interpolate == TGSI_INTERPOLATE_LINEAR ||
151 in.interpolate == TGSI_INTERPOLATE_COLOR)
152 linear = 1;
153 else if (in.interpolate == TGSI_INTERPOLATE_PERSPECTIVE)
154 persp = 1;
155 if (in.centroid)
156 centroid = 2;
157 }
158 }
159
160 if (ps_interp) {
161 unsigned mask = (1 << (2 * (linear + persp) * centroid)) - 1;
162 unsigned gpr = 0;
163
164 while (mask) {
165 sh->add_input(gpr, true, mask & 0x0F);
166 ++gpr;
167 mask >>= 4;
168 }
169 }
170
171 return 0;
172 }
173
174 int bc_parser::decode_cf(unsigned &i, bool &eop) {
175
176 int r;
177
178 cf_node *cf = sh->create_cf();
179 sh->root->push_back(cf);
180
181 unsigned id = i >> 1;
182
183 cf->bc.id = id;
184
185 if (cf_map.size() < id + 1)
186 cf_map.resize(id + 1);
187
188 cf_map[id] = cf;
189
190 if ((r = dec->decode_cf(i, cf->bc)))
191 return r;
192
193 cf_op_flags flags = (cf_op_flags)cf->bc.op_ptr->flags;
194
195 if (flags & CF_ALU) {
196 if ((r = decode_alu_clause(cf)))
197 return r;
198 } else if (flags & CF_FETCH) {
199 if ((r = decode_fetch_clause(cf)))
200 return r;;
201 } else if (flags & CF_EXP) {
202 if (cf->bc.rw_rel)
203 gpr_reladdr = true;
204 assert(!cf->bc.rw_rel);
205 } else if (flags & (CF_STRM | CF_RAT)) {
206 if (cf->bc.rw_rel)
207 gpr_reladdr = true;
208 assert(!cf->bc.rw_rel);
209 } else if (flags & CF_BRANCH) {
210 if (cf->bc.addr > max_cf)
211 max_cf = cf->bc.addr;
212 }
213
214 eop = cf->bc.end_of_program || cf->bc.op == CF_OP_CF_END ||
215 cf->bc.op == CF_OP_RET;
216 return 0;
217 }
218
219 int bc_parser::decode_alu_clause(cf_node* cf) {
220 unsigned i = cf->bc.addr << 1, cnt = cf->bc.count + 1, gcnt;
221
222 cf->subtype = NST_ALU_CLAUSE;
223
224 cgroup = 0;
225 memset(slots[0], 0, 5*sizeof(slots[0][0]));
226
227 unsigned ng = 0;
228
229 do {
230 decode_alu_group(cf, i, gcnt);
231 assert(gcnt <= cnt);
232 cnt -= gcnt;
233 ng++;
234 } while (cnt);
235
236 return 0;
237 }
238
239 int bc_parser::decode_alu_group(cf_node* cf, unsigned &i, unsigned &gcnt) {
240 int r;
241 alu_node *n;
242 alu_group_node *g = sh->create_alu_group();
243
244 cgroup = !cgroup;
245 memset(slots[cgroup], 0, 5*sizeof(slots[0][0]));
246 gcnt = 0;
247
248 unsigned literal_mask = 0;
249
250 do {
251 n = sh->create_alu();
252 g->push_back(n);
253
254 if ((r = dec->decode_alu(i, n->bc)))
255 return r;
256
257 if (!sh->assign_slot(n, slots[cgroup])) {
258 assert(!"alu slot assignment failed");
259 return -1;
260 }
261
262 gcnt++;
263
264 } while (gcnt <= 5 && !n->bc.last);
265
266 assert(n->bc.last);
267
268 for (node_iterator I = g->begin(), E = g->end(); I != E; ++I) {
269 n = static_cast<alu_node*>(*I);
270
271 if (n->bc.dst_rel)
272 gpr_reladdr = true;
273
274 for (int k = 0; k < n->bc.op_ptr->src_count; ++k) {
275 bc_alu_src &src = n->bc.src[k];
276 if (src.rel)
277 gpr_reladdr = true;
278 if (src.sel == ALU_SRC_LITERAL) {
279 literal_mask |= (1 << src.chan);
280 src.value.u = dw[i + src.chan];
281 }
282 }
283 }
284
285 unsigned literal_ndw = 0;
286 while (literal_mask) {
287 g->literals.push_back(dw[i + literal_ndw]);
288 literal_ndw += 1;
289 literal_mask >>= 1;
290 }
291
292 literal_ndw = (literal_ndw + 1) & ~1u;
293
294 i += literal_ndw;
295 gcnt += literal_ndw >> 1;
296
297 cf->push_back(g);
298 return 0;
299 }
300
301 int bc_parser::prepare_alu_clause(cf_node* cf) {
302
303 // loop over alu groups
304 for (node_iterator I = cf->begin(), E = cf->end(); I != E; ++I) {
305 assert(I->subtype == NST_ALU_GROUP);
306 alu_group_node *g = static_cast<alu_group_node*>(*I);
307 prepare_alu_group(cf, g);
308 }
309
310 return 0;
311 }
312
313 int bc_parser::prepare_alu_group(cf_node* cf, alu_group_node *g) {
314
315 alu_node *n;
316
317 cgroup = !cgroup;
318 memset(slots[cgroup], 0, 5*sizeof(slots[0][0]));
319
320 for (node_iterator I = g->begin(), E = g->end();
321 I != E; ++I) {
322 n = static_cast<alu_node*>(*I);
323
324 if (!sh->assign_slot(n, slots[cgroup])) {
325 assert(!"alu slot assignment failed");
326 return -1;
327 }
328
329 unsigned src_count = n->bc.op_ptr->src_count;
330
331 if (ctx.alu_slots(n->bc.op) & AF_4SLOT)
332 n->flags |= NF_ALU_4SLOT;
333
334 n->src.resize(src_count);
335
336 unsigned flags = n->bc.op_ptr->flags;
337
338 if (flags & AF_PRED) {
339 n->dst.resize(3);
340 if (n->bc.update_pred)
341 n->dst[1] = sh->get_special_value(SV_ALU_PRED);
342 if (n->bc.update_exec_mask)
343 n->dst[2] = sh->get_special_value(SV_EXEC_MASK);
344
345 n->flags |= NF_DONT_HOIST;
346
347 } else if (flags & AF_KILL) {
348
349 n->dst.resize(2);
350 n->dst[1] = sh->get_special_value(SV_VALID_MASK);
351 sh->set_uses_kill();
352
353 n->flags |= NF_DONT_HOIST | NF_DONT_MOVE |
354 NF_DONT_KILL | NF_SCHEDULE_EARLY;
355
356 } else {
357 n->dst.resize(1);
358 }
359
360 if (flags & AF_MOVA) {
361
362 n->dst[0] = sh->get_special_value(SV_AR_INDEX);
363
364 n->flags |= NF_DONT_HOIST;
365
366 } else if (n->bc.op_ptr->src_count == 3 || n->bc.write_mask) {
367 assert(!n->bc.dst_rel || n->bc.index_mode == INDEX_AR_X);
368
369 value *v = sh->get_gpr_value(false, n->bc.dst_gpr, n->bc.dst_chan,
370 n->bc.dst_rel);
371
372 n->dst[0] = v;
373 }
374
375 if (n->bc.pred_sel) {
376 sh->has_alu_predication = true;
377 n->pred = sh->get_special_value(SV_ALU_PRED);
378 }
379
380 for (unsigned s = 0; s < src_count; ++s) {
381 bc_alu_src &src = n->bc.src[s];
382
383 if (src.sel == ALU_SRC_LITERAL) {
384 n->src[s] = sh->get_const_value(src.value);
385 } else if (src.sel == ALU_SRC_PS || src.sel == ALU_SRC_PV) {
386 unsigned pgroup = !cgroup, prev_slot = src.sel == ALU_SRC_PS ?
387 SLOT_TRANS : src.chan;
388
389 // XXX shouldn't happen but llvm backend uses PS on cayman
390 if (prev_slot == SLOT_TRANS && ctx.is_cayman())
391 prev_slot = SLOT_X;
392
393 alu_node *prev_alu = slots[pgroup][prev_slot];
394
395 assert(prev_alu);
396
397 if (!prev_alu->dst[0]) {
398 value * t = sh->create_temp_value();
399 prev_alu->dst[0] = t;
400 }
401
402 value *d = prev_alu->dst[0];
403
404 if (d->is_rel()) {
405 d = sh->get_gpr_value(true, prev_alu->bc.dst_gpr,
406 prev_alu->bc.dst_chan,
407 prev_alu->bc.dst_rel);
408 }
409
410 n->src[s] = d;
411 } else if (ctx.is_kcache_sel(src.sel)) {
412 unsigned sel = src.sel, kc_addr;
413 unsigned kc_set = ((sel >> 7) & 2) + ((sel >> 5) & 1);
414
415 bc_kcache &kc = cf->bc.kc[kc_set];
416 kc_addr = (kc.addr << 4) + (sel & 0x1F);
417 n->src[s] = sh->get_kcache_value(kc.bank, kc_addr, src.chan);
418 } else if (src.sel < MAX_GPR) {
419 value *v = sh->get_gpr_value(true, src.sel, src.chan, src.rel);
420
421 n->src[s] = v;
422
423 } else if (src.sel >= ALU_SRC_PARAM_OFFSET) {
424 // using slot for value channel because in fact the slot
425 // determines the channel that is loaded by INTERP_LOAD_P0
426 // (and maybe some others).
427 // otherwise GVN will consider INTERP_LOAD_P0s with the same
428 // param index as equal instructions and leave only one of them
429 n->src[s] = sh->get_special_ro_value(sel_chan(src.sel,
430 n->bc.slot));
431 } else {
432 switch (src.sel) {
433 case ALU_SRC_0:
434 n->src[s] = sh->get_const_value(0);
435 break;
436 case ALU_SRC_0_5:
437 n->src[s] = sh->get_const_value(0.5f);
438 break;
439 case ALU_SRC_1:
440 n->src[s] = sh->get_const_value(1.0f);
441 break;
442 case ALU_SRC_1_INT:
443 n->src[s] = sh->get_const_value(1);
444 break;
445 case ALU_SRC_M_1_INT:
446 n->src[s] = sh->get_const_value(-1);
447 break;
448 default:
449 n->src[s] = sh->get_special_ro_value(src.sel);
450 break;
451 }
452 }
453 }
454 }
455
456 // pack multislot instructions into alu_packed_node
457
458 alu_packed_node *p = NULL;
459 for (node_iterator N, I = g->begin(), E = g->end(); I != E; I = N) {
460 N = I + 1;
461 alu_node *a = static_cast<alu_node*>(*I);
462 unsigned sflags = a->bc.slot_flags;
463
464 if (sflags == AF_4V || (ctx.is_cayman() && sflags == AF_S)) {
465 if (!p)
466 p = sh->create_alu_packed();
467
468 a->remove();
469 p->push_back(a);
470 }
471 }
472
473 if (p) {
474 g->push_front(p);
475
476 if (p->count() == 3 && ctx.is_cayman()) {
477 // cayman's scalar instruction that can use 3 or 4 slots
478
479 // FIXME for simplicity we'll always add 4th slot,
480 // but probably we might want to always remove 4th slot and make
481 // sure that regalloc won't choose 'w' component for dst
482
483 alu_node *f = static_cast<alu_node*>(p->first);
484 alu_node *a = sh->create_alu();
485 a->src = f->src;
486 a->dst.resize(f->dst.size());
487 a->bc = f->bc;
488 a->bc.slot = SLOT_W;
489 p->push_back(a);
490 }
491 }
492
493 return 0;
494 }
495
496 int bc_parser::decode_fetch_clause(cf_node* cf) {
497 int r;
498 unsigned i = cf->bc.addr << 1, cnt = cf->bc.count + 1;
499
500 cf->subtype = NST_TEX_CLAUSE;
501
502 while (cnt--) {
503 fetch_node *n = sh->create_fetch();
504 cf->push_back(n);
505 if ((r = dec->decode_fetch(i, n->bc)))
506 return r;
507 if (n->bc.src_rel || n->bc.dst_rel)
508 gpr_reladdr = true;
509
510 }
511 return 0;
512 }
513
514 int bc_parser::prepare_fetch_clause(cf_node *cf) {
515
516 vvec grad_v, grad_h;
517
518 for (node_iterator I = cf->begin(), E = cf->end(); I != E; ++I) {
519
520 fetch_node *n = static_cast<fetch_node*>(*I);
521 assert(n->is_valid());
522
523 unsigned flags = n->bc.op_ptr->flags;
524
525 unsigned vtx = flags & FF_VTX;
526 unsigned num_src = vtx ? ctx.vtx_src_num : 4;
527
528 n->dst.resize(4);
529
530 if (flags & (FF_SETGRAD | FF_USEGRAD | FF_GETGRAD)) {
531 sh->uses_gradients = true;
532 }
533
534 if (flags & FF_SETGRAD) {
535
536 vvec *grad = NULL;
537
538 switch (n->bc.op) {
539 case FETCH_OP_SET_GRADIENTS_V:
540 grad = &grad_v;
541 break;
542 case FETCH_OP_SET_GRADIENTS_H:
543 grad = &grad_h;
544 break;
545 default:
546 assert(!"unexpected SET_GRAD instruction");
547 return -1;
548 }
549
550 if (grad->empty())
551 grad->resize(4);
552
553 for(unsigned s = 0; s < 4; ++s) {
554 unsigned sw = n->bc.src_sel[s];
555 if (sw <= SEL_W)
556 (*grad)[s] = sh->get_gpr_value(true, n->bc.src_gpr,
557 sw, false);
558 else if (sw == SEL_0)
559 (*grad)[s] = sh->get_const_value(0.0f);
560 else if (sw == SEL_1)
561 (*grad)[s] = sh->get_const_value(1.0f);
562 }
563 } else {
564
565 if (flags & FF_USEGRAD) {
566 n->src.resize(12);
567 std::copy(grad_v.begin(), grad_v.end(), n->src.begin() + 4);
568 std::copy(grad_h.begin(), grad_h.end(), n->src.begin() + 8);
569 } else {
570 n->src.resize(4);
571 }
572
573 for(int s = 0; s < 4; ++s) {
574 if (n->bc.dst_sel[s] != SEL_MASK)
575 n->dst[s] = sh->get_gpr_value(false, n->bc.dst_gpr, s, false);
576 // NOTE: it doesn't matter here which components of the result we
577 // are using, but original n->bc.dst_sel should be taken into
578 // account when building the bytecode
579 }
580 for(unsigned s = 0; s < num_src; ++s) {
581 if (n->bc.src_sel[s] <= SEL_W)
582 n->src[s] = sh->get_gpr_value(true, n->bc.src_gpr,
583 n->bc.src_sel[s], false);
584 }
585
586 }
587 }
588
589 return 0;
590 }
591
592 int bc_parser::prepare_ir() {
593
594 for(id_cf_map::iterator I = cf_map.begin(), E = cf_map.end(); I != E; ++I) {
595 cf_node *c = *I;
596
597 if (!c)
598 continue;
599
600 unsigned flags = c->bc.op_ptr->flags;
601
602 if (flags & CF_ALU) {
603 prepare_alu_clause(c);
604 } else if (flags & CF_FETCH) {
605 prepare_fetch_clause(c);
606 } else if (c->bc.op == CF_OP_CALL_FS) {
607 sh->init_call_fs(c);
608 c->flags |= NF_SCHEDULE_EARLY | NF_DONT_MOVE;
609 } else if (flags & CF_LOOP_START) {
610 prepare_loop(c);
611 } else if (c->bc.op == CF_OP_JUMP) {
612 prepare_if(c);
613 } else if (c->bc.op == CF_OP_LOOP_END) {
614 loop_stack.pop();
615 } else if (c->bc.op == CF_OP_LOOP_CONTINUE) {
616 assert(!loop_stack.empty());
617 repeat_node *rep = sh->create_repeat(loop_stack.top());
618 if (c->parent->first != c)
619 rep->move(c->parent->first, c);
620 c->replace_with(rep);
621 sh->simplify_dep_rep(rep);
622 } else if (c->bc.op == CF_OP_LOOP_BREAK) {
623 assert(!loop_stack.empty());
624 depart_node *dep = sh->create_depart(loop_stack.top());
625 if (c->parent->first != c)
626 dep->move(c->parent->first, c);
627 c->replace_with(dep);
628 sh->simplify_dep_rep(dep);
629 } else if (flags & CF_EXP) {
630
631 // unroll burst exports
632
633 assert(c->bc.op == CF_OP_EXPORT || c->bc.op == CF_OP_EXPORT_DONE);
634
635 c->bc.set_op(CF_OP_EXPORT);
636
637 unsigned burst_count = c->bc.burst_count;
638 unsigned eop = c->bc.end_of_program;
639
640 c->bc.end_of_program = 0;
641 c->bc.burst_count = 0;
642
643 do {
644 c->src.resize(4);
645
646 for(int s = 0; s < 4; ++s) {
647 switch (c->bc.sel[s]) {
648 case SEL_0:
649 c->src[s] = sh->get_const_value(0.0f);
650 break;
651 case SEL_1:
652 c->src[s] = sh->get_const_value(1.0f);
653 break;
654 case SEL_MASK:
655 break;
656 default:
657 if (c->bc.sel[s] <= SEL_W)
658 c->src[s] = sh->get_gpr_value(true, c->bc.rw_gpr,
659 c->bc.sel[s], false);
660 else
661 assert(!"invalid src_sel for export");
662 }
663 }
664
665 if (!burst_count--)
666 break;
667
668 cf_node *cf_next = sh->create_cf();
669 cf_next->bc = c->bc;
670 ++cf_next->bc.rw_gpr;
671 ++cf_next->bc.array_base;
672
673 c->insert_after(cf_next);
674 c = cf_next;
675
676 } while (1);
677
678 c->bc.end_of_program = eop;
679 } else if (flags & (CF_STRM | CF_RAT)) {
680
681 unsigned burst_count = c->bc.burst_count;
682 unsigned eop = c->bc.end_of_program;
683
684 c->bc.end_of_program = 0;
685 c->bc.burst_count = 0;
686
687 do {
688
689 c->src.resize(4);
690
691 for(int s = 0; s < 4; ++s) {
692 if (c->bc.comp_mask & (1 << s))
693 c->src[s] =
694 sh->get_gpr_value(true, c->bc.rw_gpr, s, false);
695 }
696
697 if ((flags & CF_RAT) && (c->bc.type & 1)) { // indexed write
698 c->src.resize(8);
699 for(int s = 0; s < 3; ++s) {
700 c->src[4 + s] =
701 sh->get_gpr_value(true, c->bc.index_gpr, s, false);
702 }
703
704 // FIXME probably we can relax it a bit
705 c->flags |= NF_DONT_HOIST | NF_DONT_MOVE;
706 }
707
708 if (!burst_count--)
709 break;
710
711 cf_node *cf_next = sh->create_cf();
712 cf_next->bc = c->bc;
713 ++cf_next->bc.rw_gpr;
714
715 // FIXME is it correct?
716 cf_next->bc.array_base += cf_next->bc.elem_size + 1;
717
718 c->insert_after(cf_next);
719 c = cf_next;
720 } while (1);
721
722 c->bc.end_of_program = eop;
723
724 }
725 }
726
727 assert(loop_stack.empty());
728 return 0;
729 }
730
731 int bc_parser::prepare_loop(cf_node* c) {
732
733 cf_node *end = cf_map[c->bc.addr - 1];
734 assert(end->bc.op == CF_OP_LOOP_END);
735 assert(c->parent == end->parent);
736
737 region_node *reg = sh->create_region();
738 repeat_node *rep = sh->create_repeat(reg);
739
740 reg->push_back(rep);
741 c->insert_before(reg);
742 rep->move(c, end->next);
743
744 loop_stack.push(reg);
745 return 0;
746 }
747
748 int bc_parser::prepare_if(cf_node* c) {
749 cf_node *c_else = NULL, *end = cf_map[c->bc.addr];
750
751 BCP_DUMP(
752 sblog << "parsing JUMP @" << c->bc.id;
753 sblog << "\n";
754 );
755
756 if (end->bc.op == CF_OP_ELSE) {
757 BCP_DUMP(
758 sblog << " found ELSE : ";
759 dump::dump_op(end);
760 sblog << "\n";
761 );
762
763 c_else = end;
764 end = cf_map[c_else->bc.addr];
765 } else {
766 BCP_DUMP(
767 sblog << " no else\n";
768 );
769
770 c_else = end;
771 }
772
773 if (c_else->parent != c->parent)
774 c_else = NULL;
775
776 if (end->parent != c->parent)
777 end = NULL;
778
779 region_node *reg = sh->create_region();
780
781 depart_node *dep2 = sh->create_depart(reg);
782 depart_node *dep = sh->create_depart(reg);
783 if_node *n_if = sh->create_if();
784
785 c->insert_before(reg);
786
787 if (c_else != end)
788 dep->move(c_else, end);
789 dep2->move(c, end);
790
791 reg->push_back(dep);
792 dep->push_front(n_if);
793 n_if->push_back(dep2);
794
795 n_if->cond = sh->get_special_value(SV_EXEC_MASK);
796
797 return 0;
798 }
799
800
801 } // namespace r600_sb