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::do_print(std::ostream
& os
) const
151 os
<< "R" << sel() << ".";
152 for (int i
= 0; i
< 4; ++i
)
153 os
<< (m_elms
[i
] ? component_names
[m_elms
[i
]->chan() < 8 ? m_elms
[i
]->chan() : 8] : '?');
156 void GPRVector::swizzle(const Swizzle
& swz
)
159 for (uint32_t i
= 0; i
< 4; ++i
)
162 m_elms
[i
] = v
[swz
[i
]];
166 bool GPRVector::is_equal_to(const Value
& other
) const
168 if (other
.type() != gpr_vector
) {
173 const GPRVector
& o
= static_cast<const GPRVector
&>(other
);
175 for (int i
= 0; i
< 4; ++i
) {
176 if (*m_elms
[i
] != *o
.m_elms
[i
]) {
177 std::cerr
<< "elm" << i
;
185 GPRArrayValue::GPRArrayValue(PValue value
, PValue addr
, GPRArray
*array
):
186 Value(gpr_array_value
, value
->chan()),
193 GPRArrayValue::GPRArrayValue(PValue value
, GPRArray
*array
):
194 Value(gpr_array_value
, value
->chan()),
200 static const char *swz_char
= "xyzw01_";
202 void GPRArrayValue::do_print(std::ostream
& os
) const
205 os
<< "R" << m_value
->sel();
207 os
<< "[" << *m_addr
<< "] ";
209 os
<< swz_char
[m_value
->chan()];
211 os
<< "(" << *m_array
<< ")";
214 bool GPRArrayValue::is_equal_to(const Value
& other
) const
216 const GPRArrayValue
& v
= static_cast<const GPRArrayValue
&>(other
);
218 return *m_value
== *v
.m_value
&&
219 *m_array
== *v
.m_array
;
222 void GPRArrayValue::record_read(LiverangeEvaluator
& ev
) const
225 ev
.record_read(*m_addr
);
226 unsigned chan
= m_value
->chan();
228 m_array
->record_read(ev
, chan
);
230 ev
.record_read(*m_value
);
233 void GPRArrayValue::record_write(LiverangeEvaluator
& ev
) const
236 ev
.record_read(*m_addr
);
237 unsigned chan
= m_value
->chan();
239 m_array
->record_write(ev
, chan
);
241 ev
.record_write(*m_value
);
244 void GPRArrayValue::reset_value(PValue new_value
)
249 void GPRArrayValue::reset_addr(PValue new_addr
)
255 GPRArray::GPRArray(int base
, int size
, int mask
, int frac
):
258 m_component_mask(mask
),
261 m_values
.resize(size
);
262 for (int i
= 0; i
< size
; ++i
) {
263 for (int j
= 0; j
< 4; ++j
) {
265 m_values
[i
].set_reg_i(j
, PValue(new GPRValue(base
+ i
, j
)));
270 uint32_t GPRArray::sel() const
275 static const char *compchar
= "xyzw";
276 void GPRArray::do_print(std::ostream
& os
) const
278 os
<< "ARRAY[R" << sel() << "..R" << sel() + m_values
.size() - 1 << "].";
279 for (int j
= 0; j
< 4; ++j
) {
280 if (m_component_mask
& (1 << j
))
285 bool GPRArray::is_equal_to(const Value
& other
) const
287 const GPRArray
& o
= dynamic_cast<const GPRArray
&>(other
);
288 return o
.sel() == sel() &&
289 o
.m_values
.size() == m_values
.size() &&
290 o
.m_component_mask
== m_component_mask
;
293 uint32_t GPRArrayValue::sel() const
295 return m_value
->sel();
298 PValue
GPRArray::get_indirect(unsigned index
, PValue indirect
, unsigned component
)
300 assert(index
< m_values
.size());
301 assert(m_component_mask
& (1 << (component
+ m_frac
)));
303 sfn_log
<< SfnLog::reg
<< "Create indirect register from " << *this;
305 PValue v
= m_values
[index
].reg_i(component
+ m_frac
);
308 sfn_log
<< SfnLog::reg
<< " -> " << *v
;
311 sfn_log
<< SfnLog::reg
<< "[" << *indirect
<< "]";
312 switch (indirect
->type()) {
313 case Value::literal
: {
314 const LiteralValue
& lv
= static_cast<const LiteralValue
&>(*indirect
);
315 v
= m_values
[lv
.value()].reg_i(component
+ m_frac
);
319 v
= PValue(new GPRArrayValue(v
, indirect
, this));
320 sfn_log
<< SfnLog::reg
<< "(" << *v
<< ")";
324 assert(0 && !"Indirect addressing must be literal value or GPR");
327 sfn_log
<< SfnLog::reg
<<" -> " << *v
<< "\n";
331 void GPRArray::record_read(LiverangeEvaluator
& ev
, int chan
) const
333 for (auto& v
: m_values
)
334 ev
.record_read(*v
.reg_i(chan
), true);
337 void GPRArray::record_write(LiverangeEvaluator
& ev
, int chan
) const
339 for (auto& v
: m_values
)
340 ev
.record_write(*v
.reg_i(chan
), true);
343 void GPRArray::collect_registers(ValueMap
& output
) const
345 for (auto& v
: m_values
) {
346 for (int i
= 0; i
< 4; ++i
) {
347 auto vv
= v
.reg_i(i
);