xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_liverangeevaluator_helpers.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* -*- mesa-c++  -*-
2  * Copyright 2022 Collabora LTD
3  * Author: Gert Wollny <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #ifndef SFN_LIFERANGEEVALUATOR_HELPERS_H
8 #define SFN_LIFERANGEEVALUATOR_HELPERS_H
9 
10 #include "sfn_valuefactory.h"
11 
12 namespace r600 {
13 
14 enum ProgramScopeType {
15    outer_scope,           /* Outer program scope */
16    loop_body,             /* Inside a loop */
17    if_branch,             /* Inside if branch */
18    else_branch,           /* Inside else branch */
19    switch_body,           /* Inside switch statement */
20    switch_case_branch,    /* Inside switch case statement */
21    switch_default_branch, /* Inside switch default statement */
22    undefined_scope
23 };
24 
25 class ProgramScope {
26 public:
27    ProgramScope();
28    ProgramScope(ProgramScope *parent, ProgramScopeType type, int id, int depth, int begin);
29 
30    ProgramScopeType type() const;
31    ProgramScope *parent() const;
32    int nesting_depth() const;
33    int id() const;
34    int end() const;
35    int begin() const;
36    int loop_break_line() const;
37 
38    const ProgramScope *in_else_scope() const;
39    const ProgramScope *in_ifelse_scope() const;
40    const ProgramScope *in_parent_ifelse_scope() const;
41    const ProgramScope *innermost_loop() const;
42    const ProgramScope *outermost_loop() const;
43    const ProgramScope *enclosing_conditional() const;
44 
45    bool is_loop() const;
46    bool is_in_loop() const;
47    bool is_switchcase_scope_in_loop() const;
48    bool is_conditional() const;
49    bool is_child_of(const ProgramScope *scope) const;
50    bool is_child_of_ifelse_id_sibling(const ProgramScope *scope) const;
51 
52    bool break_is_for_switchcase() const;
53    bool contains_range_of(const ProgramScope& other) const;
54 
55    void set_end(int end);
56    void set_loop_break_line(int line);
57 
58 private:
59    ProgramScopeType scope_type;
60    int scope_id;
61    int scope_nesting_depth;
62    int scope_begin;
63    int scope_end;
64    int break_loop_line;
65    ProgramScope *parent_scope;
66 };
67 
68 /* Class to track the access to a component of a temporary register. */
69 
70 struct LiveRange;
71 
72 class RegisterCompAccess {
73 public:
74    RegisterCompAccess();
75    RegisterCompAccess(LiveRange range);
76 
77    void record_read(int block,int line, ProgramScope *scope, LiveRangeEntry::EUse use);
78    void record_write(int block, int line, ProgramScope *scope);
79 
80    void update_required_live_range();
81 
range()82    const auto& range() { return m_range; }
83 
use_type()84    const auto& use_type() { return m_use_type; }
85 
alu_clause_local()86    auto alu_clause_local() { return alu_block_id > block_id_uninitalized;}
87 
88 private:
89    void propagate_live_range_to_dominant_write_scope();
90    bool conditional_ifelse_write_in_loop() const;
91 
92    void record_ifelse_write(const ProgramScope& scope);
93    void record_if_write(const ProgramScope& scope);
94    void record_else_write(const ProgramScope& scope);
95 
96    ProgramScope *last_read_scope;
97    ProgramScope *first_read_scope;
98    ProgramScope *first_write_scope;
99 
100    int first_write;
101    int last_read;
102    int last_write;
103    int first_read;
104 
105    int alu_block_id{block_id_uninitalized};
106 
107    /* This member variable tracks the current resolution of conditional writing
108     * to this temporary in IF/ELSE clauses.
109     *
110     * The initial value "conditionality_untouched" indicates that this
111     * temporary has not yet been written to within an if clause.
112     *
113     * A positive (other than "conditionality_untouched") number refers to the
114     * last loop id for which the write was resolved as unconditional. With
115     * each new loop this value will be overwritten by
116     * "conditionality_unresolved" on entering the first IF clause writing this
117     * temporary.
118     *
119     * The value "conditionality_unresolved" indicates that no resolution has
120     * been achieved so far. If the variable is set to this value at the end of
121     * the processing of the whole shader it also indicates a conditional
122     * write.
123     *
124     * The value "write_is_conditional" marks that the variable is written
125     * conditionally (i.e. not in all relevant IF/ELSE code path pairs) in at
126     * least one loop.
127     */
128    int conditionality_in_loop_id;
129 
130    /* Helper constants to make the tracking code more readable. */
131    static const int write_is_conditional = -1;
132    static const int conditionality_unresolved = 0;
133    static const int conditionality_untouched;
134    static const int write_is_unconditional;
135    static const int block_id_not_unique = -1;
136    static const int block_id_uninitalized = 0;
137 
138    /* A bit field tracking the nesting levels of if-else clauses where the
139     * temporary has (so far) been written to in the if branch, but not in the
140     * else branch.
141     */
142    unsigned int if_scope_write_flags;
143 
144    int next_ifelse_nesting_depth;
145    static const int supported_ifelse_nesting_depth = 32;
146 
147    /* Tracks the last if scope in which the temporary was written to
148     * without a write in the corresponding else branch. Is also used
149     * to track read-before-write in the according scope.
150     */
151    const ProgramScope *current_unpaired_if_write_scope;
152 
153    /* Flag to resolve read-before-write in the else scope. */
154    bool was_written_in_current_else_scope;
155 
156    LiveRange m_range;
157 
158    std::bitset<LiveRangeEntry::use_unspecified> m_use_type;
159 };
160 
161 class RegisterAccess {
162 public:
163    using RegisterCompAccessVector = std::vector<RegisterCompAccess>;
164 
165    RegisterAccess(const std::array<size_t, 4>& sizes);
166 
167    RegisterCompAccess& operator()(const Register& reg);
168 
component(int i)169    auto& component(int i) { return m_access_record[i]; }
170 
171 private:
172    std::array<RegisterCompAccessVector, 4> m_access_record;
173 };
174 
175 } // namespace r600
176 #endif // SFN_LIFERANGEEVALUATOR_HELPERS_H
177