xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_instr_controlflow.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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