2 * Copyright © 2017 Gert Wollny
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:
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
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.
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"
32 /* std::sort is significantly faster than qsort */
41 #include "program/prog_print.h"
42 #include "util/debug.h"
48 /* If <windows.h> is included this is defined and clashes with
49 * std::numeric_limits<>::max()
55 using std::numeric_limits
;
57 /* Without c++11 define the nullptr for forward-compatibility
58 * and better readibility */
59 #if __cplusplus < 201103L
64 /* Prepare to make it possible to specify log file */
65 static std::ostream
& debug_log
= cerr
;
67 /* Helper function to check whether we want to seen debugging output */
68 static inline bool is_debug_enabled ()
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;
75 #define RENAME_DEBUG(X) if (is_debug_enabled()) do { X; } while (false);
77 #define RENAME_DEBUG(X)
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 */
95 prog_scope(prog_scope
*parent
, prog_scope_type type
, int id
,
96 int depth
, int begin
);
98 prog_scope_type
type() const;
99 prog_scope
*parent() const;
100 int nesting_depth() const;
104 int loop_break_line() const;
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;
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;
120 bool break_is_for_switchcase() const;
121 bool contains_range_of(const prog_scope
& other
) const;
123 void set_end(int end
);
124 void set_loop_break_line(int line
);
127 prog_scope_type scope_type
;
129 int scope_nesting_depth
;
133 prog_scope
*parent_scope
;
136 /* Some storage class to encapsulate the prog_scope (de-)allocations */
137 class prog_scope_storage
{
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
);
149 /* Class to track the access to a component of a temporary register. */
151 class temp_comp_access
{
155 void record_read(int line
, prog_scope
*scope
);
156 void record_write(int line
, prog_scope
*scope
);
157 lifetime
get_required_lifetime();
159 void propagate_lifetime_to_dominant_write_scope();
160 bool conditional_ifelse_write_in_loop() const;
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
);
166 prog_scope
*last_read_scope
;
167 prog_scope
*first_read_scope
;
168 prog_scope
*first_write_scope
;
175 /* This member variable tracks the current resolution of conditional writing
176 * to this temporary in IF/ELSE clauses.
178 * The initial value "conditionality_untouched" indicates that this
179 * temporary has not yet been written to within an if clause.
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.
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.
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
194 int conditionality_in_loop_id
;
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
;
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
205 unsigned int if_scope_write_flags
;
207 int next_ifelse_nesting_depth
;
208 static const int supported_ifelse_nesting_depth
= 32;
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.
214 const prog_scope
*current_unpaired_if_write_scope
;
216 /* Flag to resolve read-before-write in the else scope. */
217 bool was_written_in_current_else_scope
;
221 temp_comp_access::conditionality_untouched
= numeric_limits
<int>::max();
223 /* Class to track the access to all components of a temporary register. */
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();
231 void update_access_mask(int mask
);
233 temp_comp_access comp
[4];
235 bool needs_component_tracking
;
238 prog_scope_storage::prog_scope_storage(void *mc
, int n
):
242 storage
= ralloc_array(mem_ctx
, prog_scope
, n
);
245 prog_scope_storage::~prog_scope_storage()
247 ralloc_free(storage
);
251 prog_scope_storage::create(prog_scope
*p
, prog_scope_type type
, int id
,
252 int lvl
, int s_begin
)
254 storage
[current_slot
] = prog_scope(p
, type
, id
, lvl
, s_begin
);
255 return &storage
[current_slot
++];
258 prog_scope::prog_scope(prog_scope
*parent
, prog_scope_type type
, int id
,
259 int depth
, int scope_begin
):
262 scope_nesting_depth(depth
),
263 scope_begin(scope_begin
),
265 break_loop_line(numeric_limits
<int>::max()),
270 prog_scope_type
prog_scope::type() const
275 prog_scope
*prog_scope::parent() const
280 int prog_scope::nesting_depth() const
282 return scope_nesting_depth
;
285 bool prog_scope::is_loop() const
287 return (scope_type
== loop_body
);
290 bool prog_scope::is_in_loop() const
292 if (scope_type
== loop_body
)
296 return parent_scope
->is_in_loop();
301 const prog_scope
*prog_scope::innermost_loop() const
303 if (scope_type
== loop_body
)
307 return parent_scope
->innermost_loop();
312 const prog_scope
*prog_scope::outermost_loop() const
314 const prog_scope
*loop
= nullptr;
315 const prog_scope
*p
= this;
318 if (p
->type() == loop_body
)
326 bool prog_scope::is_child_of_ifelse_id_sibling(const prog_scope
*scope
) const
328 const prog_scope
*my_parent
= in_parent_ifelse_scope();
330 /* is a direct child? */
331 if (my_parent
== scope
)
333 /* is a child of the conditions sibling? */
334 if (my_parent
->id() == scope
->id())
336 my_parent
= my_parent
->in_parent_ifelse_scope();
341 bool prog_scope::is_child_of(const prog_scope
*scope
) const
343 const prog_scope
*my_parent
= parent();
345 if (my_parent
== scope
)
347 my_parent
= my_parent
->parent();
352 const prog_scope
*prog_scope::enclosing_conditional() const
354 if (is_conditional())
358 return parent_scope
->enclosing_conditional();
363 bool prog_scope::contains_range_of(const prog_scope
& other
) const
365 return (begin() <= other
.begin()) && (end() >= other
.end());
368 bool prog_scope::is_conditional() const
370 return scope_type
== if_branch
||
371 scope_type
== else_branch
||
372 scope_type
== switch_case_branch
||
373 scope_type
== switch_default_branch
;
376 const prog_scope
*prog_scope::in_else_scope() const
378 if (scope_type
== else_branch
)
382 return parent_scope
->in_else_scope();
387 const prog_scope
*prog_scope::in_parent_ifelse_scope() const
390 return parent_scope
->in_ifelse_scope();
395 const prog_scope
*prog_scope::in_ifelse_scope() const
397 if (scope_type
== if_branch
||
398 scope_type
== else_branch
)
402 return parent_scope
->in_ifelse_scope();
407 bool prog_scope::is_switchcase_scope_in_loop() const
409 return (scope_type
== switch_case_branch
||
410 scope_type
== switch_default_branch
) &&
414 bool prog_scope::break_is_for_switchcase() const
416 if (scope_type
== loop_body
)
419 if (scope_type
== switch_case_branch
||
420 scope_type
== switch_default_branch
||
421 scope_type
== switch_body
)
425 return parent_scope
->break_is_for_switchcase();
430 int prog_scope::id() const
435 int prog_scope::begin() const
440 int prog_scope::end() const
445 void prog_scope::set_end(int end
)
451 void prog_scope::set_loop_break_line(int line
)
453 if (scope_type
== loop_body
) {
454 break_loop_line
= MIN2(break_loop_line
, line
);
457 parent()->set_loop_break_line(line
);
461 int prog_scope::loop_break_line() const
463 return break_loop_line
;
466 temp_access::temp_access():
468 needs_component_tracking(false)
472 void temp_access::update_access_mask(int mask
)
474 if (access_mask
&& access_mask
!= mask
)
475 needs_component_tracking
= true;
479 void temp_access::record_write(int line
, prog_scope
*scope
, int writemask
)
481 update_access_mask(writemask
);
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
);
493 void temp_access::record_read(int line
, prog_scope
*scope
, int swizzle
)
496 for (int idx
= 0; idx
< 4; ++idx
) {
497 int swz
= GET_SWZ(swizzle
, idx
);
498 readmask
|= (1 << swz
) & 0xF;
500 update_access_mask(readmask
);
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
);
512 inline static lifetime
make_lifetime(int b
, int e
)
520 lifetime
temp_access::get_required_lifetime()
522 lifetime result
= make_lifetime(-1, -1);
524 unsigned mask
= access_mask
;
526 unsigned chan
= u_bit_scan(&mask
);
527 lifetime lt
= comp
[chan
].get_required_lifetime();
530 if ((result
.begin
< 0) || (result
.begin
> lt
.begin
))
531 result
.begin
= lt
.begin
;
534 if (lt
.end
> result
.end
)
537 if (!needs_component_tracking
)
543 temp_comp_access::temp_comp_access():
544 last_read_scope(nullptr),
545 first_read_scope(nullptr),
546 first_write_scope(nullptr),
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)
559 void temp_comp_access::record_read(int line
, prog_scope
*scope
)
561 last_read_scope
= scope
;
564 if (first_read
> line
) {
566 first_read_scope
= scope
;
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())) {
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.
578 if ((conditionality_in_loop_id
!= write_is_conditional
) &&
579 (conditionality_in_loop_id
!= enclosing_loop
->id())) {
581 if (current_unpaired_if_write_scope
) {
583 /* Has been written in this or a parent scope? - this makes the temporary
584 * unconditionally set at this point.
586 if (scope
->is_child_of(current_unpaired_if_write_scope
))
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())
594 if (was_written_in_current_else_scope
)
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.
603 conditionality_in_loop_id
= write_is_conditional
;
608 void temp_comp_access::record_write(int line
, prog_scope
*scope
)
612 if (first_write
< 0) {
614 first_write_scope
= scope
;
617 if (conditionality_in_loop_id
== write_is_conditional
)
620 /* If the nesting depth is larger than the supported level,
621 * then we assume conditional writes.
623 if (next_ifelse_nesting_depth
>= supported_ifelse_nesting_depth
) {
624 conditionality_in_loop_id
= write_is_conditional
;
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.
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
);
637 void temp_comp_access::record_ifelse_write(const prog_scope
& scope
)
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).
643 conditionality_in_loop_id
= conditionality_unresolved
;
644 was_written_in_current_else_scope
= false;
645 record_if_write(scope
);
647 was_written_in_current_else_scope
= true;
648 record_else_write(scope
);
652 void temp_comp_access::record_if_write(const prog_scope
& scope
)
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.
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.
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
++;
676 void temp_comp_access::record_else_write(const prog_scope
& scope
)
678 int mask
= 1 << (next_ifelse_nesting_depth
- 1);
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.
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
;
691 /* The following code deals with propagating unconditionality from
692 * inner levels of nested IF/ELSE to the outer levels like in
695 * 2: if (a) { <- start scope A
700 * 7: } else { <- start scope B
703 * A: else <- start scope C
709 const prog_scope
*parent_ifelse
= scope
.parent()->in_ifelse_scope();
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
718 current_unpaired_if_write_scope
= parent_ifelse
;
720 current_unpaired_if_write_scope
= nullptr;
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
729 if (parent_ifelse
&& parent_ifelse
->is_in_loop()) {
730 record_ifelse_write(*parent_ifelse
);
732 conditionality_in_loop_id
= scope
.innermost_loop()->id();
735 /* The temporary was not written in the IF branch corresponding
736 * to this ELSE branch, hence the write is conditional.
738 conditionality_in_loop_id
= write_is_conditional
;
742 bool temp_comp_access::conditional_ifelse_write_in_loop() const
744 return conditionality_in_loop_id
<= conditionality_unresolved
;
747 void temp_comp_access::propagate_lifetime_to_dominant_write_scope()
749 first_write
= first_write_scope
->begin();
750 int lr
= first_write_scope
->end();
756 lifetime
temp_comp_access::get_required_lifetime()
758 bool keep_for_full_loop
= false;
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.
766 return make_lifetime(-1, -1);
768 assert(first_write_scope
);
770 /* Only written to, just make sure the register component is not
771 * reused in the range it is used to write to
773 if (!last_read_scope
)
774 return make_lifetime(first_write
, last_write
+ 1);
776 const prog_scope
*enclosing_scope_first_read
= first_read_scope
;
777 const prog_scope
*enclosing_scope_first_write
= first_write_scope
;
779 /* We read before writing in a loop
780 * hence the value must survive the loops
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();
788 /* A conditional write within a (nested) loop must survive the outermost
789 * loop if the last read was not within the same scope.
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();
799 /* Evaluate the scope that is shared by all: required first write scope,
800 * required first read before write scope, and last read scope.
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
;
806 if (last_read_scope
->contains_range_of(*enclosing_scope
))
807 enclosing_scope
= last_read_scope
;
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
);
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.
822 if (last_read_scope
->is_loop())
823 last_read
= last_read_scope
->end();
825 last_read_scope
= last_read_scope
->parent();
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.
831 if (keep_for_full_loop
&& first_write_scope
->is_loop())
832 propagate_lifetime_to_dominant_write_scope();
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.
840 if (first_write_scope
->loop_break_line() < first_write
) {
841 keep_for_full_loop
= true;
842 propagate_lifetime_to_dominant_write_scope();
845 first_write_scope
= first_write_scope
->parent();
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();
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.
856 if (last_write
>= last_read
)
857 last_read
= last_write
+ 1;
859 /* Here we are at the same scope, all is resolved */
860 return make_lifetime(first_write
, last_read
);
863 /* Helper class for sorting and searching the registers based
865 class access_record
{
872 bool operator < (const access_record
& rhs
) const {
873 return begin
< rhs
.begin
;
880 /* Function used for debugging. */
881 static void dump_instruction(ostream
& os
, int line
, prog_scope
*scope
,
882 const glsl_to_tgsi_instruction
& inst
);
885 /* Scan the program and estimate the required register life times.
886 * The array lifetimes must be pre-allocated
889 get_temp_registers_required_lifetimes(void *mem_ctx
, exec_list
*instructions
,
890 int ntemps
, struct lifetime
*lifetimes
)
896 bool is_at_end
= false;
900 /* Count scopes to allocate the needed space without the need for
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
)
914 prog_scope_storage
scopes(mem_ctx
, n_scopes
);
915 temp_access
*acc
= new temp_access
[ntemps
];
917 prog_scope
*cur_scope
= scopes
.create(nullptr, outer_scope
, 0, 0, line
);
919 RENAME_DEBUG(debug_log
<< "========= Begin shader ============\n");
921 foreach_in_list(glsl_to_tgsi_instruction
, inst
, instructions
) {
923 assert(!"GLSL_TO_TGSI: shader has instructions past end marker");
927 RENAME_DEBUG(dump_instruction(debug_log
, line
, cur_scope
, *inst
));
930 case TGSI_OPCODE_BGNLOOP
: {
931 cur_scope
= scopes
.create(cur_scope
, loop_body
, loop_id
++,
932 cur_scope
->nesting_depth() + 1, line
);
935 case TGSI_OPCODE_ENDLOOP
: {
936 cur_scope
->set_end(line
);
937 cur_scope
= cur_scope
->parent();
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);
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(),
959 case TGSI_OPCODE_END
: {
960 cur_scope
->set_end(line
);
964 case TGSI_OPCODE_ENDIF
: {
965 cur_scope
->set_end(line
- 1);
966 cur_scope
= cur_scope
->parent();
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.
978 if (src
.file
== PROGRAM_TEMPORARY
)
979 acc
[src
.index
].record_read(line
, cur_scope
, src
.swizzle
);
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.
988 if (cur_scope
->type() != switch_body
)
989 cur_scope
= cur_scope
->parent();
991 cur_scope
= cur_scope
->parent();
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();
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
);
1005 /* Fall through to allocate the scope. */
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
,
1015 switch_scope
->nesting_depth() + 1,
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);
1023 case TGSI_OPCODE_BRK
: {
1024 if (cur_scope
->break_is_for_switchcase()) {
1025 cur_scope
->set_end(line
- 1);
1027 cur_scope
->set_loop_break_line(line
);
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.
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
);
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
);
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
);
1062 RENAME_DEBUG(debug_log
<< "==================================\n\n");
1064 /* Make sure last scope is closed, even though no
1065 * TGSI_OPCODE_END was given.
1067 if (cur_scope
->end() < 0)
1068 cur_scope
->set_end(line
- 1);
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");
1077 RENAME_DEBUG(debug_log
<< "==================================\n\n");
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.
1090 static access_record
*
1091 find_next_rename(access_record
* start
, access_record
* end
, int bound
)
1093 int delta
= (end
- start
);
1096 int half
= delta
>> 1;
1097 access_record
* middle
= start
+ half
;
1099 if (bound
<= middle
->begin
) {
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);
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
)
1125 access_record
*reg_access
= ralloc_array(mem_ctx
, access_record
, ntemps
);
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;
1139 std::sort(reg_access
, reg_access
+ used_temps
);
1141 std::qsort(reg_access
, used_temps
, sizeof(access_record
), access_record_compare
);
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;
1149 while (trgt
!= reg_access_end
) {
1150 access_record
*src
= find_next_rename(search_start
, reg_access_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
;
1157 /* Since we only search forward, don't remove the renamed
1158 * register just now, only mark it. */
1161 if (first_erase
== reg_access_end
)
1164 search_start
= src
+ 1;
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;
1172 while (inp
!= reg_access_end
) {
1178 reg_access_end
= outp
;
1179 first_erase
= reg_access_end
;
1182 search_start
= trgt
+ 1;
1185 ralloc_free(reg_access
);
1188 /* Code below used for debugging */
1191 void dump_instruction(ostream
& os
, int line
, prog_scope
*scope
,
1192 const glsl_to_tgsi_instruction
& inst
)
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
))
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
)
1208 os
<< setw(4) << line
<< ": ";
1209 os
<< setw(indent
* 4) << " ";