1/* -*- mesa-c++ -*- 2 * 3 * Copyright (c) 2018-2019 Collabora LTD 4 * 5 * Author: Gert Wollny <gert.wollny@collabora.com> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * on the rights to use, copy, modify, merge, publish, distribute, sub 11 * license, and/or sell copies of the Software, and to permit persons to whom 12 * the Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27#include "sfn_value_gpr.h" 28#include "sfn_valuepool.h" 29#include "sfn_debug.h" 30#include "sfn_liverange.h" 31 32namespace r600 { 33 34using std::vector; 35using std::array; 36 37GPRValue::GPRValue(uint32_t sel, uint32_t chan, int base_offset): 38 Value(Value::gpr, chan), 39 m_sel(sel), 40 m_base_offset(base_offset), 41 m_input(false), 42 m_pin_to_channel(false), 43 m_keep_alive(false) 44{ 45} 46 47GPRValue::GPRValue(uint32_t sel, uint32_t chan): 48 Value(Value::gpr, chan), 49 m_sel(sel), 50 m_base_offset(0), 51 m_input(false), 52 m_pin_to_channel(false), 53 m_keep_alive(false) 54{ 55} 56 57uint32_t GPRValue::sel() const 58{ 59 return m_sel; 60} 61 62void GPRValue::do_print(std::ostream& os) const 63{ 64 os << 'R'; 65 os << m_sel; 66 os << '.' << component_names[chan()]; 67} 68 69bool GPRValue::is_equal_to(const Value& other) const 70{ 71 assert(other.type() == Value::Type::gpr); 72 const auto& rhs = static_cast<const GPRValue&>(other); 73 return (sel() == rhs.sel() && 74 chan() == rhs.chan()); 75} 76 77void GPRValue::do_print(std::ostream& os, UNUSED const PrintFlags& flags) const 78{ 79 os << 'R'; 80 os << m_sel; 81 os << '.' << component_names[chan()]; 82} 83 84GPRVector::GPRVector(const GPRVector& orig): 85 Value(gpr_vector), 86 m_elms(orig.m_elms), 87 m_valid(orig.m_valid) 88{ 89} 90 91GPRVector::GPRVector(std::array<PValue,4> elms): 92 Value(gpr_vector), 93 m_elms(elms), 94 m_valid(false) 95{ 96 for (unsigned i = 0; i < 4; ++i) 97 if (!m_elms[i] || (m_elms[i]->type() != Value::gpr)) { 98 assert(0 && "GPR vector not valid because element missing or nit a GPR"); 99 return; 100 } 101 unsigned sel = m_elms[0]->sel(); 102 for (unsigned i = 1; i < 4; ++i) 103 if (m_elms[i]->sel() != sel) { 104 assert(0 && "GPR vector not valid because sel is not equal for all elements"); 105 return; 106 } 107 m_valid = true; 108} 109 110GPRVector::GPRVector(uint32_t sel, std::array<uint32_t,4> swizzle): 111 Value (gpr_vector), 112 m_valid(true) 113{ 114 for (int i = 0; i < 4; ++i) 115 m_elms[i] = PValue(new GPRValue(sel, swizzle[i])); 116} 117 118GPRVector::GPRVector(const GPRVector& orig, const std::array<uint8_t,4>& swizzle) 119{ 120 for (int i = 0; i < 4; ++i) 121 m_elms[i] = orig.reg_i(swizzle[i]); 122 m_valid = orig.m_valid; 123} 124 125void GPRVector::validate() const 126{ 127 assert(m_elms[0]); 128 uint32_t sel = m_elms[0]->sel(); 129 if (sel >= 124) 130 return; 131 132 for (unsigned i = 1; i < 4; ++i) { 133 assert(m_elms[i]); 134 if (sel != m_elms[i]->sel()) 135 return; 136 } 137 138 m_valid = true; 139} 140 141uint32_t GPRVector::sel() const 142{ 143 validate(); 144 assert(m_valid); 145 return m_elms[0] ? m_elms[0]->sel() : 999; 146} 147 148void GPRVector::set_reg_i(int i, PValue reg) 149{ 150 m_elms[i] = reg; 151} 152 153void GPRVector::pin_to_channel(int i) 154{ 155 auto& v = static_cast<GPRValue&>(*m_elms[i]); 156 v.set_pin_to_channel(); 157} 158 159void GPRVector::pin_all_to_channel() 160{ 161 for (auto& v: m_elms) { 162 auto& c = static_cast<GPRValue&>(*v); 163 c.set_pin_to_channel(); 164 } 165} 166 167void GPRVector::do_print(std::ostream& os) const 168{ 169 os << "R" << sel() << "."; 170 for (int i = 0; i < 4; ++i) 171 os << (m_elms[i] ? component_names[m_elms[i]->chan() < 8 ? m_elms[i]->chan() : 8] : '?'); 172} 173 174void GPRVector::swizzle(const Swizzle& swz) 175{ 176 Values v(m_elms); 177 for (uint32_t i = 0; i < 4; ++i) 178 if (i != swz[i]) { 179 assert(swz[i] < 4); 180 m_elms[i] = v[swz[i]]; 181 } 182} 183 184bool GPRVector::is_equal_to(const Value& other) const 185{ 186 if (other.type() != gpr_vector) { 187 std::cerr << "t"; 188 return false; 189 } 190 191 const GPRVector& o = static_cast<const GPRVector&>(other); 192 193 for (int i = 0; i < 4; ++i) { 194 if (*m_elms[i] != *o.m_elms[i]) { 195 std::cerr << "elm" << i; 196 return false; 197 } 198 } 199 return true; 200} 201 202 203GPRArrayValue::GPRArrayValue(PValue value, PValue addr, GPRArray *array): 204 Value(gpr_array_value, value->chan()), 205 m_value(value), 206 m_addr(addr), 207 m_array(array) 208{ 209} 210 211GPRArrayValue::GPRArrayValue(PValue value, GPRArray *array): 212 Value(gpr_array_value, value->chan()), 213 m_value(value), 214 m_array(array) 215{ 216} 217 218static const char *swz_char = "xyzw01_"; 219 220void GPRArrayValue::do_print(std::ostream& os) const 221{ 222 assert(m_array); 223 os << "R" << m_value->sel(); 224 if (m_addr) { 225 os << "[" << *m_addr << "] "; 226 } 227 os << swz_char[m_value->chan()]; 228 229 os << "(" << *m_array << ")"; 230} 231 232bool GPRArrayValue::is_equal_to(const Value& other) const 233{ 234 const GPRArrayValue& v = static_cast<const GPRArrayValue&>(other); 235 236 return *m_value == *v.m_value && 237 *m_array == *v.m_array; 238} 239 240void GPRArrayValue::record_read(LiverangeEvaluator& ev) const 241{ 242 if (m_addr) { 243 ev.record_read(*m_addr); 244 unsigned chan = m_value->chan(); 245 assert(m_array); 246 m_array->record_read(ev, chan); 247 } else 248 ev.record_read(*m_value); 249} 250 251void GPRArrayValue::record_write(LiverangeEvaluator& ev) const 252{ 253 if (m_addr) { 254 ev.record_read(*m_addr); 255 unsigned chan = m_value->chan(); 256 assert(m_array); 257 m_array->record_write(ev, chan); 258 } else 259 ev.record_write(*m_value); 260} 261 262void GPRArrayValue::reset_value(PValue new_value) 263{ 264 m_value = new_value; 265} 266 267void GPRArrayValue::reset_addr(PValue new_addr) 268{ 269 m_addr = new_addr; 270} 271 272 273GPRArray::GPRArray(int base, int size, int mask, int frac): 274 Value (gpr_vector), 275 m_base_index(base), 276 m_component_mask(mask), 277 m_frac(frac) 278{ 279 m_values.resize(size); 280 for (int i = 0; i < size; ++i) { 281 for (int j = 0; j < 4; ++j) { 282 if (mask & (1 << j)) { 283 auto gpr = new GPRValue(base + i, j); 284 /* If we want to use sb, we have to keep arrays 285 * alife for the whole shader range, otherwise the sb scheduler 286 * thinks is not capable to rename non-array uses of these registers */ 287 gpr->set_as_input(); 288 gpr->set_keep_alive(); 289 m_values[i].set_reg_i(j, PValue(gpr)); 290 291 } 292 } 293 } 294} 295 296uint32_t GPRArray::sel() const 297{ 298 return m_base_index; 299} 300 301static const char *compchar = "xyzw"; 302void GPRArray::do_print(std::ostream& os) const 303{ 304 os << "ARRAY[R" << sel() << "..R" << sel() + m_values.size() - 1 << "]."; 305 for (int j = 0; j < 4; ++j) { 306 if (m_component_mask & (1 << j)) 307 os << compchar[j]; 308 } 309} 310 311bool GPRArray::is_equal_to(const Value& other) const 312{ 313 const GPRArray& o = static_cast<const GPRArray&>(other); 314 return o.sel() == sel() && 315 o.m_values.size() == m_values.size() && 316 o.m_component_mask == m_component_mask; 317} 318 319uint32_t GPRArrayValue::sel() const 320{ 321 return m_value->sel(); 322} 323 324PValue GPRArray::get_indirect(unsigned index, PValue indirect, unsigned component) 325{ 326 assert(index < m_values.size()); 327 assert(m_component_mask & (1 << (component + m_frac))); 328 329 sfn_log << SfnLog::reg << "Create indirect register from " << *this; 330 331 PValue v = m_values[index].reg_i(component + m_frac); 332 assert(v); 333 334 sfn_log << SfnLog::reg << " -> " << *v; 335 336 if (indirect) { 337 sfn_log << SfnLog::reg << "[" << *indirect << "]"; 338 switch (indirect->type()) { 339 case Value::literal: { 340 const LiteralValue& lv = static_cast<const LiteralValue&>(*indirect); 341 v = m_values[lv.value()].reg_i(component + m_frac); 342 break; 343 } 344 case Value::gpr: { 345 v = PValue(new GPRArrayValue(v, indirect, this)); 346 sfn_log << SfnLog::reg << "(" << *v << ")"; 347 break; 348 } 349 default: 350 assert(0 && !"Indirect addressing must be literal value or GPR"); 351 } 352 } 353 sfn_log << SfnLog::reg <<" -> " << *v << "\n"; 354 return v; 355} 356 357void GPRArray::record_read(LiverangeEvaluator& ev, int chan) const 358{ 359 for (auto& v: m_values) 360 ev.record_read(*v.reg_i(chan), true); 361} 362 363void GPRArray::record_write(LiverangeEvaluator& ev, int chan) const 364{ 365 for (auto& v: m_values) 366 ev.record_write(*v.reg_i(chan), true); 367} 368 369void GPRArray::collect_registers(ValueMap& output) const 370{ 371 for (auto& v: m_values) { 372 for (int i = 0; i < 4; ++i) { 373 auto vv = v.reg_i(i); 374 if (vv) 375 output.insert(vv); 376 } 377 } 378} 379 380} 381