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