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