1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2018 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@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
28 #include <algorithm>
29 #include <cassert>
30
31 #include "sfn_instruction_base.h"
32 #include "sfn_liverange.h"
33 #include "sfn_valuepool.h"
34
35 namespace r600 {
36
ValueRemapper(std::vector<rename_reg_pair> & m,ValueMap & values)37 ValueRemapper::ValueRemapper(std::vector<rename_reg_pair>& m,
38 ValueMap& values):
39 m_map(m),
40 m_values(values)
41 {
42 }
43
remap(PValue & v)44 void ValueRemapper::remap(PValue& v)
45 {
46 if (!v)
47 return;
48 if (v->type() == Value::gpr) {
49 v = remap_one_registers(v);
50 } else if (v->type() == Value::gpr_array_value) {
51 GPRArrayValue& val = static_cast<GPRArrayValue&>(*v);
52 auto value = val.value();
53 auto addr = val.indirect();
54 val.reset_value(remap_one_registers(value));
55 if (addr) {
56 if (addr->type() == Value::gpr)
57 val.reset_addr(remap_one_registers(addr));
58 }
59 size_t range_start = val.sel();
60 size_t range_end = range_start + val.array_size();
61 while (range_start < range_end)
62 m_map[range_start++].used = true;
63 } else if (v->type() == Value::kconst) {
64 auto& val = static_cast<UniformValue&>(*v);
65 auto addr = val.addr();
66 if (addr && addr->type() == Value::gpr)
67 val.reset_addr(remap_one_registers(addr));
68 }
69
70 }
71
remap(GPRVector & v)72 void ValueRemapper::remap(GPRVector& v)
73 {
74 for (int i = 0; i < 4; ++i) {
75 if (v.reg_i(i)) {
76 auto& ns_idx = m_map[v.reg_i(i)->sel()];
77 if (ns_idx.valid)
78 v.set_reg_i(i,m_values.get_or_inject(ns_idx.new_reg, v.reg_i(i)->chan()));
79 m_map[v.reg_i(i)->sel()].used = true;
80 }
81 }
82 }
83
remap_one_registers(PValue & reg)84 PValue ValueRemapper::remap_one_registers(PValue& reg)
85 {
86 auto new_index = m_map[reg->sel()];
87 if (new_index.valid)
88 reg = m_values.get_or_inject(new_index.new_reg, reg->chan());
89 m_map[reg->sel()].used = true;
90 return reg;
91 }
92
93
Instruction(instr_type t)94 Instruction::Instruction(instr_type t):
95 m_type(t)
96 {
97 }
98
~Instruction()99 Instruction::~Instruction()
100 {
101 }
102
print(std::ostream & os) const103 void Instruction::print(std::ostream& os) const
104 {
105 os << "OP:";
106 do_print(os);
107 }
108
109
remap_registers(ValueRemapper & map)110 void Instruction::remap_registers(ValueRemapper& map)
111 {
112 sfn_log << SfnLog::merge << "REMAP " << *this << "\n";
113 for (auto& v: m_mappable_src_registers)
114 map.remap(*v);
115
116 for (auto& v: m_mappable_src_vectors)
117 map.remap(*v);
118
119 for (auto& v: m_mappable_dst_registers)
120 map.remap(*v);
121
122 for (auto& v: m_mappable_dst_vectors)
123 map.remap(*v);
124 sfn_log << SfnLog::merge << "TO " << *this << "\n\n";
125 }
126
add_remappable_src_value(PValue * v)127 void Instruction::add_remappable_src_value(PValue *v)
128 {
129 if (*v)
130 m_mappable_src_registers.push_back(v);
131 }
132
add_remappable_src_value(GPRVector * v)133 void Instruction::add_remappable_src_value(GPRVector *v)
134 {
135 m_mappable_src_vectors.push_back(v);
136 }
137
add_remappable_dst_value(PValue * v)138 void Instruction::add_remappable_dst_value(PValue *v)
139 {
140 if (v)
141 m_mappable_dst_registers.push_back(v);
142 }
143
add_remappable_dst_value(GPRVector * v)144 void Instruction::add_remappable_dst_value(GPRVector *v)
145 {
146 m_mappable_dst_vectors.push_back(v);
147 }
148
replace_values(UNUSED const ValueSet & candidates,UNUSED PValue new_value)149 void Instruction::replace_values(UNUSED const ValueSet& candidates, UNUSED PValue new_value)
150 {
151
152 }
153
evalue_liveness(LiverangeEvaluator & eval) const154 void Instruction::evalue_liveness(LiverangeEvaluator& eval) const
155 {
156 sfn_log << SfnLog::merge << "Scan " << *this << "\n";
157 for (const auto& s: m_mappable_src_registers)
158 if (*s)
159 eval.record_read(**s);
160
161 for (const auto& s: m_mappable_src_vectors)
162 eval.record_read(*s);
163
164 for (const auto& s: m_mappable_dst_registers)
165 if (*s)
166 eval.record_write(**s);
167
168 for (const auto& s: m_mappable_dst_vectors)
169 eval.record_write(*s);
170
171 do_evalue_liveness(eval);
172 }
173
do_evalue_liveness(UNUSED LiverangeEvaluator & eval) const174 void Instruction::do_evalue_liveness(UNUSED LiverangeEvaluator& eval) const
175 {
176
177 }
178
operator ==(const Instruction & lhs,const Instruction & rhs)179 bool operator == (const Instruction& lhs, const Instruction& rhs)
180 {
181 if (rhs.m_type != lhs.m_type)
182 return false;
183
184 return lhs.is_equal_to(rhs);
185 }
186
187 }
188