1bf215546Sopenharmony_ci/* -*- mesa-c++ -*- 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright (c) 2021 Collabora LTD 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Author: Gert Wollny <gert.wollny@collabora.com> 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 10bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 11bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 12bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 15bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 16bf215546Sopenharmony_ci * Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "sfn_virtualvalues.h" 28bf215546Sopenharmony_ci#include "sfn_alu_defines.h" 29bf215546Sopenharmony_ci#include "sfn_valuefactory.h" 30bf215546Sopenharmony_ci#include "sfn_instr.h" 31bf215546Sopenharmony_ci#include "sfn_debug.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "util/macros.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include <ostream> 36bf215546Sopenharmony_ci#include <iostream> 37bf215546Sopenharmony_ci#include <iomanip> 38bf215546Sopenharmony_ci#include <limits> 39bf215546Sopenharmony_ci#include <sstream> 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cinamespace r600 { 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistd::ostream& operator << (std::ostream& os, Pin pin) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci#define PRINT_PIN(X) case pin_ ## X : os << #X; break 46bf215546Sopenharmony_ci switch (pin) { 47bf215546Sopenharmony_ci PRINT_PIN(chan); 48bf215546Sopenharmony_ci PRINT_PIN(array); 49bf215546Sopenharmony_ci PRINT_PIN(fully); 50bf215546Sopenharmony_ci PRINT_PIN(group); 51bf215546Sopenharmony_ci PRINT_PIN(chgr); 52bf215546Sopenharmony_ci PRINT_PIN(free); 53bf215546Sopenharmony_ci case pin_none: 54bf215546Sopenharmony_ci default: 55bf215546Sopenharmony_ci ; 56bf215546Sopenharmony_ci } 57bf215546Sopenharmony_ci#undef PRINT_PIN 58bf215546Sopenharmony_ci return os; 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ciVirtualValue::VirtualValue(int sel, int chan, Pin pin): 62bf215546Sopenharmony_ci m_sel(sel), m_chan(chan), m_pins(pin) 63bf215546Sopenharmony_ci{ 64bf215546Sopenharmony_ci#if __cpp_exceptions >= 199711L 65bf215546Sopenharmony_ci ASSERT_OR_THROW(m_sel < virtual_register_base || pin != pin_fully, "Register is virtual but pinned to sel"); 66bf215546Sopenharmony_ci#endif 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cibool VirtualValue::ready(int block, int index) const 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci (void)block; 72bf215546Sopenharmony_ci (void)index; 73bf215546Sopenharmony_ci return true; 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cibool VirtualValue::is_virtual() const 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci return m_sel >= virtual_register_base; 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ciclass ValueComparer: public ConstRegisterVisitor { 82bf215546Sopenharmony_cipublic: 83bf215546Sopenharmony_ci ValueComparer(); 84bf215546Sopenharmony_ci ValueComparer(const Register *value); 85bf215546Sopenharmony_ci ValueComparer(const LocalArray *value); 86bf215546Sopenharmony_ci ValueComparer(const LocalArrayValue *value); 87bf215546Sopenharmony_ci ValueComparer(const UniformValue *value); 88bf215546Sopenharmony_ci ValueComparer(const LiteralConstant *value); 89bf215546Sopenharmony_ci ValueComparer(const InlineConstant *value); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci void visit(const Register& other) override; 92bf215546Sopenharmony_ci void visit(const LocalArray& other) override; 93bf215546Sopenharmony_ci void visit(const LocalArrayValue& other) override; 94bf215546Sopenharmony_ci void visit(const UniformValue& value) override; 95bf215546Sopenharmony_ci void visit(const LiteralConstant& other) override; 96bf215546Sopenharmony_ci void visit(const InlineConstant& other) override; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci bool m_result; 99bf215546Sopenharmony_ciprivate: 100bf215546Sopenharmony_ci const Register *m_register; 101bf215546Sopenharmony_ci const LocalArray *m_array; 102bf215546Sopenharmony_ci const LocalArrayValue *m_array_value; 103bf215546Sopenharmony_ci const UniformValue *m_uniform_value; 104bf215546Sopenharmony_ci const LiteralConstant *m_literal_value; 105bf215546Sopenharmony_ci const InlineConstant *m_inline_constant; 106bf215546Sopenharmony_ci}; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ciclass ValueCompareCreater: public ConstRegisterVisitor { 109bf215546Sopenharmony_cipublic: 110bf215546Sopenharmony_ci void visit(const Register& value) { compare = ValueComparer(&value);} 111bf215546Sopenharmony_ci void visit(const LocalArray& value) {compare = ValueComparer(&value);} 112bf215546Sopenharmony_ci void visit(const LocalArrayValue& value) {compare = ValueComparer(&value);} 113bf215546Sopenharmony_ci void visit(const UniformValue& value) {compare = ValueComparer(&value);} 114bf215546Sopenharmony_ci void visit(const LiteralConstant& value) {compare = ValueComparer(&value);} 115bf215546Sopenharmony_ci void visit(const InlineConstant& value) {compare = ValueComparer(&value);} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci ValueComparer compare; 118bf215546Sopenharmony_ci}; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ciVirtualValue::Pointer VirtualValue::from_string(const std::string& s) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci switch (s[0]) { 123bf215546Sopenharmony_ci case 'S': 124bf215546Sopenharmony_ci case 'R': return Register::from_string(s); 125bf215546Sopenharmony_ci case 'L': return LiteralConstant::from_string(s); 126bf215546Sopenharmony_ci case 'K': return UniformValue::from_string(s); 127bf215546Sopenharmony_ci case 'P': return InlineConstant::param_from_string(s); 128bf215546Sopenharmony_ci case 'I': return InlineConstant::from_string(s); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci default: 131bf215546Sopenharmony_ci std::cerr << "'" << s << "'"; 132bf215546Sopenharmony_ci unreachable("Unknown register type"); 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci} 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_cibool VirtualValue::equal_to(const VirtualValue& other) const 137bf215546Sopenharmony_ci{ 138bf215546Sopenharmony_ci bool result = m_sel == other.m_sel && 139bf215546Sopenharmony_ci m_chan == other.m_chan && 140bf215546Sopenharmony_ci m_pins == other.m_pins; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci if (result) { 143bf215546Sopenharmony_ci ValueCompareCreater comp_creater; 144bf215546Sopenharmony_ci accept(comp_creater); 145bf215546Sopenharmony_ci other.accept(comp_creater.compare); 146bf215546Sopenharmony_ci result &= comp_creater.compare.m_result; 147bf215546Sopenharmony_ci } 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci return result; 150bf215546Sopenharmony_ci} 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ciVirtualValue::Pointer VirtualValue::get_addr() const 153bf215546Sopenharmony_ci{ 154bf215546Sopenharmony_ci class GetAddressRegister: public ConstRegisterVisitor { 155bf215546Sopenharmony_ci public: 156bf215546Sopenharmony_ci void visit(const VirtualValue& value) {(void)value;} 157bf215546Sopenharmony_ci void visit(const Register& value) {(void)value;}; 158bf215546Sopenharmony_ci void visit(const LocalArray& value) {(void)value;} 159bf215546Sopenharmony_ci void visit(const LocalArrayValue& value) {m_result = value.addr();} 160bf215546Sopenharmony_ci void visit(const UniformValue& value) {(void)value;} 161bf215546Sopenharmony_ci void visit(const LiteralConstant& value) {(void)value;} 162bf215546Sopenharmony_ci void visit(const InlineConstant& value) {(void)value;} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci GetAddressRegister() : m_result(nullptr) {} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci PVirtualValue m_result; 167bf215546Sopenharmony_ci }; 168bf215546Sopenharmony_ci GetAddressRegister get_addr; 169bf215546Sopenharmony_ci accept(get_addr); 170bf215546Sopenharmony_ci return get_addr.m_result; 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ciRegister::Register(int sel, int chan, Pin pin): 174bf215546Sopenharmony_ci VirtualValue(sel, chan, pin) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci} 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_civoid Register::add_parent(Instr *instr) 179bf215546Sopenharmony_ci{ 180bf215546Sopenharmony_ci m_parents.insert(instr); 181bf215546Sopenharmony_ci instr->add_use(); 182bf215546Sopenharmony_ci add_parent_to_array(instr); 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_civoid Register::add_parent_to_array(Instr *instr) 186bf215546Sopenharmony_ci{ 187bf215546Sopenharmony_ci (void)instr; 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_civoid Register::del_parent(Instr *instr) 191bf215546Sopenharmony_ci{ 192bf215546Sopenharmony_ci m_parents.erase(instr); 193bf215546Sopenharmony_ci instr->dec_use(); 194bf215546Sopenharmony_ci del_parent_from_array(instr); 195bf215546Sopenharmony_ci} 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_civoid Register::del_parent_from_array(Instr *instr) 198bf215546Sopenharmony_ci{ 199bf215546Sopenharmony_ci (void)instr; 200bf215546Sopenharmony_ci} 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_civoid Register::add_use(Instr *instr) 204bf215546Sopenharmony_ci{ 205bf215546Sopenharmony_ci const auto& [itr, inserted] = m_uses.insert(instr); {} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci if (inserted) { 208bf215546Sopenharmony_ci for (auto& p: m_parents) 209bf215546Sopenharmony_ci p->add_use(); 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci} 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_civoid Register::del_use(Instr *instr) 214bf215546Sopenharmony_ci{ 215bf215546Sopenharmony_ci sfn_log << SfnLog::opt << "Del use of " << *this << " in " << *instr << "\n"; 216bf215546Sopenharmony_ci if (m_uses.find(instr) != m_uses.end()) { 217bf215546Sopenharmony_ci m_uses.erase(instr); 218bf215546Sopenharmony_ci if (is_ssa()) 219bf215546Sopenharmony_ci for (auto& p: m_parents) 220bf215546Sopenharmony_ci p->dec_use(); 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_cibool Register::ready(int block, int index) const 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci for (auto p : m_parents) { 227bf215546Sopenharmony_ci if (p->block_id() <= block) { 228bf215546Sopenharmony_ci if (p->index() < index && !p->is_scheduled()) { 229bf215546Sopenharmony_ci return false; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci return true; 234bf215546Sopenharmony_ci} 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_civoid Register::accept(RegisterVisitor& visitor) 237bf215546Sopenharmony_ci{ 238bf215546Sopenharmony_ci visitor.visit(*this); 239bf215546Sopenharmony_ci} 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_civoid Register::accept(ConstRegisterVisitor& visitor) const 242bf215546Sopenharmony_ci{ 243bf215546Sopenharmony_ci visitor.visit(*this); 244bf215546Sopenharmony_ci} 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_civoid Register::pin_live_range(bool start, bool end) 248bf215546Sopenharmony_ci{ 249bf215546Sopenharmony_ci m_pin_start = start; 250bf215546Sopenharmony_ci m_pin_end = end; 251bf215546Sopenharmony_ci} 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_civoid Register::set_is_ssa(bool value) 254bf215546Sopenharmony_ci{ 255bf215546Sopenharmony_ci m_is_ssa = value; 256bf215546Sopenharmony_ci} 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_civoid Register::print(std::ostream& os) const 259bf215546Sopenharmony_ci{ 260bf215546Sopenharmony_ci os << (m_is_ssa ? "S" : "R") << sel() << "." << chanchar[chan()]; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci if (pin() != pin_none) 263bf215546Sopenharmony_ci os << "@" << pin(); 264bf215546Sopenharmony_ci} 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ciRegister::Pointer Register::from_string(const std::string &s) 267bf215546Sopenharmony_ci{ 268bf215546Sopenharmony_ci std::string numstr; 269bf215546Sopenharmony_ci char chan = 0; 270bf215546Sopenharmony_ci std::string pinstr; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci assert(s[0] == 'R' || s[0] == '_' || s[0] == 'S' ); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci int type = 0; 275bf215546Sopenharmony_ci for (unsigned i = 1; i < s.length(); ++i) { 276bf215546Sopenharmony_ci if (s[i] == '.') { 277bf215546Sopenharmony_ci type = 1; 278bf215546Sopenharmony_ci continue; 279bf215546Sopenharmony_ci } else if (s[i] == '@') { 280bf215546Sopenharmony_ci type = 2; 281bf215546Sopenharmony_ci continue; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci switch (type) { 285bf215546Sopenharmony_ci case 0: numstr.append(1, s[i]); break; 286bf215546Sopenharmony_ci case 1: chan = s[i]; break; 287bf215546Sopenharmony_ci case 2: pinstr.append(1, s[i]); break; 288bf215546Sopenharmony_ci default: 289bf215546Sopenharmony_ci unreachable("Malformed register string"); 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci int sel; 294bf215546Sopenharmony_ci if (s[0] != '_') { 295bf215546Sopenharmony_ci std::istringstream n(numstr); 296bf215546Sopenharmony_ci n >> sel; 297bf215546Sopenharmony_ci } else { 298bf215546Sopenharmony_ci sel = std::numeric_limits<int>::max(); 299bf215546Sopenharmony_ci } 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci auto p = pin_none; 302bf215546Sopenharmony_ci if (pinstr == "chan") 303bf215546Sopenharmony_ci p = pin_chan; 304bf215546Sopenharmony_ci else if (pinstr == "array") 305bf215546Sopenharmony_ci p = pin_array; 306bf215546Sopenharmony_ci else if (pinstr == "fully") 307bf215546Sopenharmony_ci p = pin_fully; 308bf215546Sopenharmony_ci else if (pinstr == "group") 309bf215546Sopenharmony_ci p = pin_group; 310bf215546Sopenharmony_ci else if (pinstr == "chgr") 311bf215546Sopenharmony_ci p = pin_chgr; 312bf215546Sopenharmony_ci else if (pinstr == "free") 313bf215546Sopenharmony_ci p = pin_free; 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci switch (chan) { 316bf215546Sopenharmony_ci case 'x' : chan = 0; break; 317bf215546Sopenharmony_ci case 'y' : chan = 1; break; 318bf215546Sopenharmony_ci case 'z' : chan = 2; break; 319bf215546Sopenharmony_ci case 'w' : chan = 3; break; 320bf215546Sopenharmony_ci case '0' : chan = 4; break; 321bf215546Sopenharmony_ci case '1' : chan = 5; break; 322bf215546Sopenharmony_ci case '_' : chan = 7; break; 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci auto reg = new Register( sel, chan, p); 326bf215546Sopenharmony_ci reg->set_is_ssa(s[0] == 'S'); 327bf215546Sopenharmony_ci if (p == pin_fully || p == pin_array) 328bf215546Sopenharmony_ci reg->pin_live_range(true); 329bf215546Sopenharmony_ci return reg; 330bf215546Sopenharmony_ci} 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ciRegisterVec4::RegisterVec4(): 333bf215546Sopenharmony_ci m_sel(-1), 334bf215546Sopenharmony_ci m_swz({7,7,7,7}), 335bf215546Sopenharmony_ci m_values({nullptr, nullptr, nullptr, nullptr}) 336bf215546Sopenharmony_ci{ 337bf215546Sopenharmony_ci} 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ciRegisterVec4::RegisterVec4(int sel, bool is_ssa, const Swizzle& swz, Pin pin): 340bf215546Sopenharmony_ci m_sel(sel), 341bf215546Sopenharmony_ci m_swz(swz) 342bf215546Sopenharmony_ci{ 343bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 344bf215546Sopenharmony_ci m_values[i] = new Element( *this, new Register(m_sel, swz[i], pin)); 345bf215546Sopenharmony_ci m_values[i]->value()->set_is_ssa(is_ssa); 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci} 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ciRegisterVec4::RegisterVec4(const RegisterVec4& orig): 350bf215546Sopenharmony_ci m_sel(orig.m_sel), 351bf215546Sopenharmony_ci m_swz(orig.m_swz) 352bf215546Sopenharmony_ci{ 353bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) 354bf215546Sopenharmony_ci m_values[i] = new Element(*this, orig.m_values[i]->value()); 355bf215546Sopenharmony_ci} 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ciRegisterVec4::RegisterVec4(PRegister x, PRegister y, PRegister z, PRegister w, Pin pin) 358bf215546Sopenharmony_ci{ 359bf215546Sopenharmony_ci PRegister dummy = nullptr; 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci if (x) { 362bf215546Sopenharmony_ci m_sel = x->sel(); 363bf215546Sopenharmony_ci } else if (y) { 364bf215546Sopenharmony_ci m_sel = y->sel(); 365bf215546Sopenharmony_ci } else if (z) { 366bf215546Sopenharmony_ci m_sel = z->sel(); 367bf215546Sopenharmony_ci } else if (w) { 368bf215546Sopenharmony_ci m_sel = w->sel(); 369bf215546Sopenharmony_ci } else 370bf215546Sopenharmony_ci m_sel = 0; 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci if (!(x && y && z && w)) 373bf215546Sopenharmony_ci dummy = new Register (m_sel, 7, pin_none); 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci m_values[0] = new Element(*this, x ? x : dummy); 376bf215546Sopenharmony_ci m_values[1] = new Element(*this, y ? y : dummy); 377bf215546Sopenharmony_ci m_values[2] = new Element(*this, z ? z : dummy); 378bf215546Sopenharmony_ci m_values[3] = new Element(*this, w ? w : dummy); 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 381bf215546Sopenharmony_ci if (m_values[0]->value()->pin() == pin_fully) { 382bf215546Sopenharmony_ci pin = pin_fully; 383bf215546Sopenharmony_ci break; 384bf215546Sopenharmony_ci } 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 388bf215546Sopenharmony_ci switch (m_values[i]->value()->pin()) { 389bf215546Sopenharmony_ci case pin_none: 390bf215546Sopenharmony_ci case pin_free: 391bf215546Sopenharmony_ci m_values[i]->value()->set_pin(pin); 392bf215546Sopenharmony_ci break; 393bf215546Sopenharmony_ci case pin_chan: 394bf215546Sopenharmony_ci if (pin == pin_group) 395bf215546Sopenharmony_ci m_values[i]->value()->set_pin(pin_chgr); 396bf215546Sopenharmony_ci break; 397bf215546Sopenharmony_ci default: 398bf215546Sopenharmony_ci ; 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci m_swz[i] = m_values[i]->value()->chan(); 402bf215546Sopenharmony_ci assert(m_values[i]->value()->sel() == m_sel); 403bf215546Sopenharmony_ci } 404bf215546Sopenharmony_ci} 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_civoid RegisterVec4::add_use(Instr *instr) 407bf215546Sopenharmony_ci{ 408bf215546Sopenharmony_ci for (auto& r: m_values) { 409bf215546Sopenharmony_ci if (r->value()->chan() < 4) 410bf215546Sopenharmony_ci r->value()->add_use(instr); 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci} 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_civoid RegisterVec4::del_use(Instr *instr) 415bf215546Sopenharmony_ci{ 416bf215546Sopenharmony_ci for (auto& r: m_values) { 417bf215546Sopenharmony_ci r->value()->del_use(instr); 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci} 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_cibool RegisterVec4::has_uses() const 422bf215546Sopenharmony_ci{ 423bf215546Sopenharmony_ci for (auto& r: m_values) { 424bf215546Sopenharmony_ci if (r->value()->has_uses()) 425bf215546Sopenharmony_ci return true; 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci return false; 428bf215546Sopenharmony_ci} 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ciint RegisterVec4::sel() const 432bf215546Sopenharmony_ci{ 433bf215546Sopenharmony_ci int comp = 0; 434bf215546Sopenharmony_ci while (comp < 4 && m_values[comp]->value()->chan() > 3) 435bf215546Sopenharmony_ci ++comp; 436bf215546Sopenharmony_ci return comp < 4 ? m_values[comp]->value()->sel() : 0; 437bf215546Sopenharmony_ci} 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_cibool RegisterVec4::ready(int block_id, int index) const 440bf215546Sopenharmony_ci{ 441bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 442bf215546Sopenharmony_ci if (m_values[i]->value()->chan() < 4) { 443bf215546Sopenharmony_ci if (!m_values[i]->value()->ready(block_id, index)) 444bf215546Sopenharmony_ci return false; 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci return true; 448bf215546Sopenharmony_ci} 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_civoid RegisterVec4::print(std::ostream& os) const 451bf215546Sopenharmony_ci{ 452bf215546Sopenharmony_ci os << (m_values[0]->value()->is_ssa() ? 'S' : 'R') << sel() << "."; 453bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) 454bf215546Sopenharmony_ci os << VirtualValue::chanchar[m_swz[i]]; 455bf215546Sopenharmony_ci} 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_cibool operator == (const RegisterVec4& lhs, const RegisterVec4& rhs) 458bf215546Sopenharmony_ci{ 459bf215546Sopenharmony_ci for (int i = 0; i < 4; ++i) { 460bf215546Sopenharmony_ci assert(lhs[i]); 461bf215546Sopenharmony_ci assert(rhs[i]); 462bf215546Sopenharmony_ci if (!lhs[i]->equal_to(*rhs[i])) { 463bf215546Sopenharmony_ci return false; 464bf215546Sopenharmony_ci } 465bf215546Sopenharmony_ci } 466bf215546Sopenharmony_ci return true; 467bf215546Sopenharmony_ci} 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ciRegisterVec4::Element::Element(const RegisterVec4& parent, int chan): 470bf215546Sopenharmony_ci m_parent(parent), 471bf215546Sopenharmony_ci m_value(new Register(parent.m_sel, chan, pin_none)) 472bf215546Sopenharmony_ci{ 473bf215546Sopenharmony_ci} 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ciRegisterVec4::Element::Element(const RegisterVec4& parent, PRegister value): 476bf215546Sopenharmony_ci m_parent(parent), 477bf215546Sopenharmony_ci m_value(value) 478bf215546Sopenharmony_ci{ 479bf215546Sopenharmony_ci} 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ciLiteralConstant::LiteralConstant(uint32_t value): 482bf215546Sopenharmony_ci VirtualValue(ALU_SRC_LITERAL, -1, pin_none), 483bf215546Sopenharmony_ci m_value(value) 484bf215546Sopenharmony_ci{ 485bf215546Sopenharmony_ci} 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_civoid LiteralConstant::accept(RegisterVisitor& vistor) 488bf215546Sopenharmony_ci{ 489bf215546Sopenharmony_ci vistor.visit(*this); 490bf215546Sopenharmony_ci} 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_civoid LiteralConstant::accept(ConstRegisterVisitor& vistor) const 493bf215546Sopenharmony_ci{ 494bf215546Sopenharmony_ci vistor.visit(*this); 495bf215546Sopenharmony_ci} 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_civoid LiteralConstant::print(std::ostream& os) const 498bf215546Sopenharmony_ci{ 499bf215546Sopenharmony_ci os << "L[0x" << std::hex << m_value << std::dec << "]"; 500bf215546Sopenharmony_ci} 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ciLiteralConstant::Pointer LiteralConstant::from_string(const std::string& s) 503bf215546Sopenharmony_ci{ 504bf215546Sopenharmony_ci if (s[1] != '[') 505bf215546Sopenharmony_ci return nullptr; 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci std::string numstr; 508bf215546Sopenharmony_ci for (unsigned i = 2; i < s.length(); ++i) { 509bf215546Sopenharmony_ci if (s[i] == ']') 510bf215546Sopenharmony_ci break; 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci if (isxdigit(s[i])) 513bf215546Sopenharmony_ci numstr.append(1, s[i]); 514bf215546Sopenharmony_ci if (s[i] == 'x') 515bf215546Sopenharmony_ci continue; 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci std::istringstream n(numstr); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci uint32_t num; 521bf215546Sopenharmony_ci n >> std::hex >> num; 522bf215546Sopenharmony_ci return new LiteralConstant( num); 523bf215546Sopenharmony_ci} 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci// Inline constants usually don't care about the channel but 527bf215546Sopenharmony_ci// ALU_SRC_PV should be pinned, but we only emit these constants 528bf215546Sopenharmony_ci// very late, and based on the real register they replace 529bf215546Sopenharmony_ciInlineConstant::InlineConstant(int sel, int chan): 530bf215546Sopenharmony_ci VirtualValue(sel, chan, pin_none) 531bf215546Sopenharmony_ci{ 532bf215546Sopenharmony_ci} 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_civoid InlineConstant::accept(RegisterVisitor& vistor) 535bf215546Sopenharmony_ci{ 536bf215546Sopenharmony_ci vistor.visit(*this); 537bf215546Sopenharmony_ci} 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_civoid InlineConstant::accept(ConstRegisterVisitor& vistor) const 540bf215546Sopenharmony_ci{ 541bf215546Sopenharmony_ci vistor.visit(*this); 542bf215546Sopenharmony_ci} 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_civoid InlineConstant::print(std::ostream& os) const 545bf215546Sopenharmony_ci{ 546bf215546Sopenharmony_ci auto ivalue = alu_src_const.find(static_cast<AluInlineConstants>(sel())); 547bf215546Sopenharmony_ci if (ivalue != alu_src_const.end()) { 548bf215546Sopenharmony_ci os << "I[" << ivalue->second.descr<< "]"; 549bf215546Sopenharmony_ci if (ivalue->second.use_chan) 550bf215546Sopenharmony_ci os << "." << chanchar[chan()]; 551bf215546Sopenharmony_ci } else if (sel() >= ALU_SRC_PARAM_BASE && 552bf215546Sopenharmony_ci sel() < ALU_SRC_PARAM_BASE + 32 ) { 553bf215546Sopenharmony_ci os << "Param" 554bf215546Sopenharmony_ci << sel() - ALU_SRC_PARAM_BASE 555bf215546Sopenharmony_ci << "." << chanchar[chan()]; 556bf215546Sopenharmony_ci } else { 557bf215546Sopenharmony_ci unreachable("Unknown inline constant"); 558bf215546Sopenharmony_ci } 559bf215546Sopenharmony_ci} 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_cistd::map<std::string, std::pair<AluInlineConstants, bool>> InlineConstant::s_opmap; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ciInlineConstant::Pointer InlineConstant::from_string(const std::string& s) 564bf215546Sopenharmony_ci{ 565bf215546Sopenharmony_ci std::string namestr; 566bf215546Sopenharmony_ci char chan = 0; 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci ASSERT_OR_THROW(s[1] == '[', "inline const not started with '['"); 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci unsigned i = 2; 571bf215546Sopenharmony_ci while (i < s.length()) { 572bf215546Sopenharmony_ci if (s[i] == ']') 573bf215546Sopenharmony_ci break; 574bf215546Sopenharmony_ci namestr.append(1, s[i]); 575bf215546Sopenharmony_ci ++i; 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci ASSERT_OR_THROW(s[i] == ']', "inline const not closed with ']'"); 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_ci auto entry = s_opmap.find(namestr); 581bf215546Sopenharmony_ci AluInlineConstants value = ALU_SRC_UNKNOWN; 582bf215546Sopenharmony_ci bool use_chan = false; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci if (entry == s_opmap.end()) { 585bf215546Sopenharmony_ci for (auto& [opcode, descr] : alu_src_const) { 586bf215546Sopenharmony_ci if (namestr == descr.descr) { 587bf215546Sopenharmony_ci value = opcode; 588bf215546Sopenharmony_ci use_chan = descr.use_chan; 589bf215546Sopenharmony_ci s_opmap[namestr] = std::make_pair(opcode, use_chan); 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci break; 592bf215546Sopenharmony_ci } 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci } else { 595bf215546Sopenharmony_ci value = entry->second.first; 596bf215546Sopenharmony_ci use_chan = entry->second.second; 597bf215546Sopenharmony_ci } 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci ASSERT_OR_THROW(value != ALU_SRC_UNKNOWN, "Unknwon inline constant was given"); 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci if (use_chan) { 602bf215546Sopenharmony_ci ASSERT_OR_THROW(s[i + 1] == '.', "inline const channel not started with '.'"); 603bf215546Sopenharmony_ci switch (s[i + 2]) { 604bf215546Sopenharmony_ci case 'x': chan = 0; break; 605bf215546Sopenharmony_ci case 'y': chan = 1; break; 606bf215546Sopenharmony_ci case 'z': chan = 2; break; 607bf215546Sopenharmony_ci case 'w': chan = 3; break; 608bf215546Sopenharmony_ci case '0': chan = 4; break; 609bf215546Sopenharmony_ci case '1': chan = 5; break; 610bf215546Sopenharmony_ci case '_': chan = 7; break; 611bf215546Sopenharmony_ci default: 612bf215546Sopenharmony_ci ASSERT_OR_THROW(0, "invalied inline const channel "); 613bf215546Sopenharmony_ci } 614bf215546Sopenharmony_ci } 615bf215546Sopenharmony_ci return new InlineConstant( value, chan); 616bf215546Sopenharmony_ci} 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ciInlineConstant::Pointer InlineConstant::param_from_string(const std::string& s) 619bf215546Sopenharmony_ci{ 620bf215546Sopenharmony_ci assert(s.substr(0, 5) == "Param"); 621bf215546Sopenharmony_ci 622bf215546Sopenharmony_ci int param = 0; 623bf215546Sopenharmony_ci int i = 5; 624bf215546Sopenharmony_ci while (isdigit(s[i])) { 625bf215546Sopenharmony_ci param *= 10; 626bf215546Sopenharmony_ci param += s[i] - '0'; 627bf215546Sopenharmony_ci ++i; 628bf215546Sopenharmony_ci } 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci int chan = 7; 631bf215546Sopenharmony_ci assert(s[i] == '.'); 632bf215546Sopenharmony_ci switch (s[i+1]) { 633bf215546Sopenharmony_ci case 'x': chan = 0; break; 634bf215546Sopenharmony_ci case 'y': chan = 1; break; 635bf215546Sopenharmony_ci case 'z': chan = 2; break; 636bf215546Sopenharmony_ci case 'w': chan = 3; break; 637bf215546Sopenharmony_ci default: 638bf215546Sopenharmony_ci unreachable("unsupported channel char"); 639bf215546Sopenharmony_ci } 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci return new InlineConstant( ALU_SRC_PARAM_BASE + param, chan); 642bf215546Sopenharmony_ci} 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ciUniformValue::UniformValue(int sel, int chan, int kcache_bank): 645bf215546Sopenharmony_ci VirtualValue(sel, chan, pin_none), 646bf215546Sopenharmony_ci m_kcache_bank(kcache_bank), 647bf215546Sopenharmony_ci m_buf_addr(nullptr) 648bf215546Sopenharmony_ci{ 649bf215546Sopenharmony_ci} 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ciUniformValue::UniformValue(int sel, int chan, PVirtualValue buf_addr): 652bf215546Sopenharmony_ci VirtualValue(sel, chan, pin_none), 653bf215546Sopenharmony_ci m_kcache_bank(0), 654bf215546Sopenharmony_ci m_buf_addr(buf_addr) 655bf215546Sopenharmony_ci{ 656bf215546Sopenharmony_ci} 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_civoid UniformValue::accept(RegisterVisitor& vistor) 659bf215546Sopenharmony_ci{ 660bf215546Sopenharmony_ci vistor.visit(*this); 661bf215546Sopenharmony_ci} 662bf215546Sopenharmony_ci 663bf215546Sopenharmony_civoid UniformValue::accept(ConstRegisterVisitor& vistor) const 664bf215546Sopenharmony_ci{ 665bf215546Sopenharmony_ci vistor.visit(*this); 666bf215546Sopenharmony_ci} 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ciPVirtualValue UniformValue::buf_addr() const 669bf215546Sopenharmony_ci{ 670bf215546Sopenharmony_ci return m_buf_addr; 671bf215546Sopenharmony_ci} 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_civoid UniformValue::print(std::ostream& os) const 674bf215546Sopenharmony_ci{ 675bf215546Sopenharmony_ci os << "KC" << m_kcache_bank; 676bf215546Sopenharmony_ci if (m_buf_addr) { 677bf215546Sopenharmony_ci os << "[" << *m_buf_addr 678bf215546Sopenharmony_ci << "]"; 679bf215546Sopenharmony_ci } 680bf215546Sopenharmony_ci os << "[" << (sel() - 512) << "]." << chanchar[chan()]; 681bf215546Sopenharmony_ci} 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_cibool UniformValue::equal_buf_and_cache(const UniformValue& other) const 684bf215546Sopenharmony_ci{ 685bf215546Sopenharmony_ci bool result = m_kcache_bank == other.m_kcache_bank; 686bf215546Sopenharmony_ci if (result) { 687bf215546Sopenharmony_ci if (m_buf_addr && other.m_buf_addr) { 688bf215546Sopenharmony_ci result = m_buf_addr->equal_to(other); 689bf215546Sopenharmony_ci } else { 690bf215546Sopenharmony_ci result = !m_buf_addr && !other.m_buf_addr; 691bf215546Sopenharmony_ci } 692bf215546Sopenharmony_ci } 693bf215546Sopenharmony_ci return result; 694bf215546Sopenharmony_ci} 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ciUniformValue::Pointer UniformValue::from_string(const std::string& s) 698bf215546Sopenharmony_ci{ 699bf215546Sopenharmony_ci assert(s[1] == 'C'); 700bf215546Sopenharmony_ci std::istringstream is(s.substr(2)); 701bf215546Sopenharmony_ci int bank; 702bf215546Sopenharmony_ci char c; 703bf215546Sopenharmony_ci is >> bank; 704bf215546Sopenharmony_ci is >> c; 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci assert(c == '['); 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_ci int index; 709bf215546Sopenharmony_ci is >> index; 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci is >> c; 712bf215546Sopenharmony_ci assert(c == ']'); 713bf215546Sopenharmony_ci is >> c; 714bf215546Sopenharmony_ci assert(c == '.'); 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci is >> c; 717bf215546Sopenharmony_ci int chan = 0; 718bf215546Sopenharmony_ci switch (c) { 719bf215546Sopenharmony_ci case 'x': chan = 0; break; 720bf215546Sopenharmony_ci case 'y': chan = 1; break; 721bf215546Sopenharmony_ci case 'z': chan = 2; break; 722bf215546Sopenharmony_ci case 'w': chan = 3; break; 723bf215546Sopenharmony_ci default: 724bf215546Sopenharmony_ci unreachable("Unknown channle when reading uniform"); 725bf215546Sopenharmony_ci } 726bf215546Sopenharmony_ci return new UniformValue(index + 512, chan, bank); 727bf215546Sopenharmony_ci} 728bf215546Sopenharmony_ci 729bf215546Sopenharmony_ciLocalArray::LocalArray(int base_sel, int nchannels, int size, int frac): 730bf215546Sopenharmony_ci Register(base_sel, nchannels, pin_array), 731bf215546Sopenharmony_ci m_base_sel(base_sel), 732bf215546Sopenharmony_ci m_nchannels(nchannels), 733bf215546Sopenharmony_ci m_size(size), 734bf215546Sopenharmony_ci m_values(size * nchannels), 735bf215546Sopenharmony_ci m_frac(frac) 736bf215546Sopenharmony_ci{ 737bf215546Sopenharmony_ci assert(nchannels <= 4); 738bf215546Sopenharmony_ci assert(nchannels + frac <= 4); 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci sfn_log << SfnLog::reg << "Allocate array A" << base_sel << "(" 741bf215546Sopenharmony_ci << size << ", " << frac << ", " << nchannels << ")\n"; 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci for (int c = 0; c < nchannels; ++c) { 744bf215546Sopenharmony_ci for (unsigned i = 0; i < m_size; ++i) { 745bf215546Sopenharmony_ci PRegister reg = new Register( base_sel + i, c + frac, pin_array); 746bf215546Sopenharmony_ci m_values[m_size * c + i] = new LocalArrayValue(reg, *this); 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_ci /* Pin the array register on the start, because currently we don't 749bf215546Sopenharmony_ci * don't track the first write to an array element as write to all 750bf215546Sopenharmony_ci * array elements, and it seems that the one can not just use registers 751bf215546Sopenharmony_ci * that are not written to in an array for other purpouses */ 752bf215546Sopenharmony_ci m_values[m_size * c + i]->pin_live_range(true); 753bf215546Sopenharmony_ci } 754bf215546Sopenharmony_ci } 755bf215546Sopenharmony_ci} 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_civoid LocalArray::accept(RegisterVisitor& vistor) 758bf215546Sopenharmony_ci{ 759bf215546Sopenharmony_ci vistor.visit(*this); 760bf215546Sopenharmony_ci} 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_civoid LocalArray::accept(ConstRegisterVisitor& vistor) const 763bf215546Sopenharmony_ci{ 764bf215546Sopenharmony_ci vistor.visit(*this); 765bf215546Sopenharmony_ci} 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_civoid LocalArray::print(std::ostream& os) const 768bf215546Sopenharmony_ci{ 769bf215546Sopenharmony_ci os << "A" << m_base_sel << "[0 " << ":" << m_values.size() << "]."; 770bf215546Sopenharmony_ci for (unsigned i = 0; i < m_nchannels; ++i) { 771bf215546Sopenharmony_ci os << chanchar[i]; 772bf215546Sopenharmony_ci } 773bf215546Sopenharmony_ci} 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci 776bf215546Sopenharmony_cisize_t LocalArray::size() const 777bf215546Sopenharmony_ci{ 778bf215546Sopenharmony_ci return m_size; 779bf215546Sopenharmony_ci} 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ciuint32_t LocalArray::nchannels() const 782bf215546Sopenharmony_ci{ 783bf215546Sopenharmony_ci return m_nchannels; 784bf215546Sopenharmony_ci} 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ciPRegister LocalArray::element(size_t offset, PVirtualValue indirect, uint32_t chan) 787bf215546Sopenharmony_ci{ 788bf215546Sopenharmony_ci ASSERT_OR_THROW(offset < m_size, "Array: index out of range"); 789bf215546Sopenharmony_ci ASSERT_OR_THROW(chan < m_nchannels, "Array: channel out of range"); 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci sfn_log << SfnLog::reg << "Request element A" << m_base_sel << "[" << offset; 792bf215546Sopenharmony_ci if (indirect) 793bf215546Sopenharmony_ci sfn_log << "+" << *indirect; 794bf215546Sopenharmony_ci sfn_log << SfnLog::reg << "]\n"; 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_ci if (indirect) { 797bf215546Sopenharmony_ci class ResolveDirectArrayElement: public ConstRegisterVisitor { 798bf215546Sopenharmony_ci public: 799bf215546Sopenharmony_ci void visit(const Register& value) {(void) value;}; 800bf215546Sopenharmony_ci void visit(const LocalArray& value) {(void)value; unreachable("An array can't be used as address");} 801bf215546Sopenharmony_ci void visit(const LocalArrayValue& value) {(void) value;} 802bf215546Sopenharmony_ci void visit(const UniformValue& value) {(void)value;} 803bf215546Sopenharmony_ci void visit(const LiteralConstant& value) {offset = value.value(); is_contant = true;} 804bf215546Sopenharmony_ci void visit(const InlineConstant& value) {(void)value;} 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci ResolveDirectArrayElement(): offset(0), is_contant(false) {} 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci int offset; 809bf215546Sopenharmony_ci bool is_contant; 810bf215546Sopenharmony_ci } addr; 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci // If the address os a literal constant then update the offset 813bf215546Sopenharmony_ci // and don't access the value indirectly 814bf215546Sopenharmony_ci indirect->accept(addr); 815bf215546Sopenharmony_ci if (addr.is_contant) { 816bf215546Sopenharmony_ci offset += addr.offset; 817bf215546Sopenharmony_ci indirect = nullptr; 818bf215546Sopenharmony_ci ASSERT_OR_THROW(offset < m_size, "Array: indirect constant index out of range"); 819bf215546Sopenharmony_ci } 820bf215546Sopenharmony_ci } 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci LocalArrayValue *reg = m_values[m_size * chan + offset]; 823bf215546Sopenharmony_ci if (indirect) { 824bf215546Sopenharmony_ci reg = new LocalArrayValue( reg, indirect, *this); 825bf215546Sopenharmony_ci m_values_indirect.push_back(reg); 826bf215546Sopenharmony_ci } 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci sfn_log << SfnLog::reg << " got " << *reg << "\n"; 829bf215546Sopenharmony_ci return reg; 830bf215546Sopenharmony_ci} 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_cibool LocalArray::ready_for_direct(int block, int index, int chan) const 833bf215546Sopenharmony_ci{ 834bf215546Sopenharmony_ci if (!Register::ready(block, index)) 835bf215546Sopenharmony_ci return false; 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci /* For direct access to an array value we also have to take indirect 838bf215546Sopenharmony_ci * writes on the same channels into account */ 839bf215546Sopenharmony_ci for (LocalArrayValue *e : m_values_indirect) { 840bf215546Sopenharmony_ci if (e->chan() == chan && !e->Register::ready(block, index)) { 841bf215546Sopenharmony_ci return false; 842bf215546Sopenharmony_ci } 843bf215546Sopenharmony_ci } 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci return true; 846bf215546Sopenharmony_ci} 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_cibool LocalArray::ready_for_indirect(int block, int index, int chan) const 849bf215546Sopenharmony_ci{ 850bf215546Sopenharmony_ci int offset = (chan - m_frac) * m_size; 851bf215546Sopenharmony_ci for (unsigned i = 0; i < m_size; ++i) { 852bf215546Sopenharmony_ci if (!m_values[offset + i]->Register::ready(block, index)) 853bf215546Sopenharmony_ci return false; 854bf215546Sopenharmony_ci } 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci return ready_for_direct(block, index, chan); 857bf215546Sopenharmony_ci} 858bf215546Sopenharmony_ci 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ciLocalArrayValue::LocalArrayValue(PRegister reg, PVirtualValue index, 861bf215546Sopenharmony_ci LocalArray& array): 862bf215546Sopenharmony_ci Register(reg->sel(), reg->chan(), pin_array), 863bf215546Sopenharmony_ci m_addr(index), 864bf215546Sopenharmony_ci m_array(array) 865bf215546Sopenharmony_ci{ 866bf215546Sopenharmony_ci} 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ciconst Register& LocalArray::operator ()(size_t idx, size_t chan) const 869bf215546Sopenharmony_ci{ 870bf215546Sopenharmony_ci return *m_values[m_size * (chan - m_frac) + idx]; 871bf215546Sopenharmony_ci} 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ciLocalArrayValue::LocalArrayValue(PRegister reg, LocalArray& array): 874bf215546Sopenharmony_ci LocalArrayValue(reg, nullptr, array) 875bf215546Sopenharmony_ci{ 876bf215546Sopenharmony_ci 877bf215546Sopenharmony_ci} 878bf215546Sopenharmony_ci 879bf215546Sopenharmony_ci 880bf215546Sopenharmony_ciPVirtualValue LocalArrayValue::addr() const 881bf215546Sopenharmony_ci{ 882bf215546Sopenharmony_ci return m_addr; 883bf215546Sopenharmony_ci} 884bf215546Sopenharmony_ci 885bf215546Sopenharmony_ciconst LocalArray& LocalArrayValue::array() const 886bf215546Sopenharmony_ci{ 887bf215546Sopenharmony_ci return m_array; 888bf215546Sopenharmony_ci} 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_civoid LocalArrayValue::forward_del_use(Instr *instr) 892bf215546Sopenharmony_ci{ 893bf215546Sopenharmony_ci if (m_addr && m_addr->as_register()) 894bf215546Sopenharmony_ci m_addr->as_register()->del_use(instr); 895bf215546Sopenharmony_ci} 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_civoid LocalArrayValue::forward_add_use(Instr *instr) 898bf215546Sopenharmony_ci{ 899bf215546Sopenharmony_ci if (m_addr && m_addr->as_register()) 900bf215546Sopenharmony_ci m_addr->as_register()->add_use(instr); 901bf215546Sopenharmony_ci} 902bf215546Sopenharmony_ci 903bf215546Sopenharmony_civoid LocalArrayValue::accept(RegisterVisitor& vistor) 904bf215546Sopenharmony_ci{ 905bf215546Sopenharmony_ci vistor.visit(*this); 906bf215546Sopenharmony_ci} 907bf215546Sopenharmony_ci 908bf215546Sopenharmony_civoid LocalArrayValue::accept(ConstRegisterVisitor& vistor) const 909bf215546Sopenharmony_ci{ 910bf215546Sopenharmony_ci vistor.visit(*this); 911bf215546Sopenharmony_ci} 912bf215546Sopenharmony_ci 913bf215546Sopenharmony_civoid LocalArrayValue::add_parent_to_array(Instr *instr) 914bf215546Sopenharmony_ci{ 915bf215546Sopenharmony_ci m_array.add_parent(instr); 916bf215546Sopenharmony_ci} 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_civoid LocalArrayValue::del_parent_from_array(Instr *instr) 919bf215546Sopenharmony_ci{ 920bf215546Sopenharmony_ci m_array.del_parent(instr); 921bf215546Sopenharmony_ci} 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_civoid LocalArrayValue::print(std::ostream& os) const 924bf215546Sopenharmony_ci{ 925bf215546Sopenharmony_ci int offset = sel() - m_array.sel(); 926bf215546Sopenharmony_ci os << "A" << m_array.sel() << "["; 927bf215546Sopenharmony_ci if ( offset > 0 && m_addr) 928bf215546Sopenharmony_ci os << offset << "+" << *m_addr; 929bf215546Sopenharmony_ci else if (m_addr) 930bf215546Sopenharmony_ci os << *m_addr; 931bf215546Sopenharmony_ci else 932bf215546Sopenharmony_ci os << offset; 933bf215546Sopenharmony_ci os << "]." << chanchar[chan()]; 934bf215546Sopenharmony_ci} 935bf215546Sopenharmony_ci 936bf215546Sopenharmony_cibool LocalArrayValue::ready(int block, int index) const 937bf215546Sopenharmony_ci{ 938bf215546Sopenharmony_ci return m_addr ? 939bf215546Sopenharmony_ci (m_array.ready_for_indirect(block, index, chan()) && m_addr->ready(block, index)): 940bf215546Sopenharmony_ci m_array.ready_for_direct(block, index, chan()); 941bf215546Sopenharmony_ci} 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_ciValueComparer::ValueComparer() : 944bf215546Sopenharmony_ci m_result(false), 945bf215546Sopenharmony_ci m_register(nullptr), 946bf215546Sopenharmony_ci m_array(nullptr), 947bf215546Sopenharmony_ci m_array_value(nullptr), 948bf215546Sopenharmony_ci m_uniform_value(nullptr), 949bf215546Sopenharmony_ci m_literal_value(nullptr), 950bf215546Sopenharmony_ci m_inline_constant(nullptr) 951bf215546Sopenharmony_ci{} 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ciValueComparer::ValueComparer(const Register *value): 954bf215546Sopenharmony_ci m_result(false), 955bf215546Sopenharmony_ci m_register(value), 956bf215546Sopenharmony_ci m_array(nullptr), 957bf215546Sopenharmony_ci m_array_value(nullptr), 958bf215546Sopenharmony_ci m_uniform_value(nullptr), 959bf215546Sopenharmony_ci m_literal_value(nullptr), 960bf215546Sopenharmony_ci m_inline_constant(nullptr) 961bf215546Sopenharmony_ci{} 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ciValueComparer::ValueComparer(const LocalArray *value): 964bf215546Sopenharmony_ci m_result(false), 965bf215546Sopenharmony_ci m_register(nullptr), 966bf215546Sopenharmony_ci m_array(value), 967bf215546Sopenharmony_ci m_array_value(nullptr), 968bf215546Sopenharmony_ci m_uniform_value(nullptr), 969bf215546Sopenharmony_ci m_literal_value(nullptr), 970bf215546Sopenharmony_ci m_inline_constant(nullptr) 971bf215546Sopenharmony_ci{} 972bf215546Sopenharmony_ci 973bf215546Sopenharmony_ciValueComparer::ValueComparer(const LocalArrayValue *value): 974bf215546Sopenharmony_ci m_result(false), 975bf215546Sopenharmony_ci m_register(nullptr), 976bf215546Sopenharmony_ci m_array(nullptr), 977bf215546Sopenharmony_ci m_array_value(value), 978bf215546Sopenharmony_ci m_uniform_value(nullptr), 979bf215546Sopenharmony_ci m_literal_value(nullptr), 980bf215546Sopenharmony_ci m_inline_constant(nullptr) 981bf215546Sopenharmony_ci{} 982bf215546Sopenharmony_ci 983bf215546Sopenharmony_ciValueComparer::ValueComparer(const UniformValue *value): 984bf215546Sopenharmony_ci m_result(false), 985bf215546Sopenharmony_ci m_register(nullptr), 986bf215546Sopenharmony_ci m_array(nullptr), 987bf215546Sopenharmony_ci m_array_value(nullptr), 988bf215546Sopenharmony_ci m_uniform_value(value), 989bf215546Sopenharmony_ci m_literal_value(nullptr), 990bf215546Sopenharmony_ci m_inline_constant(nullptr) 991bf215546Sopenharmony_ci{} 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_ciValueComparer::ValueComparer(const LiteralConstant *value): 994bf215546Sopenharmony_ci m_result(false), 995bf215546Sopenharmony_ci m_register(nullptr), 996bf215546Sopenharmony_ci m_array(nullptr), 997bf215546Sopenharmony_ci m_array_value(nullptr), 998bf215546Sopenharmony_ci m_uniform_value(nullptr), 999bf215546Sopenharmony_ci m_literal_value(value), 1000bf215546Sopenharmony_ci m_inline_constant(nullptr) 1001bf215546Sopenharmony_ci{} 1002bf215546Sopenharmony_ci 1003bf215546Sopenharmony_ciValueComparer::ValueComparer(const InlineConstant *value): 1004bf215546Sopenharmony_ci m_result(false), 1005bf215546Sopenharmony_ci m_register(nullptr), 1006bf215546Sopenharmony_ci m_array(nullptr), 1007bf215546Sopenharmony_ci m_array_value(nullptr), 1008bf215546Sopenharmony_ci m_uniform_value(nullptr), 1009bf215546Sopenharmony_ci m_literal_value(nullptr), 1010bf215546Sopenharmony_ci m_inline_constant(value) 1011bf215546Sopenharmony_ci{} 1012bf215546Sopenharmony_ci 1013bf215546Sopenharmony_civoid ValueComparer::visit(const Register& other) 1014bf215546Sopenharmony_ci{ 1015bf215546Sopenharmony_ci (void)other; 1016bf215546Sopenharmony_ci m_result = !!m_register; 1017bf215546Sopenharmony_ci}; 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_civoid ValueComparer::visit(const LocalArray& other) 1020bf215546Sopenharmony_ci{ 1021bf215546Sopenharmony_ci m_result = false; 1022bf215546Sopenharmony_ci if (m_array) { 1023bf215546Sopenharmony_ci m_result = m_array->size() == other.size() && 1024bf215546Sopenharmony_ci m_array->nchannels() == other.nchannels(); 1025bf215546Sopenharmony_ci } 1026bf215546Sopenharmony_ci}; 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_civoid ValueComparer::visit(const LocalArrayValue& other) 1029bf215546Sopenharmony_ci{ 1030bf215546Sopenharmony_ci m_result = false; 1031bf215546Sopenharmony_ci if (m_array_value) { 1032bf215546Sopenharmony_ci m_result = m_array_value->array().equal_to(other.array()); 1033bf215546Sopenharmony_ci if (m_result) { 1034bf215546Sopenharmony_ci auto my_addr = m_array_value->addr(); 1035bf215546Sopenharmony_ci auto other_addr = other.addr(); 1036bf215546Sopenharmony_ci if (my_addr && other_addr) { 1037bf215546Sopenharmony_ci m_result = my_addr->equal_to(*other_addr); 1038bf215546Sopenharmony_ci } else { 1039bf215546Sopenharmony_ci m_result = !my_addr && !other_addr; 1040bf215546Sopenharmony_ci } 1041bf215546Sopenharmony_ci } 1042bf215546Sopenharmony_ci } 1043bf215546Sopenharmony_ci}; 1044bf215546Sopenharmony_ci 1045bf215546Sopenharmony_civoid ValueComparer::visit(const UniformValue& value) 1046bf215546Sopenharmony_ci{ 1047bf215546Sopenharmony_ci m_result = false; 1048bf215546Sopenharmony_ci if (m_uniform_value) { 1049bf215546Sopenharmony_ci m_result = m_uniform_value->kcache_bank() == value.kcache_bank(); 1050bf215546Sopenharmony_ci if (m_result) { 1051bf215546Sopenharmony_ci auto my_buf_addr = m_uniform_value->buf_addr(); 1052bf215546Sopenharmony_ci auto other_buf_addr = value.buf_addr(); 1053bf215546Sopenharmony_ci if (my_buf_addr && other_buf_addr) { 1054bf215546Sopenharmony_ci m_result = my_buf_addr->equal_to(*other_buf_addr); 1055bf215546Sopenharmony_ci } else { 1056bf215546Sopenharmony_ci m_result = !my_buf_addr && !other_buf_addr; 1057bf215546Sopenharmony_ci } 1058bf215546Sopenharmony_ci } 1059bf215546Sopenharmony_ci } 1060bf215546Sopenharmony_ci}; 1061bf215546Sopenharmony_ci 1062bf215546Sopenharmony_civoid ValueComparer::visit(const LiteralConstant& other) 1063bf215546Sopenharmony_ci{ 1064bf215546Sopenharmony_ci m_result = m_literal_value && (m_literal_value->value() == other.value()); 1065bf215546Sopenharmony_ci}; 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_civoid ValueComparer::visit(const InlineConstant& other) 1068bf215546Sopenharmony_ci{ 1069bf215546Sopenharmony_ci (void)other; 1070bf215546Sopenharmony_ci m_result = !!m_inline_constant; 1071bf215546Sopenharmony_ci}; 1072bf215546Sopenharmony_ci 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci} // namespace r600 1075