Home | History | Annotate | Line # | Download | only in sfn
      1 /* -*- mesa-c++  -*-
      2  *
      3  * Copyright (c) 2018-2019 Collabora LTD
      4  *
      5  * Author: Gert Wollny <gert.wollny (at) 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 
     32 namespace r600 {
     33 
     34 using std::vector;
     35 using std::array;
     36 
     37 GPRValue::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 
     47 GPRValue::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 
     57 uint32_t GPRValue::sel() const
     58 {
     59    return m_sel;
     60 }
     61 
     62 void GPRValue::do_print(std::ostream& os) const
     63 {
     64    os << 'R';
     65    os << m_sel;
     66    os << '.' << component_names[chan()];
     67 }
     68 
     69 bool 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 
     77 void 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 
     84 GPRVector::GPRVector(const GPRVector& orig):
     85    Value(gpr_vector),
     86    m_elms(orig.m_elms),
     87    m_valid(orig.m_valid)
     88 {
     89 }
     90 
     91 GPRVector::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 
    110 GPRVector::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 
    118 GPRVector::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 
    125 void 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 
    141 uint32_t GPRVector::sel() const
    142 {
    143    validate();
    144    assert(m_valid);
    145    return m_elms[0] ? m_elms[0]->sel() : 999;
    146 }
    147 
    148 void GPRVector::set_reg_i(int i, PValue reg)
    149 {
    150    m_elms[i] = reg;
    151 }
    152 
    153 void GPRVector::pin_to_channel(int i)
    154 {
    155    auto& v = static_cast<GPRValue&>(*m_elms[i]);
    156    v.set_pin_to_channel();
    157 }
    158 
    159 void 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 
    167 void 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 
    174 void 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 
    184 bool 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 
    203 GPRArrayValue::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 
    211 GPRArrayValue::GPRArrayValue(PValue value, GPRArray *array):
    212    Value(gpr_array_value, value->chan()),
    213    m_value(value),
    214    m_array(array)
    215 {
    216 }
    217 
    218 static const char *swz_char = "xyzw01_";
    219 
    220 void 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 
    232 bool 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 
    240 void 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 
    251 void 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 
    262 void GPRArrayValue::reset_value(PValue new_value)
    263 {
    264    m_value = new_value;
    265 }
    266 
    267 void GPRArrayValue::reset_addr(PValue new_addr)
    268 {
    269    m_addr = new_addr;
    270 }
    271 
    272 
    273 GPRArray::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 
    296 uint32_t GPRArray::sel() const
    297 {
    298    return m_base_index;
    299 }
    300 
    301 static const char *compchar = "xyzw";
    302 void 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 
    311 bool 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 
    319 uint32_t GPRArrayValue::sel() const
    320 {
    321    return m_value->sel();
    322 }
    323 
    324 PValue 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 
    357 void 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 
    363 void 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 
    369 void 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