• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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