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
]);
152 v
.set_pin_to_channel();
155 void GPRVector::pin_all_to_channel()
157 for (auto& v
: m_elms
) {
158 auto& c
= static_cast<GPRValue
&>(*v
);
159 c
.set_pin_to_channel();
163 void GPRVector::do_print(std::ostream
& os
) const
165 os
<< "R" << sel() << ".";
166 for (int i
= 0; i
< 4; ++i
)
167 os
<< (m_elms
[i
] ? component_names
[m_elms
[i
]->chan() < 8 ? m_elms
[i
]->chan() : 8] : '?');
170 void GPRVector::swizzle(const Swizzle
& swz
)
173 for (uint32_t i
= 0; i
< 4; ++i
)
176 m_elms
[i
] = v
[swz
[i
]];
180 bool GPRVector::is_equal_to(const Value
& other
) const
182 if (other
.type() != gpr_vector
) {
187 const GPRVector
& o
= static_cast<const GPRVector
&>(other
);
189 for (int i
= 0; i
< 4; ++i
) {
190 if (*m_elms
[i
] != *o
.m_elms
[i
]) {
191 std::cerr
<< "elm" << i
;
199 GPRArrayValue::GPRArrayValue(PValue value
, PValue addr
, GPRArray
*array
):
200 Value(gpr_array_value
, value
->chan()),
207 GPRArrayValue::GPRArrayValue(PValue value
, GPRArray
*array
):
208 Value(gpr_array_value
, value
->chan()),
214 static const char *swz_char
= "xyzw01_";
216 void GPRArrayValue::do_print(std::ostream
& os
) const
219 os
<< "R" << m_value
->sel();
221 os
<< "[" << *m_addr
<< "] ";
223 os
<< swz_char
[m_value
->chan()];
225 os
<< "(" << *m_array
<< ")";
228 bool GPRArrayValue::is_equal_to(const Value
& other
) const
230 const GPRArrayValue
& v
= static_cast<const GPRArrayValue
&>(other
);
232 return *m_value
== *v
.m_value
&&
233 *m_array
== *v
.m_array
;
236 void GPRArrayValue::record_read(LiverangeEvaluator
& ev
) const
239 ev
.record_read(*m_addr
);
240 unsigned chan
= m_value
->chan();
242 m_array
->record_read(ev
, chan
);
244 ev
.record_read(*m_value
);
247 void GPRArrayValue::record_write(LiverangeEvaluator
& ev
) const
250 ev
.record_read(*m_addr
);
251 unsigned chan
= m_value
->chan();
253 m_array
->record_write(ev
, chan
);
255 ev
.record_write(*m_value
);
258 void GPRArrayValue::reset_value(PValue new_value
)
263 void GPRArrayValue::reset_addr(PValue new_addr
)
269 GPRArray::GPRArray(int base
, int size
, int mask
, int frac
):
272 m_component_mask(mask
),
275 m_values
.resize(size
);
276 for (int i
= 0; i
< size
; ++i
) {
277 for (int j
= 0; j
< 4; ++j
) {
279 m_values
[i
].set_reg_i(j
, PValue(new GPRValue(base
+ i
, j
)));
284 uint32_t GPRArray::sel() const
289 static const char *compchar
= "xyzw";
290 void GPRArray::do_print(std::ostream
& os
) const
292 os
<< "ARRAY[R" << sel() << "..R" << sel() + m_values
.size() - 1 << "].";
293 for (int j
= 0; j
< 4; ++j
) {
294 if (m_component_mask
& (1 << j
))
299 bool GPRArray::is_equal_to(const Value
& other
) const
301 const GPRArray
& o
= static_cast<const GPRArray
&>(other
);
302 return o
.sel() == sel() &&
303 o
.m_values
.size() == m_values
.size() &&
304 o
.m_component_mask
== m_component_mask
;
307 uint32_t GPRArrayValue::sel() const
309 return m_value
->sel();
312 PValue
GPRArray::get_indirect(unsigned index
, PValue indirect
, unsigned component
)
314 assert(index
< m_values
.size());
315 assert(m_component_mask
& (1 << (component
+ m_frac
)));
317 sfn_log
<< SfnLog::reg
<< "Create indirect register from " << *this;
319 PValue v
= m_values
[index
].reg_i(component
+ m_frac
);
322 sfn_log
<< SfnLog::reg
<< " -> " << *v
;
325 sfn_log
<< SfnLog::reg
<< "[" << *indirect
<< "]";
326 switch (indirect
->type()) {
327 case Value::literal
: {
328 const LiteralValue
& lv
= static_cast<const LiteralValue
&>(*indirect
);
329 v
= m_values
[lv
.value()].reg_i(component
+ m_frac
);
333 v
= PValue(new GPRArrayValue(v
, indirect
, this));
334 sfn_log
<< SfnLog::reg
<< "(" << *v
<< ")";
338 assert(0 && !"Indirect addressing must be literal value or GPR");
341 sfn_log
<< SfnLog::reg
<<" -> " << *v
<< "\n";
345 void GPRArray::record_read(LiverangeEvaluator
& ev
, int chan
) const
347 for (auto& v
: m_values
)
348 ev
.record_read(*v
.reg_i(chan
), true);
351 void GPRArray::record_write(LiverangeEvaluator
& ev
, int chan
) const
353 for (auto& v
: m_values
)
354 ev
.record_write(*v
.reg_i(chan
), true);
357 void GPRArray::collect_registers(ValueMap
& output
) const
359 for (auto& v
: m_values
) {
360 for (int i
= 0; i
< 4; ++i
) {
361 auto vv
= v
.reg_i(i
);