3 * Copyright (c) 2018-2019 Collabora LTD
5 * Author: Gert Wollny <gert.wollny@collabora.com>
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:
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
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.
27 #include "sfn_value_gpr.h"
28 #include "sfn_valuepool.h"
29 #include "sfn_debug.h"
30 #include "sfn_liverange.h"
37 GPRValue::GPRValue(uint32_t sel
, uint32_t chan
, int base_offset
):
38 Value(Value::gpr
, chan
),
40 m_base_offset(base_offset
),
45 GPRValue::GPRValue(uint32_t sel
, uint32_t chan
):
46 Value(Value::gpr
, chan
),
53 uint32_t GPRValue::sel() const
58 void GPRValue::do_print(std::ostream
& os
) const
62 os
<< '.' << component_names
[chan()];
65 bool GPRValue::is_equal_to(const Value
& other
) const
67 assert(other
.type() == Value::Type::gpr
);
68 const auto& rhs
= static_cast<const GPRValue
&>(other
);
69 return (sel() == rhs
.sel() &&
70 chan() == rhs
.chan());
73 void GPRValue::do_print(std::ostream
& os
, UNUSED
const PrintFlags
& flags
) const
77 os
<< '.' << component_names
[chan()];
80 GPRVector::GPRVector(const GPRVector
& orig
):
87 GPRVector::GPRVector(std::array
<PValue
,4> elms
):
92 for (unsigned i
= 0; i
< 4; ++i
)
93 if (!m_elms
[i
] || (m_elms
[i
]->type() != Value::gpr
)) {
94 assert(0 && "GPR vector not valid because element missing or nit a GPR");
97 unsigned sel
= m_elms
[0]->sel();
98 for (unsigned i
= 1; i
< 4; ++i
)
99 if (m_elms
[i
]->sel() != sel
) {
100 assert(0 && "GPR vector not valid because sel is not equal for all elements");
106 GPRVector::GPRVector(uint32_t sel
, std::array
<uint32_t,4> swizzle
):
110 for (int i
= 0; i
< 4; ++i
)
111 m_elms
[i
] = PValue(new GPRValue(sel
, swizzle
[i
]));
114 GPRVector::GPRVector(const GPRVector
& orig
, const std::array
<uint8_t,4>& swizzle
)
116 for (int i
= 0; i
< 4; ++i
)
117 m_elms
[i
] = orig
.reg_i(swizzle
[i
]);
118 m_valid
= orig
.m_valid
;
121 void GPRVector::validate() const
124 uint32_t sel
= m_elms
[0]->sel();
128 for (unsigned i
= 1; i
< 4; ++i
) {
130 if (sel
!= m_elms
[i
]->sel())
137 uint32_t GPRVector::sel() const
141 return m_elms
[0] ? m_elms
[0]->sel() : 999;
144 void GPRVector::set_reg_i(int i
, PValue reg
)
149 void GPRVector::pin_to_channel(int i
)
151 auto& v
= static_cast<GPRValue
&>(*m_elms
[i
]);
155 void GPRVector::do_print(std::ostream
& os
) const
157 os
<< "R" << sel() << ".";
158 for (int i
= 0; i
< 4; ++i
)
159 os
<< (m_elms
[i
] ? component_names
[m_elms
[i
]->chan() < 8 ? m_elms
[i
]->chan() : 8] : '?');
162 void GPRVector::swizzle(const Swizzle
& swz
)
165 for (uint32_t i
= 0; i
< 4; ++i
)
168 m_elms
[i
] = v
[swz
[i
]];
172 bool GPRVector::is_equal_to(const Value
& other
) const
174 if (other
.type() != gpr_vector
) {
179 const GPRVector
& o
= static_cast<const GPRVector
&>(other
);
181 for (int i
= 0; i
< 4; ++i
) {
182 if (*m_elms
[i
] != *o
.m_elms
[i
]) {
183 std::cerr
<< "elm" << i
;
191 GPRArrayValue::GPRArrayValue(PValue value
, PValue addr
, GPRArray
*array
):
192 Value(gpr_array_value
, value
->chan()),
199 GPRArrayValue::GPRArrayValue(PValue value
, GPRArray
*array
):
200 Value(gpr_array_value
, value
->chan()),
206 static const char *swz_char
= "xyzw01_";
208 void GPRArrayValue::do_print(std::ostream
& os
) const
211 os
<< "R" << m_value
->sel();
213 os
<< "[" << *m_addr
<< "] ";
215 os
<< swz_char
[m_value
->chan()];
217 os
<< "(" << *m_array
<< ")";
220 bool GPRArrayValue::is_equal_to(const Value
& other
) const
222 const GPRArrayValue
& v
= static_cast<const GPRArrayValue
&>(other
);
224 return *m_value
== *v
.m_value
&&
225 *m_array
== *v
.m_array
;
228 void GPRArrayValue::record_read(LiverangeEvaluator
& ev
) const
231 ev
.record_read(*m_addr
);
232 unsigned chan
= m_value
->chan();
234 m_array
->record_read(ev
, chan
);
236 ev
.record_read(*m_value
);
239 void GPRArrayValue::record_write(LiverangeEvaluator
& ev
) const
242 ev
.record_read(*m_addr
);
243 unsigned chan
= m_value
->chan();
245 m_array
->record_write(ev
, chan
);
247 ev
.record_write(*m_value
);
250 void GPRArrayValue::reset_value(PValue new_value
)
255 void GPRArrayValue::reset_addr(PValue new_addr
)
261 GPRArray::GPRArray(int base
, int size
, int mask
, int frac
):
264 m_component_mask(mask
),
267 m_values
.resize(size
);
268 for (int i
= 0; i
< size
; ++i
) {
269 for (int j
= 0; j
< 4; ++j
) {
271 m_values
[i
].set_reg_i(j
, PValue(new GPRValue(base
+ i
, j
)));
276 uint32_t GPRArray::sel() const
281 static const char *compchar
= "xyzw";
282 void GPRArray::do_print(std::ostream
& os
) const
284 os
<< "ARRAY[R" << sel() << "..R" << sel() + m_values
.size() - 1 << "].";
285 for (int j
= 0; j
< 4; ++j
) {
286 if (m_component_mask
& (1 << j
))
291 bool GPRArray::is_equal_to(const Value
& other
) const
293 const GPRArray
& o
= static_cast<const GPRArray
&>(other
);
294 return o
.sel() == sel() &&
295 o
.m_values
.size() == m_values
.size() &&
296 o
.m_component_mask
== m_component_mask
;
299 uint32_t GPRArrayValue::sel() const
301 return m_value
->sel();
304 PValue
GPRArray::get_indirect(unsigned index
, PValue indirect
, unsigned component
)
306 assert(index
< m_values
.size());
307 assert(m_component_mask
& (1 << (component
+ m_frac
)));
309 sfn_log
<< SfnLog::reg
<< "Create indirect register from " << *this;
311 PValue v
= m_values
[index
].reg_i(component
+ m_frac
);
314 sfn_log
<< SfnLog::reg
<< " -> " << *v
;
317 sfn_log
<< SfnLog::reg
<< "[" << *indirect
<< "]";
318 switch (indirect
->type()) {
319 case Value::literal
: {
320 const LiteralValue
& lv
= static_cast<const LiteralValue
&>(*indirect
);
321 v
= m_values
[lv
.value()].reg_i(component
+ m_frac
);
325 v
= PValue(new GPRArrayValue(v
, indirect
, this));
326 sfn_log
<< SfnLog::reg
<< "(" << *v
<< ")";
330 assert(0 && !"Indirect addressing must be literal value or GPR");
333 sfn_log
<< SfnLog::reg
<<" -> " << *v
<< "\n";
337 void GPRArray::record_read(LiverangeEvaluator
& ev
, int chan
) const
339 for (auto& v
: m_values
)
340 ev
.record_read(*v
.reg_i(chan
), true);
343 void GPRArray::record_write(LiverangeEvaluator
& ev
, int chan
) const
345 for (auto& v
: m_values
)
346 ev
.record_write(*v
.reg_i(chan
), true);
349 void GPRArray::collect_registers(ValueMap
& output
) const
351 for (auto& v
: m_values
) {
352 for (int i
= 0; i
< 4; ++i
) {
353 auto vv
= v
.reg_i(i
);