mesa/st/glsl_to_tgsi: Add tracking of ifelse writes in register merging
[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_else_scope() const;
107 const prog_scope *in_ifelse_scope() const;
108 const prog_scope *in_parent_ifelse_scope() const;
109 const prog_scope *innermost_loop() const;
110 const prog_scope *outermost_loop() const;
111 const prog_scope *enclosing_conditional() const;
112
113 bool is_loop() const;
114 bool is_in_loop() const;
115 bool is_switchcase_scope_in_loop() const;
116 bool is_conditional() const;
117 bool is_child_of(const prog_scope *scope) const;
118 bool is_child_of_ifelse_id_sibling(const prog_scope *scope) const;
119
120 bool break_is_for_switchcase() const;
121 bool contains_range_of(const prog_scope& other) const;
122
123 void set_end(int end);
124 void set_loop_break_line(int line);
125
126 private:
127 prog_scope_type scope_type;
128 int scope_id;
129 int scope_nesting_depth;
130 int scope_begin;
131 int scope_end;
132 int break_loop_line;
133 prog_scope *parent_scope;
134 };
135
136 /* Some storage class to encapsulate the prog_scope (de-)allocations */
137 class prog_scope_storage {
138 public:
139 prog_scope_storage(void *mem_ctx, int n);
140 ~prog_scope_storage();
141 prog_scope * create(prog_scope *p, prog_scope_type type, int id,
142 int lvl, int s_begin);
143 private:
144 void *mem_ctx;
145 int current_slot;
146 prog_scope *storage;
147 };
148
149 /* Class to track the access to a component of a temporary register. */
150
151 class temp_comp_access {
152 public:
153 temp_comp_access();
154
155 void record_read(int line, prog_scope *scope);
156 void record_write(int line, prog_scope *scope);
157 lifetime get_required_lifetime();
158 private:
159 void propagate_lifetime_to_dominant_write_scope();
160 bool conditional_ifelse_write_in_loop() const;
161
162 void record_ifelse_write(const prog_scope& scope);
163 void record_if_write(const prog_scope& scope);
164 void record_else_write(const prog_scope& scope);
165
166 prog_scope *last_read_scope;
167 prog_scope *first_read_scope;
168 prog_scope *first_write_scope;
169
170 int first_write;
171 int last_read;
172 int last_write;
173 int first_read;
174
175 /* This member variable tracks the current resolution of conditional writing
176 * to this temporary in IF/ELSE clauses.
177 *
178 * The initial value "conditionality_untouched" indicates that this
179 * temporary has not yet been written to within an if clause.
180 *
181 * A positive (other than "conditionality_untouched") number refers to the
182 * last loop id for which the write was resolved as unconditional. With each
183 * new loop this value will be overwitten by "conditionality_unresolved"
184 * on entering the first IF clause writing this temporary.
185 *
186 * The value "conditionality_unresolved" indicates that no resolution has
187 * been achieved so far. If the variable is set to this value at the end of
188 * the processing of the whole shader it also indicates a conditional write.
189 *
190 * The value "write_is_conditional" marks that the variable is written
191 * conditionally (i.e. not in all relevant IF/ELSE code path pairs) in at
192 * least one loop.
193 */
194 int conditionality_in_loop_id;
195
196 /* Helper constants to make the tracking code more readable. */
197 static const int write_is_conditional = -1;
198 static const int conditionality_unresolved = 0;
199 static const int conditionality_untouched;
200
201 /* A bit field tracking the nexting levels of if-else clauses where the
202 * temporary has (so far) been written to in the if branch, but not in the
203 * else branch.
204 */
205 unsigned int if_scope_write_flags;
206
207 int next_ifelse_nesting_depth;
208 static const int supported_ifelse_nesting_depth = 32;
209
210 /* Tracks the last if scope in which the temporary was written to
211 * without a write in the correspondig else branch. Is also used
212 * to track read-before-write in the according scope.
213 */
214 const prog_scope *current_unpaired_if_write_scope;
215
216 /* Flag to resolve read-before-write in the else scope. */
217 bool was_written_in_current_else_scope;
218 };
219
220 const int
221 temp_comp_access::conditionality_untouched = numeric_limits<int>::max();
222
223 /* Class to track the access to all components of a temporary register. */
224 class temp_access {
225 public:
226 temp_access();
227 void record_read(int line, prog_scope *scope, int swizzle);
228 void record_write(int line, prog_scope *scope, int writemask);
229 lifetime get_required_lifetime();
230 private:
231 void update_access_mask(int mask);
232
233 temp_comp_access comp[4];
234 int access_mask;
235 bool needs_component_tracking;
236 };
237
238 prog_scope_storage::prog_scope_storage(void *mc, int n):
239 mem_ctx(mc),
240 current_slot(0)
241 {
242 storage = ralloc_array(mem_ctx, prog_scope, n);
243 }
244
245 prog_scope_storage::~prog_scope_storage()
246 {
247 ralloc_free(storage);
248 }
249
250 prog_scope*
251 prog_scope_storage::create(prog_scope *p, prog_scope_type type, int id,
252 int lvl, int s_begin)
253 {
254 storage[current_slot] = prog_scope(p, type, id, lvl, s_begin);
255 return &storage[current_slot++];
256 }
257
258 prog_scope::prog_scope(prog_scope *parent, prog_scope_type type, int id,
259 int depth, int scope_begin):
260 scope_type(type),
261 scope_id(id),
262 scope_nesting_depth(depth),
263 scope_begin(scope_begin),
264 scope_end(-1),
265 break_loop_line(numeric_limits<int>::max()),
266 parent_scope(parent)
267 {
268 }
269
270 prog_scope_type prog_scope::type() const
271 {
272 return scope_type;
273 }
274
275 prog_scope *prog_scope::parent() const
276 {
277 return parent_scope;
278 }
279
280 int prog_scope::nesting_depth() const
281 {
282 return scope_nesting_depth;
283 }
284
285 bool prog_scope::is_loop() const
286 {
287 return (scope_type == loop_body);
288 }
289
290 bool prog_scope::is_in_loop() const
291 {
292 if (scope_type == loop_body)
293 return true;
294
295 if (parent_scope)
296 return parent_scope->is_in_loop();
297
298 return false;
299 }
300
301 const prog_scope *prog_scope::innermost_loop() const
302 {
303 if (scope_type == loop_body)
304 return this;
305
306 if (parent_scope)
307 return parent_scope->innermost_loop();
308
309 return nullptr;
310 }
311
312 const prog_scope *prog_scope::outermost_loop() const
313 {
314 const prog_scope *loop = nullptr;
315 const prog_scope *p = this;
316
317 do {
318 if (p->type() == loop_body)
319 loop = p;
320 p = p->parent();
321 } while (p);
322
323 return loop;
324 }
325
326 bool prog_scope::is_child_of_ifelse_id_sibling(const prog_scope *scope) const
327 {
328 const prog_scope *my_parent = in_parent_ifelse_scope();
329 while (my_parent) {
330 /* is a direct child? */
331 if (my_parent == scope)
332 return false;
333 /* is a child of the conditions sibling? */
334 if (my_parent->id() == scope->id())
335 return true;
336 my_parent = my_parent->in_parent_ifelse_scope();
337 }
338 return false;
339 }
340
341 bool prog_scope::is_child_of(const prog_scope *scope) const
342 {
343 const prog_scope *my_parent = parent();
344 while (my_parent) {
345 if (my_parent == scope)
346 return true;
347 my_parent = my_parent->parent();
348 }
349 return false;
350 }
351
352 const prog_scope *prog_scope::enclosing_conditional() const
353 {
354 if (is_conditional())
355 return this;
356
357 if (parent_scope)
358 return parent_scope->enclosing_conditional();
359
360 return nullptr;
361 }
362
363 bool prog_scope::contains_range_of(const prog_scope& other) const
364 {
365 return (begin() <= other.begin()) && (end() >= other.end());
366 }
367
368 bool prog_scope::is_conditional() const
369 {
370 return scope_type == if_branch ||
371 scope_type == else_branch ||
372 scope_type == switch_case_branch ||
373 scope_type == switch_default_branch;
374 }
375
376 const prog_scope *prog_scope::in_else_scope() const
377 {
378 if (scope_type == else_branch)
379 return this;
380
381 if (parent_scope)
382 return parent_scope->in_else_scope();
383
384 return nullptr;
385 }
386
387 const prog_scope *prog_scope::in_parent_ifelse_scope() const
388 {
389 if (parent_scope)
390 return parent_scope->in_ifelse_scope();
391 else
392 return nullptr;
393 }
394
395 const prog_scope *prog_scope::in_ifelse_scope() const
396 {
397 if (scope_type == if_branch ||
398 scope_type == else_branch)
399 return this;
400
401 if (parent_scope)
402 return parent_scope->in_ifelse_scope();
403
404 return nullptr;
405 }
406
407 bool prog_scope::is_switchcase_scope_in_loop() const
408 {
409 return (scope_type == switch_case_branch ||
410 scope_type == switch_default_branch) &&
411 is_in_loop();
412 }
413
414 bool prog_scope::break_is_for_switchcase() const
415 {
416 if (scope_type == loop_body)
417 return false;
418
419 if (scope_type == switch_case_branch ||
420 scope_type == switch_default_branch ||
421 scope_type == switch_body)
422 return true;
423
424 if (parent_scope)
425 return parent_scope->break_is_for_switchcase();
426
427 return false;
428 }
429
430 int prog_scope::id() const
431 {
432 return scope_id;
433 }
434
435 int prog_scope::begin() const
436 {
437 return scope_begin;
438 }
439
440 int prog_scope::end() const
441 {
442 return scope_end;
443 }
444
445 void prog_scope::set_end(int end)
446 {
447 if (scope_end == -1)
448 scope_end = end;
449 }
450
451 void prog_scope::set_loop_break_line(int line)
452 {
453 if (scope_type == loop_body) {
454 break_loop_line = MIN2(break_loop_line, line);
455 } else {
456 if (parent_scope)
457 parent()->set_loop_break_line(line);
458 }
459 }
460
461 int prog_scope::loop_break_line() const
462 {
463 return break_loop_line;
464 }
465
466 temp_access::temp_access():
467 access_mask(0),
468 needs_component_tracking(false)
469 {
470 }
471
472 void temp_access::update_access_mask(int mask)
473 {
474 if (access_mask && access_mask != mask)
475 needs_component_tracking = true;
476 access_mask |= mask;
477 }
478
479 void temp_access::record_write(int line, prog_scope *scope, int writemask)
480 {
481 update_access_mask(writemask);
482
483 if (writemask & WRITEMASK_X)
484 comp[0].record_write(line, scope);
485 if (writemask & WRITEMASK_Y)
486 comp[1].record_write(line, scope);
487 if (writemask & WRITEMASK_Z)
488 comp[2].record_write(line, scope);
489 if (writemask & WRITEMASK_W)
490 comp[3].record_write(line, scope);
491 }
492
493 void temp_access::record_read(int line, prog_scope *scope, int swizzle)
494 {
495 int readmask = 0;
496 for (int idx = 0; idx < 4; ++idx) {
497 int swz = GET_SWZ(swizzle, idx);
498 readmask |= (1 << swz) & 0xF;
499 }
500 update_access_mask(readmask);
501
502 if (readmask & WRITEMASK_X)
503 comp[0].record_read(line, scope);
504 if (readmask & WRITEMASK_Y)
505 comp[1].record_read(line, scope);
506 if (readmask & WRITEMASK_Z)
507 comp[2].record_read(line, scope);
508 if (readmask & WRITEMASK_W)
509 comp[3].record_read(line, scope);
510 }
511
512 inline static lifetime make_lifetime(int b, int e)
513 {
514 lifetime lt;
515 lt.begin = b;
516 lt.end = e;
517 return lt;
518 }
519
520 lifetime temp_access::get_required_lifetime()
521 {
522 lifetime result = make_lifetime(-1, -1);
523
524 unsigned mask = access_mask;
525 while (mask) {
526 unsigned chan = u_bit_scan(&mask);
527 lifetime lt = comp[chan].get_required_lifetime();
528
529 if (lt.begin >= 0) {
530 if ((result.begin < 0) || (result.begin > lt.begin))
531 result.begin = lt.begin;
532 }
533
534 if (lt.end > result.end)
535 result.end = lt.end;
536
537 if (!needs_component_tracking)
538 break;
539 }
540 return result;
541 }
542
543 temp_comp_access::temp_comp_access():
544 last_read_scope(nullptr),
545 first_read_scope(nullptr),
546 first_write_scope(nullptr),
547 first_write(-1),
548 last_read(-1),
549 last_write(-1),
550 first_read(numeric_limits<int>::max()),
551 conditionality_in_loop_id(conditionality_untouched),
552 if_scope_write_flags(0),
553 next_ifelse_nesting_depth(0),
554 current_unpaired_if_write_scope(nullptr),
555 was_written_in_current_else_scope(false)
556 {
557 }
558
559 void temp_comp_access::record_read(int line, prog_scope *scope)
560 {
561 last_read_scope = scope;
562 last_read = line;
563
564 if (first_read > line) {
565 first_read = line;
566 first_read_scope = scope;
567 }
568
569 /* Check whether we are in a condition within a loop */
570 const prog_scope *ifelse_scope = scope->in_ifelse_scope();
571 const prog_scope *enclosing_loop;
572 if (ifelse_scope && (enclosing_loop = ifelse_scope->innermost_loop())) {
573
574 /* If we have either not yet written to this register nor writes are
575 * resolved as unconditional in the enclosing loop then check whether
576 * we read before write in an IF/ELSE branch.
577 */
578 if ((conditionality_in_loop_id != write_is_conditional) &&
579 (conditionality_in_loop_id != enclosing_loop->id())) {
580
581 if (current_unpaired_if_write_scope) {
582
583 /* Has been written in this or a parent scope? - this makes the temporary
584 * unconditionally set at this point.
585 */
586 if (scope->is_child_of(current_unpaired_if_write_scope))
587 return;
588
589 /* Has been written in the same scope before it was read? */
590 if (ifelse_scope->type() == if_branch) {
591 if (current_unpaired_if_write_scope->id() == scope->id())
592 return;
593 } else {
594 if (was_written_in_current_else_scope)
595 return;
596 }
597 }
598
599 /* The temporary was read (conditionally) before it is written, hence
600 * it should survive a loop. This can be signaled like if it were
601 * conditionally written.
602 */
603 conditionality_in_loop_id = write_is_conditional;
604 }
605 }
606 }
607
608 void temp_comp_access::record_write(int line, prog_scope *scope)
609 {
610 last_write = line;
611
612 if (first_write < 0) {
613 first_write = line;
614 first_write_scope = scope;
615 }
616
617 if (conditionality_in_loop_id == write_is_conditional)
618 return;
619
620 /* If the nesting depth is larger than the supported level,
621 * then we assume conditional writes.
622 */
623 if (next_ifelse_nesting_depth >= supported_ifelse_nesting_depth) {
624 conditionality_in_loop_id = write_is_conditional;
625 return;
626 }
627
628 /* If we are in an IF/ELSE scope within a loop and the loop has not
629 * been resolved already, then record this write.
630 */
631 const prog_scope *ifelse_scope = scope->in_ifelse_scope();
632 if (ifelse_scope && ifelse_scope->innermost_loop() &&
633 ifelse_scope->innermost_loop()->id() != conditionality_in_loop_id)
634 record_ifelse_write(*ifelse_scope);
635 }
636
637 void temp_comp_access::record_ifelse_write(const prog_scope& scope)
638 {
639 if (scope.type() == if_branch) {
640 /* The first write in an IF branch within a loop implies unresolved
641 * conditionality (if it was untouched or unconditional before).
642 */
643 conditionality_in_loop_id = conditionality_unresolved;
644 was_written_in_current_else_scope = false;
645 record_if_write(scope);
646 } else {
647 was_written_in_current_else_scope = true;
648 record_else_write(scope);
649 }
650 }
651
652 void temp_comp_access::record_if_write(const prog_scope& scope)
653 {
654 /* Don't record write if this IF scope if it ...
655 * - is not the first write in this IF scope,
656 * - has already been written in a parent IF scope.
657 * In both cases this write is a secondary write that doesn't contribute
658 * to resolve conditionality.
659 *
660 * Record the write if it
661 * - is the first one (obviously),
662 * - happens in an IF branch that is a child of the ELSE branch of the
663 * last active IF/ELSE pair. In this case recording this write is used to
664 * established whether the write is (un-)conditional in the scope enclosing
665 * this outer IF/ELSE pair.
666 */
667 if (!current_unpaired_if_write_scope ||
668 (current_unpaired_if_write_scope->id() != scope.id() &&
669 scope.is_child_of_ifelse_id_sibling(current_unpaired_if_write_scope))) {
670 if_scope_write_flags |= 1 << next_ifelse_nesting_depth;
671 current_unpaired_if_write_scope = &scope;
672 next_ifelse_nesting_depth++;
673 }
674 }
675
676 void temp_comp_access::record_else_write(const prog_scope& scope)
677 {
678 int mask = 1 << (next_ifelse_nesting_depth - 1);
679
680 /* If the temporary was written in an IF branch on the same scope level
681 * and this branch is the sibling of this ELSE branch, then we have a
682 * pair of writes that makes write access to this temporary unconditional
683 * in the enclosing scope.
684 */
685
686 if ((if_scope_write_flags & mask) &&
687 (scope.id() == current_unpaired_if_write_scope->id())) {
688 --next_ifelse_nesting_depth;
689 if_scope_write_flags &= ~mask;
690
691 /* The following code deals with propagating unconditionality from
692 * inner levels of nested IF/ELSE to the outer levels like in
693 *
694 * 1: var t;
695 * 2: if (a) { <- start scope A
696 * 3: if (b)
697 * 4: t = ...
698 * 5: else
699 * 6: t = ...
700 * 7: } else { <- start scope B
701 * 8: if (c)
702 * 9: t = ...
703 * A: else <- start scope C
704 * B: t = ...
705 * C: }
706 *
707 */
708
709 const prog_scope *parent_ifelse = scope.parent()->in_ifelse_scope();
710
711 if (1 << (next_ifelse_nesting_depth - 1) & if_scope_write_flags) {
712 /* We are at the end of scope C and already recorded a write
713 * within an IF scope (A), the sibling of the parent ELSE scope B,
714 * and it is not yet resolved. Mark that as the last relevant
715 * IF scope. Below the write will be resolved for the A/B
716 * scope pair.
717 */
718 current_unpaired_if_write_scope = parent_ifelse;
719 } else {
720 current_unpaired_if_write_scope = nullptr;
721 }
722
723 /* If some parent is IF/ELSE and in a loop then propagate the
724 * write to that scope. Otherwise the write is unconditional
725 * because it happens in both corresponding IF/ELSE branches
726 * in this loop, and hence, record the loop id to signal the
727 * resolution.
728 */
729 if (parent_ifelse && parent_ifelse->is_in_loop()) {
730 record_ifelse_write(*parent_ifelse);
731 } else {
732 conditionality_in_loop_id = scope.innermost_loop()->id();
733 }
734 } else {
735 /* The temporary was not written in the IF branch corresponding
736 * to this ELSE branch, hence the write is conditional.
737 */
738 conditionality_in_loop_id = write_is_conditional;
739 }
740 }
741
742 bool temp_comp_access::conditional_ifelse_write_in_loop() const
743 {
744 return conditionality_in_loop_id <= conditionality_unresolved;
745 }
746
747 void temp_comp_access::propagate_lifetime_to_dominant_write_scope()
748 {
749 first_write = first_write_scope->begin();
750 int lr = first_write_scope->end();
751
752 if (last_read < lr)
753 last_read = lr;
754 }
755
756 lifetime temp_comp_access::get_required_lifetime()
757 {
758 bool keep_for_full_loop = false;
759
760 /* This register component is not used at all, or only read,
761 * mark it as unused and ignore it when renaming.
762 * glsl_to_tgsi_visitor::renumber_registers will take care of
763 * eliminating registers that are not written to.
764 */
765 if (last_write < 0)
766 return make_lifetime(-1, -1);
767
768 assert(first_write_scope);
769
770 /* Only written to, just make sure the register component is not
771 * reused in the range it is used to write to
772 */
773 if (!last_read_scope)
774 return make_lifetime(first_write, last_write + 1);
775
776 const prog_scope *enclosing_scope_first_read = first_read_scope;
777 const prog_scope *enclosing_scope_first_write = first_write_scope;
778
779 /* We read before writing in a loop
780 * hence the value must survive the loops
781 */
782 if ((first_read <= first_write) &&
783 first_read_scope->is_in_loop()) {
784 keep_for_full_loop = true;
785 enclosing_scope_first_read = first_read_scope->outermost_loop();
786 }
787
788 /* A conditional write within a (nested) loop must survive the outermost
789 * loop if the last read was not within the same scope.
790 */
791 const prog_scope *conditional = enclosing_scope_first_write->enclosing_conditional();
792 if (conditional && !conditional->contains_range_of(*last_read_scope) &&
793 (conditional->is_switchcase_scope_in_loop() ||
794 conditional_ifelse_write_in_loop())) {
795 keep_for_full_loop = true;
796 enclosing_scope_first_write = conditional->outermost_loop();
797 }
798
799 /* Evaluate the scope that is shared by all: required first write scope,
800 * required first read before write scope, and last read scope.
801 */
802 const prog_scope *enclosing_scope = enclosing_scope_first_read;
803 if (enclosing_scope_first_write->contains_range_of(*enclosing_scope))
804 enclosing_scope = enclosing_scope_first_write;
805
806 if (last_read_scope->contains_range_of(*enclosing_scope))
807 enclosing_scope = last_read_scope;
808
809 while (!enclosing_scope->contains_range_of(*enclosing_scope_first_write) ||
810 !enclosing_scope->contains_range_of(*last_read_scope)) {
811 enclosing_scope = enclosing_scope->parent();
812 assert(enclosing_scope);
813 }
814
815 /* Propagate the last read scope to the target scope */
816 while (enclosing_scope->nesting_depth() < last_read_scope->nesting_depth()) {
817 /* If the read is in a loop and we have to move up the scope we need to
818 * extend the life time to the end of this current loop because at this
819 * point we don't know whether the component was written before
820 * un-conditionally in the same loop.
821 */
822 if (last_read_scope->is_loop())
823 last_read = last_read_scope->end();
824
825 last_read_scope = last_read_scope->parent();
826 }
827
828 /* If the variable has to be kept for the whole loop, and we
829 * are currently in a loop, then propagate the life time.
830 */
831 if (keep_for_full_loop && first_write_scope->is_loop())
832 propagate_lifetime_to_dominant_write_scope();
833
834 /* Propagate the first_dominant_write scope to the target scope */
835 while (enclosing_scope->nesting_depth() < first_write_scope->nesting_depth()) {
836 /* Propagate lifetime if there was a break in a loop and the write was
837 * after the break inside that loop. Note, that this is only needed if
838 * we move up in the scopes.
839 */
840 if (first_write_scope->loop_break_line() < first_write) {
841 keep_for_full_loop = true;
842 propagate_lifetime_to_dominant_write_scope();
843 }
844
845 first_write_scope = first_write_scope->parent();
846
847 /* Propagte lifetime if we are now in a loop */
848 if (keep_for_full_loop && first_write_scope->is_loop())
849 propagate_lifetime_to_dominant_write_scope();
850 }
851
852 /* The last write past the last read is dead code, but we have to
853 * ensure that the component is not reused too early, hence extend the
854 * lifetime past the last write.
855 */
856 if (last_write >= last_read)
857 last_read = last_write + 1;
858
859 /* Here we are at the same scope, all is resolved */
860 return make_lifetime(first_write, last_read);
861 }
862
863 /* Helper class for sorting and searching the registers based
864 * on life times. */
865 class access_record {
866 public:
867 int begin;
868 int end;
869 int reg;
870 bool erase;
871
872 bool operator < (const access_record& rhs) const {
873 return begin < rhs.begin;
874 }
875 };
876
877 }
878
879 #ifndef NDEBUG
880 /* Function used for debugging. */
881 static void dump_instruction(ostream& os, int line, prog_scope *scope,
882 const glsl_to_tgsi_instruction& inst);
883 #endif
884
885 /* Scan the program and estimate the required register life times.
886 * The array lifetimes must be pre-allocated
887 */
888 bool
889 get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
890 int ntemps, struct lifetime *lifetimes)
891 {
892 int line = 0;
893 int loop_id = 1;
894 int if_id = 1;
895 int switch_id = 0;
896 bool is_at_end = false;
897 bool ok = true;
898 int n_scopes = 1;
899
900 /* Count scopes to allocate the needed space without the need for
901 * re-allocation
902 */
903 foreach_in_list(glsl_to_tgsi_instruction, inst, instructions) {
904 if (inst->op == TGSI_OPCODE_BGNLOOP ||
905 inst->op == TGSI_OPCODE_SWITCH ||
906 inst->op == TGSI_OPCODE_CASE ||
907 inst->op == TGSI_OPCODE_IF ||
908 inst->op == TGSI_OPCODE_UIF ||
909 inst->op == TGSI_OPCODE_ELSE ||
910 inst->op == TGSI_OPCODE_DEFAULT)
911 ++n_scopes;
912 }
913
914 prog_scope_storage scopes(mem_ctx, n_scopes);
915 temp_access *acc = new temp_access[ntemps];
916
917 prog_scope *cur_scope = scopes.create(nullptr, outer_scope, 0, 0, line);
918
919 RENAME_DEBUG(debug_log << "========= Begin shader ============\n");
920
921 foreach_in_list(glsl_to_tgsi_instruction, inst, instructions) {
922 if (is_at_end) {
923 assert(!"GLSL_TO_TGSI: shader has instructions past end marker");
924 break;
925 }
926
927 RENAME_DEBUG(dump_instruction(debug_log, line, cur_scope, *inst));
928
929 switch (inst->op) {
930 case TGSI_OPCODE_BGNLOOP: {
931 cur_scope = scopes.create(cur_scope, loop_body, loop_id++,
932 cur_scope->nesting_depth() + 1, line);
933 break;
934 }
935 case TGSI_OPCODE_ENDLOOP: {
936 cur_scope->set_end(line);
937 cur_scope = cur_scope->parent();
938 assert(cur_scope);
939 break;
940 }
941 case TGSI_OPCODE_IF:
942 case TGSI_OPCODE_UIF: {
943 assert(num_inst_src_regs(inst) == 1);
944 const st_src_reg& src = inst->src[0];
945 if (src.file == PROGRAM_TEMPORARY)
946 acc[src.index].record_read(line, cur_scope, src.swizzle);
947 cur_scope = scopes.create(cur_scope, if_branch, if_id++,
948 cur_scope->nesting_depth() + 1, line + 1);
949 break;
950 }
951 case TGSI_OPCODE_ELSE: {
952 assert(cur_scope->type() == if_branch);
953 cur_scope->set_end(line - 1);
954 cur_scope = scopes.create(cur_scope->parent(), else_branch,
955 cur_scope->id(), cur_scope->nesting_depth(),
956 line + 1);
957 break;
958 }
959 case TGSI_OPCODE_END: {
960 cur_scope->set_end(line);
961 is_at_end = true;
962 break;
963 }
964 case TGSI_OPCODE_ENDIF: {
965 cur_scope->set_end(line - 1);
966 cur_scope = cur_scope->parent();
967 assert(cur_scope);
968 break;
969 }
970 case TGSI_OPCODE_SWITCH: {
971 assert(num_inst_src_regs(inst) == 1);
972 const st_src_reg& src = inst->src[0];
973 prog_scope *scope = scopes.create(cur_scope, switch_body, switch_id++,
974 cur_scope->nesting_depth() + 1, line);
975 /* We record the read only for the SWITCH statement itself, like it
976 * is used by the only consumer of TGSI_OPCODE_SWITCH in tgsi_exec.c.
977 */
978 if (src.file == PROGRAM_TEMPORARY)
979 acc[src.index].record_read(line, cur_scope, src.swizzle);
980 cur_scope = scope;
981 break;
982 }
983 case TGSI_OPCODE_ENDSWITCH: {
984 cur_scope->set_end(line - 1);
985 /* Remove the case level, it might not have been
986 * closed with a break.
987 */
988 if (cur_scope->type() != switch_body)
989 cur_scope = cur_scope->parent();
990
991 cur_scope = cur_scope->parent();
992 assert(cur_scope);
993 break;
994 }
995 case TGSI_OPCODE_CASE: {
996 /* Take care of tracking the registers. */
997 prog_scope *switch_scope = cur_scope->type() == switch_body ?
998 cur_scope : cur_scope->parent();
999
1000 assert(num_inst_src_regs(inst) == 1);
1001 const st_src_reg& src = inst->src[0];
1002 if (src.file == PROGRAM_TEMPORARY)
1003 acc[src.index].record_read(line, switch_scope, src.swizzle);
1004
1005 /* Fall through to allocate the scope. */
1006 }
1007 case TGSI_OPCODE_DEFAULT: {
1008 prog_scope_type t = inst->op == TGSI_OPCODE_CASE ? switch_case_branch
1009 : switch_default_branch;
1010 prog_scope *switch_scope = (cur_scope->type() == switch_body) ?
1011 cur_scope : cur_scope->parent();
1012 assert(switch_scope->type() == switch_body);
1013 prog_scope *scope = scopes.create(switch_scope, t,
1014 switch_scope->id(),
1015 switch_scope->nesting_depth() + 1,
1016 line);
1017 /* Previous case falls through, so scope was not yet closed. */
1018 if ((cur_scope != switch_scope) && (cur_scope->end() == -1))
1019 cur_scope->set_end(line - 1);
1020 cur_scope = scope;
1021 break;
1022 }
1023 case TGSI_OPCODE_BRK: {
1024 if (cur_scope->break_is_for_switchcase()) {
1025 cur_scope->set_end(line - 1);
1026 } else {
1027 cur_scope->set_loop_break_line(line);
1028 }
1029 break;
1030 }
1031 case TGSI_OPCODE_CAL:
1032 case TGSI_OPCODE_RET:
1033 /* These opcodes are not supported and if a subroutine would
1034 * be called in a shader, then the lifetime tracking would have
1035 * to follow that call to see which registers are used there.
1036 * Since this is not done, we have to bail out here and signal
1037 * that no register merge will take place.
1038 */
1039 ok = false;
1040 goto out;
1041 default: {
1042 for (unsigned j = 0; j < num_inst_src_regs(inst); j++) {
1043 const st_src_reg& src = inst->src[j];
1044 if (src.file == PROGRAM_TEMPORARY)
1045 acc[src.index].record_read(line, cur_scope, src.swizzle);
1046 }
1047 for (unsigned j = 0; j < inst->tex_offset_num_offset; j++) {
1048 const st_src_reg& src = inst->tex_offsets[j];
1049 if (src.file == PROGRAM_TEMPORARY)
1050 acc[src.index].record_read(line, cur_scope, src.swizzle);
1051 }
1052 for (unsigned j = 0; j < num_inst_dst_regs(inst); j++) {
1053 const st_dst_reg& dst = inst->dst[j];
1054 if (dst.file == PROGRAM_TEMPORARY)
1055 acc[dst.index].record_write(line, cur_scope, dst.writemask);
1056 }
1057 }
1058 }
1059 ++line;
1060 }
1061
1062 RENAME_DEBUG(debug_log << "==================================\n\n");
1063
1064 /* Make sure last scope is closed, even though no
1065 * TGSI_OPCODE_END was given.
1066 */
1067 if (cur_scope->end() < 0)
1068 cur_scope->set_end(line - 1);
1069
1070 RENAME_DEBUG(debug_log << "========= lifetimes ==============\n");
1071 for(int i = 0; i < ntemps; ++i) {
1072 RENAME_DEBUG(debug_log << setw(4) << i);
1073 lifetimes[i] = acc[i].get_required_lifetime();
1074 RENAME_DEBUG(debug_log << ": [" << lifetimes[i].begin << ", "
1075 << lifetimes[i].end << "]\n");
1076 }
1077 RENAME_DEBUG(debug_log << "==================================\n\n");
1078
1079 out:
1080 delete[] acc;
1081 return ok;
1082 }
1083
1084 /* Find the next register between [start, end) that has a life time starting
1085 * at or after bound by using a binary search.
1086 * start points at the beginning of the search range,
1087 * end points at the element past the end of the search range, and
1088 * the array comprising [start, end) must be sorted in ascending order.
1089 */
1090 static access_record*
1091 find_next_rename(access_record* start, access_record* end, int bound)
1092 {
1093 int delta = (end - start);
1094
1095 while (delta > 0) {
1096 int half = delta >> 1;
1097 access_record* middle = start + half;
1098
1099 if (bound <= middle->begin) {
1100 delta = half;
1101 } else {
1102 start = middle;
1103 ++start;
1104 delta -= half + 1;
1105 }
1106 }
1107
1108 return start;
1109 }
1110
1111 #ifndef USE_STL_SORT
1112 static int access_record_compare (const void *a, const void *b) {
1113 const access_record *aa = static_cast<const access_record*>(a);
1114 const access_record *bb = static_cast<const access_record*>(b);
1115 return aa->begin < bb->begin ? -1 : (aa->begin > bb->begin ? 1 : 0);
1116 }
1117 #endif
1118
1119 /* This functions evaluates the register merges by using a binary
1120 * search to find suitable merge candidates. */
1121 void get_temp_registers_remapping(void *mem_ctx, int ntemps,
1122 const struct lifetime* lifetimes,
1123 struct rename_reg_pair *result)
1124 {
1125 access_record *reg_access = ralloc_array(mem_ctx, access_record, ntemps);
1126
1127 int used_temps = 0;
1128 for (int i = 0; i < ntemps; ++i) {
1129 if (lifetimes[i].begin >= 0) {
1130 reg_access[used_temps].begin = lifetimes[i].begin;
1131 reg_access[used_temps].end = lifetimes[i].end;
1132 reg_access[used_temps].reg = i;
1133 reg_access[used_temps].erase = false;
1134 ++used_temps;
1135 }
1136 }
1137
1138 #ifdef USE_STL_SORT
1139 std::sort(reg_access, reg_access + used_temps);
1140 #else
1141 std::qsort(reg_access, used_temps, sizeof(access_record), access_record_compare);
1142 #endif
1143
1144 access_record *trgt = reg_access;
1145 access_record *reg_access_end = reg_access + used_temps;
1146 access_record *first_erase = reg_access_end;
1147 access_record *search_start = trgt + 1;
1148
1149 while (trgt != reg_access_end) {
1150 access_record *src = find_next_rename(search_start, reg_access_end,
1151 trgt->end);
1152 if (src != reg_access_end) {
1153 result[src->reg].new_reg = trgt->reg;
1154 result[src->reg].valid = true;
1155 trgt->end = src->end;
1156
1157 /* Since we only search forward, don't remove the renamed
1158 * register just now, only mark it. */
1159 src->erase = true;
1160
1161 if (first_erase == reg_access_end)
1162 first_erase = src;
1163
1164 search_start = src + 1;
1165 } else {
1166 /* Moving to the next target register it is time to remove
1167 * the already merged registers from the search range */
1168 if (first_erase != reg_access_end) {
1169 access_record *outp = first_erase;
1170 access_record *inp = first_erase + 1;
1171
1172 while (inp != reg_access_end) {
1173 if (!inp->erase)
1174 *outp++ = *inp;
1175 ++inp;
1176 }
1177
1178 reg_access_end = outp;
1179 first_erase = reg_access_end;
1180 }
1181 ++trgt;
1182 search_start = trgt + 1;
1183 }
1184 }
1185 ralloc_free(reg_access);
1186 }
1187
1188 /* Code below used for debugging */
1189 #ifndef NDEBUG
1190 static
1191 void dump_instruction(ostream& os, int line, prog_scope *scope,
1192 const glsl_to_tgsi_instruction& inst)
1193 {
1194 const struct tgsi_opcode_info *info = inst.info;
1195 int indent = scope->nesting_depth();
1196 if ((scope->type() == switch_case_branch ||
1197 scope->type() == switch_default_branch) &&
1198 (info->opcode == TGSI_OPCODE_CASE ||
1199 info->opcode == TGSI_OPCODE_DEFAULT))
1200 --indent;
1201
1202 if (info->opcode == TGSI_OPCODE_ENDIF ||
1203 info->opcode == TGSI_OPCODE_ELSE ||
1204 info->opcode == TGSI_OPCODE_ENDLOOP ||
1205 info->opcode == TGSI_OPCODE_ENDSWITCH)
1206 --indent;
1207
1208 os << setw(4) << line << ": ";
1209 os << setw(indent * 4) << " ";
1210 os << inst << "\n";
1211 }
1212 #endif