1 /* -*- mesa-c++ -*-
2 * Copyright 2022 Collabora LTD
3 * Author: Gert Wollny <[email protected]>
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "sfn_instr_controlflow.h"
8
9 #include <sstream>
10
11 namespace r600 {
12
ControlFlowInstr(CFType type)13 ControlFlowInstr::ControlFlowInstr(CFType type):
14 m_type(type)
15 {
16 }
17
18 bool
do_ready() const19 ControlFlowInstr::do_ready() const
20 {
21 /* Have to rework this, but the CF should always */
22 return true;
23 }
24
25 bool
is_equal_to(const ControlFlowInstr & rhs) const26 ControlFlowInstr::is_equal_to(const ControlFlowInstr& rhs) const
27 {
28 return m_type == rhs.m_type;
29 }
30
31 void
accept(ConstInstrVisitor & visitor) const32 ControlFlowInstr::accept(ConstInstrVisitor& visitor) const
33 {
34 visitor.visit(*this);
35 }
36
37 void
accept(InstrVisitor & visitor)38 ControlFlowInstr::accept(InstrVisitor& visitor)
39 {
40 visitor.visit(this);
41 }
42
43 void
do_print(std::ostream & os) const44 ControlFlowInstr::do_print(std::ostream& os) const
45 {
46 switch (m_type) {
47 case cf_else:
48 os << "ELSE";
49 break;
50 case cf_endif:
51 os << "ENDIF";
52 break;
53 case cf_loop_begin:
54 os << "LOOP_BEGIN";
55 break;
56 case cf_loop_end:
57 os << "LOOP_END";
58 break;
59 case cf_loop_break:
60 os << "BREAK";
61 break;
62 case cf_loop_continue:
63 os << "CONTINUE";
64 break;
65 case cf_wait_ack:
66 os << "WAIT_ACK";
67 break;
68 default:
69 unreachable("Unknown CF type");
70 }
71 }
72
73 Instr::Pointer
from_string(std::string type_str)74 ControlFlowInstr::from_string(std::string type_str)
75 {
76 if (type_str == "ELSE")
77 return new ControlFlowInstr(cf_else);
78 else if (type_str == "ENDIF")
79 return new ControlFlowInstr(cf_endif);
80 else if (type_str == "LOOP_BEGIN")
81 return new ControlFlowInstr(cf_loop_begin);
82 else if (type_str == "LOOP_END")
83 return new ControlFlowInstr(cf_loop_end);
84 else if (type_str == "BREAK")
85 return new ControlFlowInstr(cf_loop_break);
86 else if (type_str == "CONTINUE")
87 return new ControlFlowInstr(cf_loop_continue);
88 else if (type_str == "WAIT_ACK")
89 return new ControlFlowInstr(cf_wait_ack);
90 else
91 return nullptr;
92 }
93
94 int
nesting_corr() const95 ControlFlowInstr::nesting_corr() const
96 {
97 switch (m_type) {
98 case cf_else:
99 case cf_endif:
100 case cf_loop_end:
101 return -1;
102 default:
103 return 0;
104 }
105 }
106
107 int
nesting_offset() const108 ControlFlowInstr::nesting_offset() const
109 {
110 switch (m_type) {
111 case cf_endif:
112 case cf_loop_end:
113 return -1;
114 case cf_loop_begin:
115 return 1;
116 default:
117 return 0;
118 }
119 }
120
IfInstr(AluInstr * pred)121 IfInstr::IfInstr(AluInstr *pred):
122 m_predicate(pred)
123 {
124 assert(pred);
125 }
126
IfInstr(const IfInstr & orig)127 IfInstr::IfInstr(const IfInstr& orig) { m_predicate = new AluInstr(*orig.m_predicate); }
128
129 bool
is_equal_to(const IfInstr & rhs) const130 IfInstr::is_equal_to(const IfInstr& rhs) const
131 {
132 return m_predicate->equal_to(*rhs.m_predicate);
133 }
134
slots() const135 uint32_t IfInstr::slots() const
136 {
137 /* If we have a literal value in the predicate evaluation, then
138 * we need at most two alu slots, otherwise it's just one. */
139 for (auto s : m_predicate->sources())
140 if (s->as_literal())
141 return 2;
142 return 1;
143 };
144
145 void
accept(ConstInstrVisitor & visitor) const146 IfInstr::accept(ConstInstrVisitor& visitor) const
147 {
148 visitor.visit(*this);
149 }
150
151 void
accept(InstrVisitor & visitor)152 IfInstr::accept(InstrVisitor& visitor)
153 {
154 visitor.visit(this);
155 }
156
157 bool
replace_source(PRegister old_src,PVirtualValue new_src)158 IfInstr::replace_source(PRegister old_src, PVirtualValue new_src)
159 {
160 return m_predicate->replace_source(old_src, new_src);
161 }
162
163 bool
do_ready() const164 IfInstr::do_ready() const
165 {
166 return m_predicate->ready();
167 }
168
169 void
forward_set_scheduled()170 IfInstr::forward_set_scheduled()
171 {
172 m_predicate->set_scheduled();
173 }
174
175 void
forward_set_blockid(int id,int index)176 IfInstr::forward_set_blockid(int id, int index)
177 {
178 m_predicate->set_blockid(id, index);
179 }
180
181 void
do_print(std::ostream & os) const182 IfInstr::do_print(std::ostream& os) const
183 {
184 os << "IF (( " << *m_predicate << " ))";
185 }
186
187 void
set_predicate(AluInstr * new_predicate)188 IfInstr::set_predicate(AluInstr *new_predicate)
189 {
190 m_predicate = new_predicate;
191 m_predicate->set_blockid(block_id(), index());
192 }
193
194 Instr::Pointer
from_string(std::istream & is,ValueFactory & value_factory,bool is_cayman)195 IfInstr::from_string(std::istream& is, ValueFactory& value_factory, bool is_cayman)
196 {
197 std::string pred_start;
198 is >> pred_start;
199 if (pred_start != "((")
200 return nullptr;
201 char buf[2048];
202
203 is.get(buf, 2048, ')');
204 std::string pred_end;
205 is >> pred_end;
206
207 if (pred_end != "))") {
208 return nullptr;
209 }
210
211 std::istringstream bufstr(buf);
212
213 std::string instr_type;
214 bufstr >> instr_type;
215
216 if (instr_type != "ALU")
217 return nullptr;
218
219 auto pred = AluInstr::from_string(bufstr, value_factory, nullptr, is_cayman);
220 return new IfInstr(static_cast<AluInstr *>(pred));
221 }
222
223 } // namespace r600
224