mesa/st/glsl_to_tgsi: Add some operators for glsl_to_tgsi related classes
[mesa.git] / src / mesa / state_tracker / st_glsl_to_tgsi_temprename.cpp
1 /*
2 * Copyright © 2017 Gert Wollny
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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "st_glsl_to_tgsi_temprename.h"
25 #include "tgsi/tgsi_info.h"
26 #include "tgsi/tgsi_strings.h"
27 #include "program/prog_instruction.h"
28 #include "util/bitscan.h"
29 #include <limits>
30 #include <cstdlib>
31
32 /* std::sort is significantly faster than qsort */
33 #define USE_STL_SORT
34 #ifdef USE_STL_SORT
35 #include <algorithm>
36 #endif
37
38 #ifndef NDEBUG
39 #include <iostream>
40 #include <iomanip>
41 #include "program/prog_print.h"
42 #include "util/debug.h"
43 using std::cerr;
44 using std::setw;
45 using std::ostream;
46 #endif
47
48 /* If <windows.h> is included this is defined and clashes with
49 * std::numeric_limits<>::max()
50 */
51 #ifdef max
52 #undef max
53 #endif
54
55 using std::numeric_limits;
56
57 /* Without c++11 define the nullptr for forward-compatibility
58 * and better readibility */
59 #if __cplusplus < 201103L
60 #define nullptr 0
61 #endif
62
63 #ifndef NDEBUG
64 /* Prepare to make it possible to specify log file */
65 static std::ostream& debug_log = cerr;
66
67 /* Helper function to check whether we want to seen debugging output */
68 static inline bool is_debug_enabled ()
69 {
70 static int debug_enabled = -1;
71 if (debug_enabled < 0)
72 debug_enabled = env_var_as_boolean("GLSL_TO_TGSI_RENAME_DEBUG", false);
73 return debug_enabled > 0;
74 }
75 #define RENAME_DEBUG(X) if (is_debug_enabled()) do { X; } while (false);
76 #else
77 #define RENAME_DEBUG(X)
78 #endif
79
80 namespace {
81
82 enum prog_scope_type {
83 outer_scope, /* Outer program scope */
84 loop_body, /* Inside a loop */
85 if_branch, /* Inside if branch */
86 else_branch, /* Inside else branch */
87 switch_body, /* Inside switch statmenet */
88 switch_case_branch, /* Inside switch case statmenet */
89 switch_default_branch, /* Inside switch default statmenet */
90 undefined_scope
91 };
92
93 class prog_scope {
94 public:
95 prog_scope(prog_scope *parent, prog_scope_type type, int id,
96 int depth, int begin);
97
98 prog_scope_type type() const;
99 prog_scope *parent() const;
100 int nesting_depth() const;
101 int id() const;
102 int end() const;
103 int begin() const;
104 int loop_break_line() const;
105
106 const prog_scope *in_ifelse_scope() const;
107 const prog_scope *in_switchcase_scope() const;
108 const prog_scope *innermost_loop() const;
109 const prog_scope *outermost_loop() const;
110 const prog_scope *enclosing_conditional() const;
111
112 bool is_loop() const;
113 bool is_in_loop() const;
114 bool is_conditional() const;
115
116 bool break_is_for_switchcase() const;
117 bool contains_range_of(const prog_scope& other) const;
118
119 void set_end(int end);
120 void set_loop_break_line(int line);
121
122 private:
123 prog_scope_type scope_type;
124 int scope_id;
125 int scope_nesting_depth;
126 int scope_begin;
127 int scope_end;
128 int break_loop_line;
129 prog_scope *parent_scope;
130 };
131
132 /* Some storage class to encapsulate the prog_scope (de-)allocations */
133 class prog_scope_storage {
134 public:
135 prog_scope_storage(void *mem_ctx, int n);
136 ~prog_scope_storage();
137 prog_scope * create(prog_scope *p, prog_scope_type type, int id,
138 int lvl, int s_begin);
139 private:
140 void *mem_ctx;
141 int current_slot;
142 prog_scope *storage;
143 };
144
145 class temp_comp_access {
146 public:
147 temp_comp_access();
148 void record_read(int line, prog_scope *scope);
149 void record_write(int line, prog_scope *scope);
150 lifetime get_required_lifetime();
151 private:
152 void propagate_lifetime_to_dominant_write_scope();
153
154 prog_scope *last_read_scope;
155 prog_scope *first_read_scope;
156 prog_scope *first_write_scope;
157 int first_write;
158 int last_read;
159 int last_write;
160 int first_read;
161 bool keep_for_full_loop;
162 };
163
164 class temp_access {
165 public:
166 temp_access();
167 void record_read(int line, prog_scope *scope, int swizzle);
168 void record_write(int line, prog_scope *scope, int writemask);
169 lifetime get_required_lifetime();
170 private:
171 void update_access_mask(int mask);
172
173 temp_comp_access comp[4];
174 int access_mask;
175 bool needs_component_tracking;
176 };
177
178 prog_scope_storage::prog_scope_storage(void *mc, int n):
179 mem_ctx(mc),
180 current_slot(0)
181 {
182 storage = ralloc_array(mem_ctx, prog_scope, n);
183 }
184
185 prog_scope_storage::~prog_scope_storage()
186 {
187 ralloc_free(storage);
188 }
189
190 prog_scope*
191 prog_scope_storage::create(prog_scope *p, prog_scope_type type, int id,
192 int lvl, int s_begin)
193 {
194 storage[current_slot] = prog_scope(p, type, id, lvl, s_begin);
195 return &storage[current_slot++];
196 }
197
198 prog_scope::prog_scope(prog_scope *parent, prog_scope_type type, int id,
199 int depth, int scope_begin):
200 scope_type(type),
201 scope_id(id),
202 scope_nesting_depth(depth),
203 scope_begin(scope_begin),
204 scope_end(-1),
205 break_loop_line(numeric_limits<int>::max()),
206 parent_scope(parent)
207 {
208 }
209
210 prog_scope_type prog_scope::type() const
211 {
212 return scope_type;
213 }
214
215 prog_scope *prog_scope::parent() const
216 {
217 return parent_scope;
218 }
219
220 int prog_scope::nesting_depth() const
221 {
222 return scope_nesting_depth;
223 }
224
225 bool prog_scope::is_loop() const
226 {
227 return (scope_type == loop_body);
228 }
229
230 bool prog_scope::is_in_loop() const
231 {
232 if (scope_type == loop_body)
233 return true;
234
235 if (parent_scope)
236 return parent_scope->is_in_loop();
237
238 return false;
239 }
240
241 const prog_scope *prog_scope::innermost_loop() const
242 {
243 if (scope_type == loop_body)
244 return this;
245
246 if (parent_scope)
247 return parent_scope->innermost_loop();
248
249 return nullptr;
250 }
251
252 const prog_scope *prog_scope::outermost_loop() const
253 {
254 const prog_scope *loop = nullptr;
255 const prog_scope *p = this;
256
257 do {
258 if (p->type() == loop_body)
259 loop = p;
260 p = p->parent();
261 } while (p);
262
263 return loop;
264 }
265
266 const prog_scope *prog_scope::enclosing_conditional() const
267 {
268 if (is_conditional())
269 return this;
270
271 if (parent_scope)
272 return parent_scope->enclosing_conditional();
273
274 return nullptr;
275 }
276
277 bool prog_scope::contains_range_of(const prog_scope& other) const
278 {
279 return (begin() <= other.begin()) && (end() >= other.end());
280 }
281
282 bool prog_scope::is_conditional() const
283 {
284 return scope_type == if_branch ||
285 scope_type == else_branch ||
286 scope_type == switch_case_branch ||
287 scope_type == switch_default_branch;
288 }
289
290 const prog_scope *prog_scope::in_ifelse_scope() const
291 {
292 if (scope_type == if_branch ||
293 scope_type == else_branch)
294 return this;
295
296 if (parent_scope)
297 return parent_scope->in_ifelse_scope();
298
299 return nullptr;
300 }
301
302 const prog_scope *prog_scope::in_switchcase_scope() const
303 {
304 if (scope_type == switch_case_branch ||
305 scope_type == switch_default_branch)
306 return this;
307
308 if (parent_scope)
309 return parent_scope->in_switchcase_scope();
310
311 return nullptr;
312 }
313
314 bool prog_scope::break_is_for_switchcase() const
315 {
316 if (scope_type == loop_body)
317 return false;
318
319 if (scope_type == switch_case_branch ||
320 scope_type == switch_default_branch ||
321 scope_type == switch_body)
322 return true;
323
324 if (parent_scope)
325 return parent_scope->break_is_for_switchcase();
326
327 return false;
328 }
329
330 int prog_scope::id() const
331 {
332 return scope_id;
333 }
334
335 int prog_scope::begin() const
336 {
337 return scope_begin;
338 }
339
340 int prog_scope::end() const
341 {
342 return scope_end;
343 }
344
345 void prog_scope::set_end(int end)
346 {
347 if (scope_end == -1)
348 scope_end = end;
349 }
350
351 void prog_scope::set_loop_break_line(int line)
352 {
353 if (scope_type == loop_body) {
354 break_loop_line = MIN2(break_loop_line, line);
355 } else {
356 if (parent_scope)
357 parent()->set_loop_break_line(line);
358 }
359 }
360
361 int prog_scope::loop_break_line() const
362 {
363 return break_loop_line;
364 }
365
366 temp_access::temp_access():
367 access_mask(0),
368 needs_component_tracking(false)
369 {
370 }
371
372 void temp_access::update_access_mask(int mask)
373 {
374 if (access_mask && access_mask != mask)
375 needs_component_tracking = true;
376 access_mask |= mask;
377 }
378
379 void temp_access::record_write(int line, prog_scope *scope, int writemask)
380 {
381 update_access_mask(writemask);
382
383 if (writemask & WRITEMASK_X)
384 comp[0].record_write(line, scope);
385 if (writemask & WRITEMASK_Y)
386 comp[1].record_write(line, scope);
387 if (writemask & WRITEMASK_Z)
388 comp[2].record_write(line, scope);
389 if (writemask & WRITEMASK_W)
390 comp[3].record_write(line, scope);
391 }
392
393 void temp_access::record_read(int line, prog_scope *scope, int swizzle)
394 {
395 int readmask = 0;
396 for (int idx = 0; idx < 4; ++idx) {
397 int swz = GET_SWZ(swizzle, idx);
398 readmask |= (1 << swz) & 0xF;
399 }
400 update_access_mask(readmask);
401
402 if (readmask & WRITEMASK_X)
403 comp[0].record_read(line, scope);
404 if (readmask & WRITEMASK_Y)
405 comp[1].record_read(line, scope);
406 if (readmask & WRITEMASK_Z)
407 comp[2].record_read(line, scope);
408 if (readmask & WRITEMASK_W)
409 comp[3].record_read(line, scope);
410 }
411
412 inline static lifetime make_lifetime(int b, int e)
413 {
414 lifetime lt;
415 lt.begin = b;
416 lt.end = e;
417 return lt;
418 }
419
420 lifetime temp_access::get_required_lifetime()
421 {
422 lifetime result = make_lifetime(-1, -1);
423
424 unsigned mask = access_mask;
425 while (mask) {
426 unsigned chan = u_bit_scan(&mask);
427 lifetime lt = comp[chan].get_required_lifetime();
428
429 if (lt.begin >= 0) {
430 if ((result.begin < 0) || (result.begin > lt.begin))
431 result.begin = lt.begin;
432 }
433
434 if (lt.end > result.end)
435 result.end = lt.end;
436
437 if (!needs_component_tracking)
438 break;
439 }
440 return result;
441 }
442
443 temp_comp_access::temp_comp_access():
444 last_read_scope(nullptr),
445 first_read_scope(nullptr),
446 first_write_scope(nullptr),
447 first_write(-1),
448 last_read(-1),
449 last_write(-1),
450 first_read(numeric_limits<int>::max())
451 {
452 }
453
454 void temp_comp_access::record_read(int line, prog_scope *scope)
455 {
456 last_read_scope = scope;
457 last_read = line;
458
459 if (first_read > line) {
460 first_read = line;
461 first_read_scope = scope;
462 }
463 }
464
465 void temp_comp_access::record_write(int line, prog_scope *scope)
466 {
467 last_write = line;
468
469 if (first_write < 0) {
470 first_write = line;
471 first_write_scope = scope;
472 }
473 }
474
475 void temp_comp_access::propagate_lifetime_to_dominant_write_scope()
476 {
477 first_write = first_write_scope->begin();
478 int lr = first_write_scope->end();
479
480 if (last_read < lr)
481 last_read = lr;
482 }
483
484 lifetime temp_comp_access::get_required_lifetime()
485 {
486 bool keep_for_full_loop = false;
487
488 /* This register component is not used at all, or only read,
489 * mark it as unused and ignore it when renaming.
490 * glsl_to_tgsi_visitor::renumber_registers will take care of
491 * eliminating registers that are not written to.
492 */
493 if (last_write < 0)
494 return make_lifetime(-1, -1);
495
496 assert(first_write_scope);
497
498 /* Only written to, just make sure the register component is not
499 * reused in the range it is used to write to
500 */
501 if (!last_read_scope)
502 return make_lifetime(first_write, last_write + 1);
503
504 const prog_scope *enclosing_scope_first_read = first_read_scope;
505 const prog_scope *enclosing_scope_first_write = first_write_scope;
506
507 /* We read before writing in a loop
508 * hence the value must survive the loops
509 */
510 if ((first_read <= first_write) &&
511 first_read_scope->is_in_loop()) {
512 keep_for_full_loop = true;
513 enclosing_scope_first_read = first_read_scope->outermost_loop();
514 }
515
516 /* A conditional write within a nested loop must survive
517 * the outermost loop, but only if it is read outside
518 * the condition scope where we write.
519 */
520 const prog_scope *conditional = enclosing_scope_first_write->enclosing_conditional();
521 if (conditional && conditional->is_in_loop() &&
522 !conditional->contains_range_of(*last_read_scope)) {
523 keep_for_full_loop = true;
524 enclosing_scope_first_write = conditional->outermost_loop();
525 }
526
527 /* Evaluate the scope that is shared by all: required first write scope,
528 * required first read before write scope, and last read scope.
529 */
530 const prog_scope *enclosing_scope = enclosing_scope_first_read;
531 if (enclosing_scope_first_write->contains_range_of(*enclosing_scope))
532 enclosing_scope = enclosing_scope_first_write;
533
534 if (last_read_scope->contains_range_of(*enclosing_scope))
535 enclosing_scope = last_read_scope;
536
537 while (!enclosing_scope->contains_range_of(*enclosing_scope_first_write) ||
538 !enclosing_scope->contains_range_of(*last_read_scope)) {
539 enclosing_scope = enclosing_scope->parent();
540 assert(enclosing_scope);
541 }
542
543 /* Propagate the last read scope to the target scope */
544 while (enclosing_scope->nesting_depth() < last_read_scope->nesting_depth()) {
545 /* If the read is in a loop and we have to move up the scope we need to
546 * extend the life time to the end of this current loop because at this
547 * point we don't know whether the component was written before
548 * un-conditionally in the same loop.
549 */
550 if (last_read_scope->is_loop())
551 last_read = last_read_scope->end();
552
553 last_read_scope = last_read_scope->parent();
554 }
555
556 /* If the variable has to be kept for the whole loop, and we
557 * are currently in a loop, then propagate the life time.
558 */
559 if (keep_for_full_loop && first_write_scope->is_loop())
560 propagate_lifetime_to_dominant_write_scope();
561
562 /* Propagate the first_dominant_write scope to the target scope */
563 while (enclosing_scope->nesting_depth() < first_write_scope->nesting_depth()) {
564 /* Propagate lifetime if there was a break in a loop and the write was
565 * after the break inside that loop. Note, that this is only needed if
566 * we move up in the scopes.
567 */
568 if (first_write_scope->loop_break_line() < first_write) {
569 keep_for_full_loop = true;
570 propagate_lifetime_to_dominant_write_scope();
571 }
572
573 first_write_scope = first_write_scope->parent();
574
575 /* Propagte lifetime if we are now in a loop */
576 if (keep_for_full_loop && first_write_scope->is_loop())
577 propagate_lifetime_to_dominant_write_scope();
578 }
579
580 /* The last write past the last read is dead code, but we have to
581 * ensure that the component is not reused too early, hence extend the
582 * lifetime past the last write.
583 */
584 if (last_write >= last_read)
585 last_read = last_write + 1;
586
587 /* Here we are at the same scope, all is resolved */
588 return make_lifetime(first_write, last_read);
589 }
590
591 /* Helper class for sorting and searching the registers based
592 * on life times. */
593 class access_record {
594 public:
595 int begin;
596 int end;
597 int reg;
598 bool erase;
599
600 bool operator < (const access_record& rhs) const {
601 return begin < rhs.begin;
602 }
603 };
604
605 }
606
607 #ifndef NDEBUG
608 /* Function used for debugging. */
609 static void dump_instruction(ostream& os, int line, prog_scope *scope,
610 const glsl_to_tgsi_instruction& inst);
611 #endif
612
613 /* Scan the program and estimate the required register life times.
614 * The array lifetimes must be pre-allocated
615 */
616 bool
617 get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
618 int ntemps, struct lifetime *lifetimes)
619 {
620 int line = 0;
621 int loop_id = 0;
622 int if_id = 0;
623 int switch_id = 0;
624 bool is_at_end = false;
625 bool ok = true;
626 int n_scopes = 1;
627
628 /* Count scopes to allocate the needed space without the need for
629 * re-allocation
630 */
631 foreach_in_list(glsl_to_tgsi_instruction, inst, instructions) {
632 if (inst->op == TGSI_OPCODE_BGNLOOP ||
633 inst->op == TGSI_OPCODE_SWITCH ||
634 inst->op == TGSI_OPCODE_CASE ||
635 inst->op == TGSI_OPCODE_IF ||
636 inst->op == TGSI_OPCODE_UIF ||
637 inst->op == TGSI_OPCODE_ELSE ||
638 inst->op == TGSI_OPCODE_DEFAULT)
639 ++n_scopes;
640 }
641
642 prog_scope_storage scopes(mem_ctx, n_scopes);
643 temp_access *acc = new temp_access[ntemps];
644
645 prog_scope *cur_scope = scopes.create(nullptr, outer_scope, 0, 0, line);
646
647 RENAME_DEBUG(debug_log << "========= Begin shader ============\n");
648
649 foreach_in_list(glsl_to_tgsi_instruction, inst, instructions) {
650 if (is_at_end) {
651 assert(!"GLSL_TO_TGSI: shader has instructions past end marker");
652 break;
653 }
654
655 RENAME_DEBUG(dump_instruction(debug_log, line, cur_scope, *inst));
656
657 switch (inst->op) {
658 case TGSI_OPCODE_BGNLOOP: {
659 cur_scope = scopes.create(cur_scope, loop_body, loop_id++,
660 cur_scope->nesting_depth() + 1, line);
661 break;
662 }
663 case TGSI_OPCODE_ENDLOOP: {
664 cur_scope->set_end(line);
665 cur_scope = cur_scope->parent();
666 assert(cur_scope);
667 break;
668 }
669 case TGSI_OPCODE_IF:
670 case TGSI_OPCODE_UIF: {
671 assert(num_inst_src_regs(inst) == 1);
672 const st_src_reg& src = inst->src[0];
673 if (src.file == PROGRAM_TEMPORARY)
674 acc[src.index].record_read(line, cur_scope, src.swizzle);
675 cur_scope = scopes.create(cur_scope, if_branch, if_id++,
676 cur_scope->nesting_depth() + 1, line + 1);
677 break;
678 }
679 case TGSI_OPCODE_ELSE: {
680 assert(cur_scope->type() == if_branch);
681 cur_scope->set_end(line - 1);
682 cur_scope = scopes.create(cur_scope->parent(), else_branch,
683 cur_scope->id(), cur_scope->nesting_depth(),
684 line + 1);
685 break;
686 }
687 case TGSI_OPCODE_END: {
688 cur_scope->set_end(line);
689 is_at_end = true;
690 break;
691 }
692 case TGSI_OPCODE_ENDIF: {
693 cur_scope->set_end(line - 1);
694 cur_scope = cur_scope->parent();
695 assert(cur_scope);
696 break;
697 }
698 case TGSI_OPCODE_SWITCH: {
699 assert(num_inst_src_regs(inst) == 1);
700 const st_src_reg& src = inst->src[0];
701 prog_scope *scope = scopes.create(cur_scope, switch_body, switch_id++,
702 cur_scope->nesting_depth() + 1, line);
703 /* We record the read only for the SWITCH statement itself, like it
704 * is used by the only consumer of TGSI_OPCODE_SWITCH in tgsi_exec.c.
705 */
706 if (src.file == PROGRAM_TEMPORARY)
707 acc[src.index].record_read(line, cur_scope, src.swizzle);
708 cur_scope = scope;
709 break;
710 }
711 case TGSI_OPCODE_ENDSWITCH: {
712 cur_scope->set_end(line - 1);
713 /* Remove the case level, it might not have been
714 * closed with a break.
715 */
716 if (cur_scope->type() != switch_body)
717 cur_scope = cur_scope->parent();
718
719 cur_scope = cur_scope->parent();
720 assert(cur_scope);
721 break;
722 }
723 case TGSI_OPCODE_CASE: {
724 /* Take care of tracking the registers. */
725 prog_scope *switch_scope = cur_scope->type() == switch_body ?
726 cur_scope : cur_scope->parent();
727
728 assert(num_inst_src_regs(inst) == 1);
729 const st_src_reg& src = inst->src[0];
730 if (src.file == PROGRAM_TEMPORARY)
731 acc[src.index].record_read(line, switch_scope, src.swizzle);
732
733 /* Fall through to allocate the scope. */
734 }
735 case TGSI_OPCODE_DEFAULT: {
736 prog_scope_type t = inst->op == TGSI_OPCODE_CASE ? switch_case_branch
737 : switch_default_branch;
738 prog_scope *switch_scope = (cur_scope->type() == switch_body) ?
739 cur_scope : cur_scope->parent();
740 assert(switch_scope->type() == switch_body);
741 prog_scope *scope = scopes.create(switch_scope, t,
742 switch_scope->id(),
743 switch_scope->nesting_depth() + 1,
744 line);
745 /* Previous case falls through, so scope was not yet closed. */
746 if ((cur_scope != switch_scope) && (cur_scope->end() == -1))
747 cur_scope->set_end(line - 1);
748 cur_scope = scope;
749 break;
750 }
751 case TGSI_OPCODE_BRK: {
752 if (cur_scope->break_is_for_switchcase()) {
753 cur_scope->set_end(line - 1);
754 } else {
755 cur_scope->set_loop_break_line(line);
756 }
757 break;
758 }
759 case TGSI_OPCODE_CAL:
760 case TGSI_OPCODE_RET:
761 /* These opcodes are not supported and if a subroutine would
762 * be called in a shader, then the lifetime tracking would have
763 * to follow that call to see which registers are used there.
764 * Since this is not done, we have to bail out here and signal
765 * that no register merge will take place.
766 */
767 ok = false;
768 goto out;
769 default: {
770 for (unsigned j = 0; j < num_inst_src_regs(inst); j++) {
771 const st_src_reg& src = inst->src[j];
772 if (src.file == PROGRAM_TEMPORARY)
773 acc[src.index].record_read(line, cur_scope, src.swizzle);
774 }
775 for (unsigned j = 0; j < inst->tex_offset_num_offset; j++) {
776 const st_src_reg& src = inst->tex_offsets[j];
777 if (src.file == PROGRAM_TEMPORARY)
778 acc[src.index].record_read(line, cur_scope, src.swizzle);
779 }
780 for (unsigned j = 0; j < num_inst_dst_regs(inst); j++) {
781 const st_dst_reg& dst = inst->dst[j];
782 if (dst.file == PROGRAM_TEMPORARY)
783 acc[dst.index].record_write(line, cur_scope, dst.writemask);
784 }
785 }
786 }
787 ++line;
788 }
789
790 RENAME_DEBUG(debug_log << "==================================\n\n");
791
792 /* Make sure last scope is closed, even though no
793 * TGSI_OPCODE_END was given.
794 */
795 if (cur_scope->end() < 0)
796 cur_scope->set_end(line - 1);
797
798 RENAME_DEBUG(debug_log << "========= lifetimes ==============\n");
799 for(int i = 0; i < ntemps; ++i) {
800 RENAME_DEBUG(debug_log << setw(4) << i);
801 lifetimes[i] = acc[i].get_required_lifetime();
802 RENAME_DEBUG(debug_log << ": [" << lifetimes[i].begin << ", "
803 << lifetimes[i].end << "]\n");
804 }
805 RENAME_DEBUG(debug_log << "==================================\n\n");
806
807 out:
808 delete[] acc;
809 return ok;
810 }
811
812 /* Find the next register between [start, end) that has a life time starting
813 * at or after bound by using a binary search.
814 * start points at the beginning of the search range,
815 * end points at the element past the end of the search range, and
816 * the array comprising [start, end) must be sorted in ascending order.
817 */
818 static access_record*
819 find_next_rename(access_record* start, access_record* end, int bound)
820 {
821 int delta = (end - start);
822
823 while (delta > 0) {
824 int half = delta >> 1;
825 access_record* middle = start + half;
826
827 if (bound <= middle->begin) {
828 delta = half;
829 } else {
830 start = middle;
831 ++start;
832 delta -= half + 1;
833 }
834 }
835
836 return start;
837 }
838
839 #ifndef USE_STL_SORT
840 static int access_record_compare (const void *a, const void *b) {
841 const access_record *aa = static_cast<const access_record*>(a);
842 const access_record *bb = static_cast<const access_record*>(b);
843 return aa->begin < bb->begin ? -1 : (aa->begin > bb->begin ? 1 : 0);
844 }
845 #endif
846
847 /* This functions evaluates the register merges by using a binary
848 * search to find suitable merge candidates. */
849 void get_temp_registers_remapping(void *mem_ctx, int ntemps,
850 const struct lifetime* lifetimes,
851 struct rename_reg_pair *result)
852 {
853 access_record *reg_access = ralloc_array(mem_ctx, access_record, ntemps);
854
855 int used_temps = 0;
856 for (int i = 0; i < ntemps; ++i) {
857 if (lifetimes[i].begin >= 0) {
858 reg_access[used_temps].begin = lifetimes[i].begin;
859 reg_access[used_temps].end = lifetimes[i].end;
860 reg_access[used_temps].reg = i;
861 reg_access[used_temps].erase = false;
862 ++used_temps;
863 }
864 }
865
866 #ifdef USE_STL_SORT
867 std::sort(reg_access, reg_access + used_temps);
868 #else
869 std::qsort(reg_access, used_temps, sizeof(access_record), access_record_compare);
870 #endif
871
872 access_record *trgt = reg_access;
873 access_record *reg_access_end = reg_access + used_temps;
874 access_record *first_erase = reg_access_end;
875 access_record *search_start = trgt + 1;
876
877 while (trgt != reg_access_end) {
878 access_record *src = find_next_rename(search_start, reg_access_end,
879 trgt->end);
880 if (src != reg_access_end) {
881 result[src->reg].new_reg = trgt->reg;
882 result[src->reg].valid = true;
883 trgt->end = src->end;
884
885 /* Since we only search forward, don't remove the renamed
886 * register just now, only mark it. */
887 src->erase = true;
888
889 if (first_erase == reg_access_end)
890 first_erase = src;
891
892 search_start = src + 1;
893 } else {
894 /* Moving to the next target register it is time to remove
895 * the already merged registers from the search range */
896 if (first_erase != reg_access_end) {
897 access_record *outp = first_erase;
898 access_record *inp = first_erase + 1;
899
900 while (inp != reg_access_end) {
901 if (!inp->erase)
902 *outp++ = *inp;
903 ++inp;
904 }
905
906 reg_access_end = outp;
907 first_erase = reg_access_end;
908 }
909 ++trgt;
910 search_start = trgt + 1;
911 }
912 }
913 ralloc_free(reg_access);
914 }
915
916 /* Code below used for debugging */
917 #ifndef NDEBUG
918 static
919 void dump_instruction(ostream& os, int line, prog_scope *scope,
920 const glsl_to_tgsi_instruction& inst)
921 {
922 const struct tgsi_opcode_info *info = inst.info;
923 int indent = scope->nesting_depth();
924 if ((scope->type() == switch_case_branch ||
925 scope->type() == switch_default_branch) &&
926 (info->opcode == TGSI_OPCODE_CASE ||
927 info->opcode == TGSI_OPCODE_DEFAULT))
928 --indent;
929
930 if (info->opcode == TGSI_OPCODE_ENDIF ||
931 info->opcode == TGSI_OPCODE_ELSE ||
932 info->opcode == TGSI_OPCODE_ENDLOOP ||
933 info->opcode == TGSI_OPCODE_ENDSWITCH)
934 --indent;
935
936 os << setw(4) << line << ": ";
937 os << setw(indent * 4) << " ";
938 os << inst << "\n";
939 }
940 #endif