1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2022 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 #include "sfn_instr_controlflow.h"
28
29 #include <sstream>
30
31 namespace r600 {
32
ControlFlowInstr(CFType type)33 ControlFlowInstr::ControlFlowInstr(CFType type):
34 m_type(type)
35 {
36 }
37
38 bool
do_ready() const39 ControlFlowInstr::do_ready() const
40 {
41 /* Have to rework this, but the CF should always */
42 return true;
43 }
44
45 bool
is_equal_to(const ControlFlowInstr & rhs) const46 ControlFlowInstr::is_equal_to(const ControlFlowInstr& rhs) const
47 {
48 return m_type == rhs.m_type;
49 }
50
51 void
accept(ConstInstrVisitor & visitor) const52 ControlFlowInstr::accept(ConstInstrVisitor& visitor) const
53 {
54 visitor.visit(*this);
55 }
56
57 void
accept(InstrVisitor & visitor)58 ControlFlowInstr::accept(InstrVisitor& visitor)
59 {
60 visitor.visit(this);
61 }
62
63 void
do_print(std::ostream & os) const64 ControlFlowInstr::do_print(std::ostream& os) const
65 {
66 switch (m_type) {
67 case cf_else:
68 os << "ELSE";
69 break;
70 case cf_endif:
71 os << "ENDIF";
72 break;
73 case cf_loop_begin:
74 os << "LOOP_BEGIN";
75 break;
76 case cf_loop_end:
77 os << "LOOP_END";
78 break;
79 case cf_loop_break:
80 os << "BREAK";
81 break;
82 case cf_loop_continue:
83 os << "CONTINUE";
84 break;
85 case cf_wait_ack:
86 os << "WAIT_ACK";
87 break;
88 default:
89 unreachable("Unknown CF type");
90 }
91 }
92
93 Instr::Pointer
from_string(std::string type_str)94 ControlFlowInstr::from_string(std::string type_str)
95 {
96 if (type_str == "ELSE")
97 return new ControlFlowInstr(cf_else);
98 else if (type_str == "ENDIF")
99 return new ControlFlowInstr(cf_endif);
100 else if (type_str == "LOOP_BEGIN")
101 return new ControlFlowInstr(cf_loop_begin);
102 else if (type_str == "LOOP_END")
103 return new ControlFlowInstr(cf_loop_end);
104 else if (type_str == "BREAK")
105 return new ControlFlowInstr(cf_loop_break);
106 else if (type_str == "CONTINUE")
107 return new ControlFlowInstr(cf_loop_continue);
108 else if (type_str == "WAIT_ACK")
109 return new ControlFlowInstr(cf_wait_ack);
110 else
111 return nullptr;
112 }
113
114 int
nesting_corr() const115 ControlFlowInstr::nesting_corr() const
116 {
117 switch (m_type) {
118 case cf_else:
119 case cf_endif:
120 case cf_loop_end:
121 return -1;
122 default:
123 return 0;
124 }
125 }
126
127 int
nesting_offset() const128 ControlFlowInstr::nesting_offset() const
129 {
130 switch (m_type) {
131 case cf_endif:
132 case cf_loop_end:
133 return -1;
134 case cf_loop_begin:
135 return 1;
136 default:
137 return 0;
138 }
139 }
140
IfInstr(AluInstr * pred)141 IfInstr::IfInstr(AluInstr *pred):
142 m_predicate(pred)
143 {
144 assert(pred);
145 }
146
IfInstr(const IfInstr & orig)147 IfInstr::IfInstr(const IfInstr& orig) { m_predicate = new AluInstr(*orig.m_predicate); }
148
149 bool
is_equal_to(const IfInstr & rhs) const150 IfInstr::is_equal_to(const IfInstr& rhs) const
151 {
152 return m_predicate->equal_to(*rhs.m_predicate);
153 }
154
slots() const155 uint32_t IfInstr::slots() const
156 {
157 /* If we hava a literal value in the predicate evaluation, then
158 * we need at most two alu slots, otherwise it's just one. */
159 for (auto s : m_predicate->sources())
160 if (s->as_literal())
161 return 2;
162 return 1;
163 };
164
165 void
accept(ConstInstrVisitor & visitor) const166 IfInstr::accept(ConstInstrVisitor& visitor) const
167 {
168 visitor.visit(*this);
169 }
170
171 void
accept(InstrVisitor & visitor)172 IfInstr::accept(InstrVisitor& visitor)
173 {
174 visitor.visit(this);
175 }
176
177 bool
replace_source(PRegister old_src,PVirtualValue new_src)178 IfInstr::replace_source(PRegister old_src, PVirtualValue new_src)
179 {
180 return m_predicate->replace_source(old_src, new_src);
181 }
182
183 bool
do_ready() const184 IfInstr::do_ready() const
185 {
186 return m_predicate->ready();
187 }
188
189 void
forward_set_scheduled()190 IfInstr::forward_set_scheduled()
191 {
192 m_predicate->set_scheduled();
193 }
194
195 void
forward_set_blockid(int id,int index)196 IfInstr::forward_set_blockid(int id, int index)
197 {
198 m_predicate->set_blockid(id, index);
199 }
200
201 void
do_print(std::ostream & os) const202 IfInstr::do_print(std::ostream& os) const
203 {
204 os << "IF (( " << *m_predicate << " ))";
205 }
206
207 void
set_predicate(AluInstr * new_predicate)208 IfInstr::set_predicate(AluInstr *new_predicate)
209 {
210 m_predicate = new_predicate;
211 m_predicate->set_blockid(block_id(), index());
212 }
213
214 Instr::Pointer
from_string(std::istream & is,ValueFactory & value_factory,bool is_cayman)215 IfInstr::from_string(std::istream& is, ValueFactory& value_factory, bool is_cayman)
216 {
217 std::string pred_start;
218 is >> pred_start;
219 if (pred_start != "((")
220 return nullptr;
221 char buf[2048];
222
223 is.get(buf, 2048, ')');
224 std::string pred_end;
225 is >> pred_end;
226
227 if (pred_end != "))") {
228 return nullptr;
229 }
230
231 std::istringstream bufstr(buf);
232
233 std::string instr_type;
234 bufstr >> instr_type;
235
236 if (instr_type != "ALU")
237 return nullptr;
238
239 auto pred = AluInstr::from_string(bufstr, value_factory, nullptr, is_cayman);
240 return new IfInstr(static_cast<AluInstr *>(pred));
241 }
242
243 } // namespace r600
244