• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2021 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 #pragma once
28 
29 #include "sfn_memorypool.h"
30 #include "sfn_alu_defines.h"
31 #include <memory>
32 #include <vector>
33 #include <iosfwd>
34 #include <map>
35 #include <set>
36 #include <array>
37 #include <cassert>
38 
39 #if __cpp_exceptions >= 199711L
40 #include <exception>
41 #define ASSERT_OR_THROW(EXPR, ERROR) if (!(EXPR))  throw std::invalid_argument(ERROR)
42 #else
43 #define ASSERT_OR_THROW(EXPR, ERROR) if (!(EXPR)) unreachable(ERROR)
44 #endif
45 
46 namespace r600 {
47 
48 enum Pin {
49    pin_none,
50    pin_chan,
51    pin_array,
52    pin_group,
53    pin_chgr,
54    pin_fully,
55    pin_free
56 };
57 
58 std::ostream& operator << (std::ostream& os, Pin pin);
59 
60 class Register;
61 class RegisterVisitor;
62 class ConstRegisterVisitor;
63 class Instr;
64 class InlineConstant;
65 class LiteralConstant;
66 class UniformValue;
67 
68 using InstructionSet = std::set<Instr *, std::less<Instr *>,  Allocator<Instr *>>;
69 
70 class VirtualValue : public Allocate {
71 public:
72 
73    static const uint32_t virtual_register_base = 1024;
74    static const uint32_t clause_temp_registers = 2;
75    static const uint32_t gpr_register_end = 128 - 2 * clause_temp_registers;
76    static const uint32_t clause_temp_register_begin = gpr_register_end;
77    static const uint32_t clause_temp_register_end = 128;
78 
79    static const uint32_t uniforms_begin = 512;
80    static const uint32_t uniforms_end = 640;
81 
82    using Pointer = R600_POINTER_TYPE(VirtualValue);
83 
84    VirtualValue(int sel, int chan, Pin pin);
85    VirtualValue(const VirtualValue& orig) = default;
86 
sel()87    int sel() const { return m_sel; }
chan()88    int chan() const { return m_chan;}
pin()89    Pin pin() const { return m_pins;};
90    bool is_virtual() const;
91 
set_pin(Pin p)92    void set_pin(Pin p) { m_pins = p;}
93 
94 
95    virtual void accept(RegisterVisitor& vistor) = 0;
96    virtual void accept(ConstRegisterVisitor& vistor) const = 0;
97    virtual void print(std::ostream& os) const = 0;
98 
99    bool equal_to(const VirtualValue& other) const;
100    Pointer get_addr() const;
101 
102    static Pointer from_string(const std::string& s);
103 
as_register()104    virtual Register *as_register() { return nullptr;}
as_inline_const()105    virtual InlineConstant * as_inline_const() { return nullptr;}
as_literal()106    virtual LiteralConstant *as_literal() { return nullptr;}
as_uniform()107    virtual UniformValue *as_uniform() { return nullptr;}
108    virtual bool ready(int block, int index) const;
109 
110    static constexpr char chanchar[9] = "xyzw01?_";
111 
112 protected:
do_set_chan(int c)113    void do_set_chan(int c) {m_chan = c;}
set_sel_internal(int sel)114    void set_sel_internal(int sel) { m_sel = sel; }
115 
116 private:
117    uint32_t m_sel;
118    int m_chan;
119    Pin m_pins;
120 };
121 using PVirtualValue = VirtualValue::Pointer;
122 
123 
124 inline std::ostream& operator << (std::ostream& os, const VirtualValue& val)
125 {
126     val.print(os);
127     return os;
128 }
129 
130 inline bool operator == (const VirtualValue& lhs, const VirtualValue& rhs)
131 {
132     return lhs.equal_to(rhs);
133 }
134 
135 struct LiveRange {
LiveRangeLiveRange136    LiveRange(): start(-1), end(-1), is_pinned(false) {}
LiveRangeLiveRange137    LiveRange(int s, int e): start(s), end(e), is_pinned(false) {}
138    int start;
139    int end;
140    int is_pinned;
141 };
142 
143 class Register : public VirtualValue {
144 public:
145     using Pointer = R600_POINTER_TYPE(Register);
146 
147     Register(int sel, int chan, Pin pin);
148     void accept(RegisterVisitor& vistor) override;
149     void accept(ConstRegisterVisitor& vistor) const override;
150     void print(std::ostream& os) const override;
151 
live_start_pinned()152     int live_start_pinned() const { return m_pin_start;}
live_end_pinned()153     int live_end_pinned() const { return m_pin_end;}
154 
155     void pin_live_range(bool start, bool end = false);
156 
157     static Pointer from_string(const std::string& s);
158 
as_register()159     Register *as_register() override { return this;}
160 
161     void set_is_ssa(bool value);
162 
is_ssa()163     bool is_ssa() const { return m_is_ssa;}
164 
165     void add_parent(Instr *instr);
166     void del_parent(Instr *instr);
parents()167     const InstructionSet& parents() const {return m_parents;}
168 
169     bool ready(int block, int index) const override;
170 
uses()171     const InstructionSet& uses() const {return m_uses;}
172     void add_use(Instr *instr);
173     void del_use(Instr *instr);
has_uses()174     bool has_uses() const {return !m_uses.empty() || pin() == pin_array;}
set_chan(int c)175     void set_chan(int c) {do_set_chan(c);}
176 
addr()177     virtual VirtualValue *addr() const { return nullptr;}
178 
index()179     int index() const {return m_index;}
set_index(int idx)180     void set_index(int idx) {m_index = idx;}
181 
set_sel(int new_sel)182     void set_sel(int new_sel) { set_sel_internal(new_sel); m_is_ssa = false;}
183 
184 private:
185     Register(const Register& orig) = delete;
186     Register(const Register&& orig) = delete;
187     Register& operator = (const Register& orig) = delete;
188     Register& operator = (Register&& orig) = delete;
189 
forward_del_use(Instr * instr)190     virtual void forward_del_use(Instr *instr) {(void)instr;}
forward_add_use(Instr * instr)191     virtual void forward_add_use(Instr *instr) {(void)instr;}
192     virtual void add_parent_to_array(Instr *instr);
193     virtual void del_parent_from_array(Instr *instr);
194 
195     InstructionSet m_parents;
196     InstructionSet m_uses;
197 
198     int m_index{-1};
199 
200     bool m_is_ssa {false};
201     bool m_pin_start {false};
202     bool m_pin_end {false};
203 };
204 using PRegister = Register::Pointer;
205 
206 inline std::ostream& operator << (std::ostream& os, const Register& val)
207 {
208     val.print(os);
209     return os;
210 }
211 
212 class InlineConstant : public VirtualValue {
213 public:
214     using Pointer = R600_POINTER_TYPE(InlineConstant);
215 
216     InlineConstant(int sel, int chan = 0);
217 
218     void accept(RegisterVisitor& vistor) override;
219     void accept(ConstRegisterVisitor& vistor) const override;
220     void print(std::ostream& os) const override;
221     static Pointer from_string(const std::string& s);
222 	 static Pointer param_from_string(const std::string& s);
223 
as_inline_const()224     InlineConstant * as_inline_const() override { return this;}
225 private:
226     InlineConstant(const InlineConstant& orig) = default;
227     static std::map<std::string, std::pair<AluInlineConstants, bool>> s_opmap;
228 
229 };
230 using PInlineConstant = InlineConstant::Pointer;
231 
232 inline std::ostream& operator << (std::ostream& os, const InlineConstant& val)
233 {
234     val.print(os);
235     return os;
236 }
237 
238 class RegisterVec4 {
239 public:
240 	using Swizzle = std::array<uint8_t, 4>;
241    RegisterVec4();
242    RegisterVec4(int sel, bool is_ssa = false, const Swizzle& swz = {0,1,2,3}, Pin pin = pin_group);
243    RegisterVec4(PRegister x, PRegister y, PRegister z, PRegister w, Pin pin);
244 
245    RegisterVec4(const RegisterVec4& orig);
246 
247    RegisterVec4(RegisterVec4&& orig) = default;
248    RegisterVec4& operator = (RegisterVec4& orig) = default;
249    RegisterVec4& operator = (RegisterVec4&& orig) = default;
250 
251    void add_use(Instr *instr);
252    void del_use(Instr *instr);
253    bool has_uses() const;
254 
255    int sel() const;
256    void print(std::ostream& os) const;
257 
258    class Element  : public Allocate {
259    public:
260       Element(const RegisterVec4& parent, int chan);
261       Element(const RegisterVec4& parent, PRegister value);
value()262       PRegister value() { return m_value; }
set_value(PRegister reg)263       void set_value(PRegister reg) { m_value = reg;}
264    private:
265       const RegisterVec4& m_parent;
266       PRegister m_value;
267 	};
268 
269 	friend class Element;
270 
271 	PRegister operator [] (int i) const {
272            return m_values[i]->value();
273 	}
274 
275         PRegister operator [] (int i) {
276            return m_values[i]->value();
277         }
278 
set_value(int i,PRegister reg)279         void set_value(int i, PRegister reg) {
280            assert(reg->sel() == m_sel);
281            m_swz[i] = reg->chan();
282            m_values[i]->set_value(reg);
283         }
284 
285         bool ready(int block_id, int index) const;
286 private:
287         int m_sel;
288         Swizzle m_swz;
289         std::array<R600_POINTER_TYPE(Element), 4> m_values;
290 };
291 
292 bool operator == (const RegisterVec4& lhs, const RegisterVec4& rhs);
293 
294 inline bool operator != (const RegisterVec4& lhs, const RegisterVec4& rhs)
295 {
296    return !(lhs == rhs);
297 }
298 
299 inline std::ostream& operator << (std::ostream& os, const RegisterVec4& val)
300 {
301     val.print(os);
302     return os;
303 }
304 
305 
306 class LiteralConstant : public VirtualValue {
307 public:
308    using Pointer = R600_POINTER_TYPE(LiteralConstant);
309 
310    LiteralConstant(uint32_t value);
311    void accept(RegisterVisitor& vistor) override;
312    void accept(ConstRegisterVisitor& vistor) const override;
313    void print(std::ostream& os) const override;
value()314    uint32_t value() const {return m_value;}
315    static Pointer from_string(const std::string& s);
as_literal()316    LiteralConstant *as_literal() override { return this;}
317 
318 private:
319    LiteralConstant(const LiteralConstant& orig) = default;
320    uint32_t m_value;
321 };
322 using PLiteralVirtualValue = LiteralConstant::Pointer;
323 
324 
325 class UniformValue : public VirtualValue {
326 public:
327    using Pointer = R600_POINTER_TYPE(UniformValue);
328 
329    UniformValue(int sel, int chan, int kcache_bank = 0);
330    UniformValue(int sel, int chan, PVirtualValue buf_addr);
331 
332    void accept(RegisterVisitor& vistor) override;
333    void accept(ConstRegisterVisitor& vistor) const override;
334    void print(std::ostream& os) const override;
kcache_bank()335    int kcache_bank() const { return m_kcache_bank; }
336    PVirtualValue buf_addr() const;
as_uniform()337    UniformValue *as_uniform() override { return this;}
338 
339    bool equal_buf_and_cache(const UniformValue& other) const;
340    static Pointer from_string(const std::string& s);
341 
342 private:
343    int m_kcache_bank;
344    PVirtualValue m_buf_addr;
345 };
346 using PUniformVirtualValue = UniformValue::Pointer;
347 
348 inline std::ostream& operator << (std::ostream& os, const UniformValue& val)
349 {
350     val.print(os);
351     return os;
352 }
353 
354 class LocalArrayValue;
355 class LocalArray : public Register {
356 public:
357    using Pointer = R600_POINTER_TYPE(LocalArray);
358    using Values = std::vector<LocalArrayValue *, Allocator<LocalArrayValue *> >;
359 
360    LocalArray(int base_sel, int nchannels, int size, int frac = 0);
361    void accept(RegisterVisitor& vistor) override;
362    void accept(ConstRegisterVisitor& vistor) const override;
363    void print(std::ostream& os) const override;
364    bool ready_for_direct(int block, int index, int chan) const;
365    bool ready_for_indirect(int block, int index, int chan) const;
366 
367    PRegister element(size_t offset, PVirtualValue indirect, uint32_t chan);
368 
369    size_t size() const;
370    uint32_t nchannels() const;
frac()371    uint32_t frac() const { return m_frac;}
372 
373    void add_parent_to_elements(Instr *instr);
374 
375    const Register& operator ()(size_t idx, size_t chan) const;
376 
begin()377    Values::iterator begin() { return m_values.begin();}
end()378    Values::iterator end() { return m_values.end();}
379 
380 private:
381     uint32_t m_base_sel;
382     uint32_t m_nchannels;
383     size_t m_size;
384     Values m_values;
385     Values m_values_indirect;
386     int m_frac;
387 };
388 
389 inline std::ostream& operator << (std::ostream& os, const LocalArray & val)
390 {
391     val.print(os);
392     return os;
393 }
394 
395 class LocalArrayValue : public Register {
396 public:
397     using Pointer = R600_POINTER_TYPE(LocalArrayValue);
398 
399     LocalArrayValue(PRegister reg, LocalArray& array);
400     LocalArrayValue(PRegister reg, PVirtualValue index, LocalArray &array);
401 
402     void accept(RegisterVisitor& vistor) override;
403     void accept(ConstRegisterVisitor& vistor) const override;
404     void print(std::ostream& os) const override;
405     bool ready(int block, int index) const override;
406 
407     VirtualValue *addr() const override;
408     const LocalArray& array() const;
409 private:
410     void forward_del_use(Instr *instr) override;
411     void forward_add_use(Instr *instr) override;
412     void add_parent_to_array(Instr *instr) override;
413     void del_parent_from_array(Instr *instr) override;
414 
415     PVirtualValue m_addr;
416     LocalArray& m_array;
417 };
418 
419 inline std::ostream& operator << (std::ostream& os, const LocalArrayValue& val)
420 {
421     val.print(os);
422     return os;
423 }
424 
425 template <typename T>
sfn_value_equal(const T * lhs,const T * rhs)426 bool sfn_value_equal(const T* lhs, const T* rhs)
427 {
428    if (lhs) {
429       if (!rhs) return
430             false;
431       if ( !lhs->equal_to(*rhs))
432          return false;
433    } else {
434       if (rhs)
435          return false;
436    }
437    return true;
438 }
439 
440 class RegisterVisitor {
441 public:
442     virtual void visit(Register& value) = 0;
443     virtual void visit(LocalArray& value) = 0;
444     virtual void visit(LocalArrayValue& value) = 0;
445     virtual void visit(UniformValue& value) = 0;
446     virtual void visit(LiteralConstant& value) = 0;
447     virtual void visit(InlineConstant& value) = 0;
448 };
449 
450 class ConstRegisterVisitor {
451 public:
452     virtual void visit(const Register& value) = 0;
453     virtual void visit(const LocalArray& value) = 0;
454     virtual void visit(const LocalArrayValue& value) = 0;
455     virtual void visit(const UniformValue& value) = 0;
456     virtual void visit(const LiteralConstant& value) = 0;
457     virtual void visit(const InlineConstant& value) = 0;
458 };
459 
460 }
461 
462