Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *      Vadim Girlin
  25.  */
  26.  
  27. #ifndef R600_SB_IR_H_
  28. #define R600_SB_IR_H_
  29.  
  30. #include <algorithm>
  31. #include <stdint.h>
  32. #include <vector>
  33. #include <set>
  34. #include <algorithm>
  35.  
  36. #include "sb_bc.h"
  37.  
  38. namespace r600_sb {
  39.  
  40. enum special_regs {
  41.         SV_ALU_PRED = 128,
  42.         SV_EXEC_MASK,
  43.         SV_AR_INDEX,
  44.         SV_VALID_MASK
  45. };
  46.  
  47. class node;
  48. class value;
  49. class shader;
  50.  
  51. struct sel_chan
  52. {
  53.         unsigned id;
  54.  
  55.         sel_chan(unsigned id = 0) : id(id) {}
  56.         sel_chan(unsigned sel, unsigned chan) : id(((sel << 2) | chan) + 1) {}
  57.  
  58.         unsigned sel() const { return sel(id); }
  59.         unsigned chan() const {return chan(id); }
  60.         operator unsigned() const {return id;}
  61.  
  62.         static unsigned sel(unsigned idx) { return (idx-1) >> 2; }
  63.         static unsigned chan(unsigned idx) { return (idx-1) & 3; }
  64. };
  65.  
  66. inline sb_ostream& operator <<(sb_ostream& o, sel_chan r) {
  67.         static const char * ch = "xyzw";
  68.         o << r.sel() << "." << ch[r.chan()];
  69.         return o;
  70. }
  71.  
  72. typedef std::vector<value*>  vvec;
  73.  
  74. class sb_pool {
  75. protected:
  76.         static const unsigned SB_POOL_ALIGN = 8;
  77.         static const unsigned SB_POOL_DEFAULT_BLOCK_SIZE = (1 << 16);
  78.  
  79.         typedef std::vector<void*> block_vector;
  80.  
  81.         unsigned block_size;
  82.         block_vector blocks;
  83.         unsigned total_size;
  84.  
  85. public:
  86.         sb_pool(unsigned block_size = SB_POOL_DEFAULT_BLOCK_SIZE)
  87.                 : block_size(block_size), blocks(), total_size() {}
  88.  
  89.         virtual ~sb_pool() { free_all(); }
  90.  
  91.         void* allocate(unsigned sz);
  92.  
  93. protected:
  94.         void free_all();
  95. };
  96.  
  97. template <typename V, typename Comp = std::less<V> >
  98. class sb_set {
  99.         typedef std::vector<V> data_vector;
  100.         data_vector vec;
  101. public:
  102.  
  103.         typedef typename data_vector::iterator iterator;
  104.         typedef typename data_vector::const_iterator const_iterator;
  105.  
  106.         sb_set() : vec() {}
  107.         ~sb_set() {  }
  108.  
  109.         iterator begin() { return vec.begin(); }
  110.         iterator end() { return vec.end(); }
  111.         const_iterator begin() const { return vec.begin(); }
  112.         const_iterator end() const { return vec.end(); }
  113.  
  114.         void add_set(const sb_set& s) {
  115.                 data_vector t;
  116.                 t.reserve(vec.size() + s.vec.size());
  117.                 std::set_union(vec.begin(), vec.end(), s.vec.begin(), s.vec.end(),
  118.                           std::inserter(t, t.begin()), Comp());
  119.                 vec.swap(t);
  120.         }
  121.  
  122.         iterator lower_bound(const V& v) {
  123.                 return std::lower_bound(vec.begin(), vec.end(), v, Comp());
  124.         }
  125.  
  126.         std::pair<iterator, bool> insert(const V& v) {
  127.                 iterator P = lower_bound(v);
  128.                 if (P != vec.end() && is_equal(*P, v))
  129.                         return std::make_pair(P, false);
  130.                 return std::make_pair(vec.insert(P, v), true);
  131.         }
  132.  
  133.         unsigned erase(const V&  v) {
  134.                 iterator P = lower_bound(v);
  135.                 if (P == vec.end() || !is_equal(*P, v))
  136.                         return 0;
  137.                 vec.erase(P);
  138.                 return 1;
  139.         }
  140.  
  141.         void clear() { vec.clear(); }
  142.  
  143.         bool empty() { return vec.empty(); }
  144.  
  145.         bool is_equal(const V& v1, const V& v2) {
  146.                 return !Comp()(v1, v2) && !Comp()(v2, v1);
  147.         }
  148.  
  149.         iterator find(const V& v) {
  150.                 iterator P = lower_bound(v);
  151.                 return (P != vec.end() && is_equal(*P, v)) ? P : vec.end();
  152.         }
  153.  
  154.         unsigned size() { return vec.size(); }
  155.         void erase(iterator I) { vec.erase(I); }
  156. };
  157.  
  158. template <typename K, typename V, typename KComp = std::less<K> >
  159. class sb_map {
  160.         typedef std::pair<K, V> datatype;
  161.  
  162.         struct Comp {
  163.                 bool operator()(const datatype &v1, const datatype &v2) {
  164.                         return KComp()(v1.first, v2.first);
  165.                 }
  166.         };
  167.  
  168.         typedef sb_set<datatype, Comp> dataset;
  169.  
  170.         dataset set;
  171.  
  172. public:
  173.  
  174.         sb_map() : set() {}
  175.  
  176.         typedef typename dataset::iterator iterator;
  177.  
  178.         iterator begin() { return set.begin(); }
  179.         iterator end() { return set.end(); }
  180.  
  181.         void clear() { set.clear(); }
  182.  
  183.         V& operator[](const K& key) {
  184.                 datatype P = std::make_pair(key, V());
  185.                 iterator F = set.find(P);
  186.                 if (F == set.end()) {
  187.                         return (*(set.insert(P).first)).second;
  188.                 } else {
  189.                         return (*F).second;
  190.                 }
  191.         }
  192.  
  193.         std::pair<iterator, bool> insert(const datatype& d) {
  194.                 return set.insert(d);
  195.         }
  196.  
  197.         iterator find(const K& key) {
  198.                 return set.find(std::make_pair(key, V()));
  199.         }
  200.  
  201.         unsigned erase(const K& key) {
  202.                 return set.erase(std::make_pair(key, V()));
  203.         }
  204.  
  205.         void erase(iterator I) {
  206.                 set.erase(I);
  207.         }
  208. };
  209.  
  210. class sb_bitset {
  211.         typedef uint32_t basetype;
  212.         static const unsigned bt_bits = sizeof(basetype) << 3;
  213.         std::vector<basetype> data;
  214.         unsigned bit_size;
  215.  
  216. public:
  217.  
  218.         sb_bitset() : data(), bit_size() {}
  219.  
  220.         bool get(unsigned id);
  221.         void set(unsigned id, bool bit = true);
  222.         bool set_chk(unsigned id, bool bit = true);
  223.  
  224.         void clear();
  225.         void resize(unsigned size);
  226.  
  227.         unsigned size() { return bit_size; }
  228.  
  229.         unsigned find_bit(unsigned start = 0);
  230.  
  231.         void swap(sb_bitset & bs2);
  232.  
  233.         bool operator==(const sb_bitset &bs2);
  234.         bool operator!=(const sb_bitset &bs2) { return !(*this == bs2); }
  235.  
  236.         sb_bitset& operator|=(const sb_bitset &bs2) {
  237.                 if (bit_size < bs2.bit_size) {
  238.                         resize(bs2.bit_size);
  239.                 }
  240.  
  241.                 for (unsigned i = 0, c = std::min(data.size(), bs2.data.size()); i < c;
  242.                                 ++i) {
  243.                         data[i] |= bs2.data[i];
  244.                 }
  245.                 return *this;
  246.         }
  247.  
  248.         sb_bitset& operator&=(const sb_bitset &bs2);
  249.         sb_bitset& mask(const sb_bitset &bs2);
  250.  
  251.         friend sb_bitset operator|(const sb_bitset &b1, const sb_bitset &b2) {
  252.                         sb_bitset nbs(b1);
  253.                         nbs |= b2;
  254.                         return nbs;
  255.         }
  256. };
  257.  
  258. class value;
  259.  
  260. enum value_kind {
  261.         VLK_REG,
  262.         VLK_REL_REG,
  263.         VLK_SPECIAL_REG,
  264.         VLK_TEMP,
  265.  
  266.         VLK_CONST,
  267.         VLK_KCACHE,
  268.         VLK_PARAM,
  269.         VLK_SPECIAL_CONST,
  270.  
  271.         VLK_UNDEF
  272. };
  273.  
  274.  
  275.  
  276. class sb_value_pool : protected sb_pool {
  277.         unsigned aligned_elt_size;
  278.  
  279. public:
  280.         sb_value_pool(unsigned elt_size, unsigned block_elts = 256)
  281.                 : sb_pool(block_elts * (aligned_elt_size = ((elt_size +
  282.                                 SB_POOL_ALIGN - 1) & ~(SB_POOL_ALIGN - 1)))) {}
  283.  
  284.         virtual ~sb_value_pool() { delete_all(); }
  285.  
  286.         value* create(value_kind k, sel_chan regid, unsigned ver);
  287.  
  288.         value* operator[](unsigned id) {
  289.                 unsigned offset = id * aligned_elt_size;
  290.                 unsigned block_id;
  291.                 if (offset < block_size) {
  292.                         block_id = 0;
  293.                 } else {
  294.                         block_id = offset / block_size;
  295.                         offset = offset % block_size;
  296.                 }
  297.                 return (value*)((char*)blocks[block_id] + offset);
  298.         }
  299.  
  300.         unsigned size() { return total_size / aligned_elt_size; }
  301.  
  302. protected:
  303.         void delete_all();
  304. };
  305.  
  306.  
  307.  
  308.  
  309.  
  310. class sb_value_set {
  311.  
  312.         sb_bitset bs;
  313.  
  314. public:
  315.         sb_value_set() : bs() {}
  316.  
  317.         class iterator {
  318.                 sb_value_pool &vp;
  319.                 sb_value_set *s;
  320.                 unsigned nb;
  321.         public:
  322.                 iterator(shader &sh, sb_value_set *s, unsigned nb = 0);
  323.  
  324.  
  325.                 iterator& operator++() {
  326.                         if (nb + 1 < s->bs.size())
  327.                                 nb = s->bs.find_bit(nb + 1);
  328.                         else
  329.                                 nb = s->bs.size();
  330.                         return *this;
  331.                 }
  332.                 bool operator !=(const iterator &i) {
  333.                         return s != i.s || nb != i.nb;
  334.                 }
  335.                 bool operator ==(const iterator &i) { return !(*this != i); }
  336.                 value* operator *() {
  337.                          return vp[nb];
  338.                 }
  339.  
  340.  
  341.         };
  342.  
  343.         iterator begin(shader &sh) {
  344.                 return iterator(sh, this, bs.size() ? bs.find_bit(0) : 0);
  345.         }
  346.         iterator end(shader &sh) { return iterator(sh, this, bs.size()); }
  347.  
  348.         bool add_set_checked(sb_value_set & s2);
  349.  
  350.         void add_set(sb_value_set & s2)  {
  351.                 if (bs.size() < s2.bs.size())
  352.                         bs.resize(s2.bs.size());
  353.                 bs |= s2.bs;
  354.         }
  355.  
  356.         void remove_set(sb_value_set & s2);
  357.  
  358.         bool add_vec(vvec &vv);
  359.  
  360.         bool add_val(value *v);
  361.         bool contains(value *v);
  362.  
  363.         bool remove_val(value *v);
  364.  
  365.         bool remove_vec(vvec &vv);
  366.  
  367.         void clear();
  368.  
  369.         bool empty();
  370. };
  371.  
  372. typedef sb_value_set val_set;
  373.  
  374. struct gpr_array {
  375.         sel_chan base_gpr; // original gpr
  376.         sel_chan gpr; // assigned by regalloc
  377.         unsigned array_size;
  378.  
  379.         gpr_array(sel_chan base_gpr, unsigned array_size) : base_gpr(base_gpr),
  380.                         array_size(array_size) {}
  381.  
  382.         unsigned hash() { return (base_gpr << 10) * array_size; }
  383.  
  384.         val_set interferences;
  385.         vvec refs;
  386.  
  387.         bool is_dead();
  388.  
  389. };
  390.  
  391. typedef std::vector<gpr_array*> regarray_vec;
  392.  
  393. enum value_flags {
  394.         VLF_UNDEF = (1 << 0),
  395.         VLF_READONLY = (1 << 1),
  396.         VLF_DEAD = (1 << 2),
  397.  
  398.         VLF_PIN_REG = (1 << 3),
  399.         VLF_PIN_CHAN = (1 << 4),
  400.  
  401.         // opposite to alu clause local value - goes through alu clause boundary
  402.         // (can't use temp gpr, can't recolor in the alu scheduler, etc)
  403.         VLF_GLOBAL = (1 << 5),
  404.         VLF_FIXED = (1 << 6),
  405.         VLF_PVPS = (1 << 7),
  406.  
  407.         VLF_PREALLOC = (1 << 8)
  408. };
  409.  
  410. inline value_flags operator |(value_flags l, value_flags r) {
  411.         return (value_flags)((unsigned)l|(unsigned)r);
  412. }
  413. inline value_flags operator &(value_flags l, value_flags r) {
  414.         return (value_flags)((unsigned)l&(unsigned)r);
  415. }
  416. inline value_flags operator ~(value_flags l) {
  417.         return (value_flags)(~(unsigned)l);
  418. }
  419. inline value_flags& operator |=(value_flags &l, value_flags r) {
  420.         l = l | r;
  421.         return l;
  422. }
  423. inline value_flags& operator &=(value_flags &l, value_flags r) {
  424.         l = l & r;
  425.         return l;
  426. }
  427.  
  428. struct value;
  429.  
  430. sb_ostream& operator << (sb_ostream &o, value &v);
  431.  
  432. typedef uint32_t value_hash;
  433.  
  434. enum use_kind {
  435.         UK_SRC,
  436.         UK_SRC_REL,
  437.         UK_DST_REL,
  438.         UK_MAYDEF,
  439.         UK_MAYUSE,
  440.         UK_PRED,
  441.         UK_COND
  442. };
  443.  
  444. struct use_info {
  445.         use_info *next;
  446.         node *op;
  447.         use_kind kind;
  448.         int arg;
  449.  
  450.         use_info(node *n, use_kind kind, int arg, use_info* next)
  451.                 : next(next), op(n), kind(kind), arg(arg) {}
  452. };
  453.  
  454. enum constraint_kind {
  455.         CK_SAME_REG,
  456.         CK_PACKED_BS,
  457.         CK_PHI
  458. };
  459.  
  460. class shader;
  461. class sb_value_pool;
  462. class ra_chunk;
  463. class ra_constraint;
  464.  
  465. class value {
  466. protected:
  467.         value(unsigned sh_id, value_kind k, sel_chan select, unsigned ver = 0)
  468.                 : kind(k), flags(),
  469.                         rel(), array(),
  470.                         version(ver), select(select), pin_gpr(select), gpr(),
  471.                         gvn_source(), ghash(),
  472.                         def(), adef(), uses(), constraint(), chunk(),
  473.                         literal_value(), uid(sh_id) {}
  474.  
  475.         ~value() { delete_uses(); }
  476.  
  477.         friend class sb_value_pool;
  478. public:
  479.         value_kind kind;
  480.         value_flags flags;
  481.  
  482.         vvec mdef;
  483.         vvec muse;
  484.         value *rel;
  485.         gpr_array *array;
  486.  
  487.         unsigned version;
  488.  
  489.         sel_chan select;
  490.         sel_chan pin_gpr;
  491.         sel_chan gpr;
  492.  
  493.         value *gvn_source;
  494.         value_hash ghash;
  495.  
  496.         node *def, *adef;
  497.         use_info *uses;
  498.  
  499.         ra_constraint *constraint;
  500.         ra_chunk *chunk;
  501.  
  502.         literal literal_value;
  503.  
  504.         bool is_const() { return kind == VLK_CONST || kind == VLK_UNDEF; }
  505.  
  506.         bool is_AR() {
  507.                 return is_special_reg() && select == sel_chan(SV_AR_INDEX, 0);
  508.         }
  509.  
  510.         node* any_def() {
  511.                 assert(!(def && adef));
  512.                 return def ? def : adef;
  513.         }
  514.  
  515.         value* gvalue() {
  516.                 value *v = this;
  517.                 while (v->gvn_source && v != v->gvn_source)
  518.                         // FIXME we really shouldn't have such chains
  519.                         v = v->gvn_source;
  520.                 return v;
  521.         }
  522.  
  523.         bool is_float_0_or_1() {
  524.                 value *v = gvalue();
  525.                 return v->is_const() && (v->literal_value == literal(0)
  526.                                                 || v->literal_value == literal(1.0f));
  527.         }
  528.  
  529.         bool is_undef() { return gvalue()->kind == VLK_UNDEF; }
  530.  
  531.         bool is_any_gpr() {
  532.                 return (kind == VLK_REG || kind == VLK_TEMP);
  533.         }
  534.  
  535.         bool is_agpr() {
  536.                 return array && is_any_gpr();
  537.         }
  538.  
  539.         // scalar gpr, as opposed to element of gpr array
  540.         bool is_sgpr() {
  541.                 return !array && is_any_gpr();
  542.         }
  543.  
  544.         bool is_special_reg() { return kind == VLK_SPECIAL_REG; }
  545.         bool is_any_reg() { return is_any_gpr() || is_special_reg(); }
  546.         bool is_kcache() { return kind == VLK_KCACHE; }
  547.         bool is_rel() { return kind == VLK_REL_REG; }
  548.         bool is_readonly() { return flags & VLF_READONLY; }
  549.  
  550.         bool is_chan_pinned() { return flags & VLF_PIN_CHAN; }
  551.         bool is_reg_pinned() { return flags & VLF_PIN_REG; }
  552.  
  553.         bool is_global();
  554.         void set_global();
  555.         void set_prealloc();
  556.  
  557.         bool is_prealloc();
  558.  
  559.         bool is_fixed();
  560.         void fix();
  561.  
  562.         bool is_dead() { return flags & VLF_DEAD; }
  563.  
  564.         literal & get_const_value() {
  565.                 value *v = gvalue();
  566.                 assert(v->is_const());
  567.                 return v->literal_value;
  568.         }
  569.  
  570.         // true if needs to be encoded as literal in alu
  571.         bool is_literal() {
  572.                 return is_const()
  573.                                 && literal_value != literal(0)
  574.                                 && literal_value != literal(1)
  575.                                 && literal_value != literal(-1)
  576.                                 && literal_value != literal(0.5)
  577.                                 && literal_value != literal(1.0);
  578.         }
  579.  
  580.         void add_use(node *n, use_kind kind, int arg);
  581.  
  582.         value_hash hash();
  583.         value_hash rel_hash();
  584.  
  585.         void assign_source(value *v) {
  586.                 assert(!gvn_source || gvn_source == this);
  587.                 gvn_source = v->gvalue();
  588.         }
  589.  
  590.         bool v_equal(value *v) { return gvalue() == v->gvalue(); }
  591.  
  592.         unsigned use_count();
  593.         void delete_uses();
  594.  
  595.         sel_chan get_final_gpr() {
  596.                 if (array && array->gpr) {
  597.                         int reg_offset = select.sel() - array->base_gpr.sel();
  598.                         if (rel && rel->is_const())
  599.                                 reg_offset += rel->get_const_value().i;
  600.                         return array->gpr + (reg_offset << 2);
  601.                 } else {
  602.                         return gpr;
  603.                 }
  604.         }
  605.  
  606.         unsigned get_final_chan() {
  607.                 if (array) {
  608.                         assert(array->gpr);
  609.                         return array->gpr.chan();
  610.                 } else {
  611.                         assert(gpr);
  612.                         return gpr.chan();
  613.                 }
  614.         }
  615.  
  616.         val_set interferences;
  617.         unsigned uid;
  618. };
  619.  
  620. class expr_handler;
  621.  
  622. class value_table {
  623.         typedef std::vector<value*> vt_item;
  624.         typedef std::vector<vt_item> vt_table;
  625.  
  626.         expr_handler &ex;
  627.  
  628.         unsigned size_bits;
  629.         unsigned size;
  630.         unsigned size_mask;
  631.  
  632.         vt_table hashtable;
  633.  
  634.         unsigned cnt;
  635.  
  636. public:
  637.  
  638.         value_table(expr_handler &ex, unsigned size_bits = 10)
  639.                 : ex(ex), size_bits(size_bits), size(1u << size_bits),
  640.                   size_mask(size - 1), hashtable(size), cnt() {}
  641.  
  642.         ~value_table() {}
  643.  
  644.         void add_value(value* v);
  645.  
  646.         bool expr_equal(value* l, value* r);
  647.  
  648.         unsigned count() { return cnt; }
  649.  
  650.         void get_values(vvec & v);
  651. };
  652.  
  653. class sb_context;
  654.  
  655. enum node_type {
  656.         NT_UNKNOWN,
  657.         NT_LIST,
  658.         NT_OP,
  659.         NT_REGION,
  660.         NT_REPEAT,
  661.         NT_DEPART,
  662.         NT_IF,
  663. };
  664.  
  665. enum node_subtype {
  666.         NST_UNKNOWN,
  667.         NST_LIST,
  668.         NST_ALU_GROUP,
  669.         NST_ALU_CLAUSE,
  670.         NST_ALU_INST,
  671.         NST_ALU_PACKED_INST,
  672.         NST_CF_INST,
  673.         NST_FETCH_INST,
  674.         NST_TEX_CLAUSE,
  675.         NST_VTX_CLAUSE,
  676.  
  677.         NST_BB,
  678.  
  679.         NST_PHI,
  680.         NST_PSI,
  681.         NST_COPY,
  682.  
  683.         NST_LOOP_PHI_CONTAINER,
  684.         NST_LOOP_CONTINUE,
  685.         NST_LOOP_BREAK
  686. };
  687.  
  688. enum node_flags {
  689.         NF_EMPTY = 0,
  690.         NF_DEAD = (1 << 0),
  691.         NF_REG_CONSTRAINT = (1 << 1),
  692.         NF_CHAN_CONSTRAINT = (1 << 2),
  693.         NF_ALU_4SLOT = (1 << 3),
  694.         NF_CONTAINER = (1 << 4),
  695.  
  696.         NF_COPY_MOV = (1 << 5),
  697.  
  698.         NF_DONT_KILL = (1 << 6),
  699.         NF_DONT_HOIST = (1 << 7),
  700.         NF_DONT_MOVE = (1 << 8),
  701.  
  702.         // for KILLxx - we want to schedule them as early as possible
  703.         NF_SCHEDULE_EARLY = (1 << 9)
  704. };
  705.  
  706. inline node_flags operator |(node_flags l, node_flags r) {
  707.         return (node_flags)((unsigned)l|(unsigned)r);
  708. }
  709. inline node_flags& operator |=(node_flags &l, node_flags r) {
  710.         l = l | r;
  711.         return l;
  712. }
  713.  
  714. inline node_flags& operator &=(node_flags &l, node_flags r) {
  715.         l = (node_flags)((unsigned)l & (unsigned)r);
  716.         return l;
  717. }
  718.  
  719. inline node_flags operator ~(node_flags r) {
  720.         return (node_flags)~(unsigned)r;
  721. }
  722.  
  723. struct node_stats {
  724.         unsigned alu_count;
  725.         unsigned alu_kill_count;
  726.         unsigned alu_copy_mov_count;
  727.         unsigned cf_count;
  728.         unsigned fetch_count;
  729.         unsigned region_count;
  730.         unsigned loop_count;
  731.         unsigned phi_count;
  732.         unsigned loop_phi_count;
  733.         unsigned depart_count;
  734.         unsigned repeat_count;
  735.         unsigned if_count;
  736.  
  737.         node_stats() : alu_count(), alu_kill_count(), alu_copy_mov_count(),
  738.                         cf_count(), fetch_count(), region_count(),
  739.                         loop_count(), phi_count(), loop_phi_count(), depart_count(),
  740.                         repeat_count(), if_count() {}
  741.  
  742.         void dump();
  743. };
  744.  
  745. class shader;
  746.  
  747. class vpass;
  748.  
  749. class container_node;
  750. class region_node;
  751.  
  752. class node {
  753.  
  754. protected:
  755.         node(node_type nt, node_subtype nst, node_flags flags = NF_EMPTY)
  756.         : prev(), next(), parent(),
  757.           type(nt), subtype(nst), flags(flags),
  758.           pred(), dst(), src() {}
  759.  
  760.         virtual ~node() {};
  761.  
  762. public:
  763.         node *prev, *next;
  764.         container_node *parent;
  765.  
  766.         node_type type;
  767.         node_subtype subtype;
  768.         node_flags flags;
  769.  
  770.         value *pred;
  771.  
  772.         vvec dst;
  773.         vvec src;
  774.  
  775.         virtual bool is_valid() { return true; }
  776.         virtual bool accept(vpass &p, bool enter);
  777.  
  778.         void insert_before(node *n);
  779.         void insert_after(node *n);
  780.         void replace_with(node *n);
  781.         void remove();
  782.  
  783.         virtual value_hash hash();
  784.         value_hash hash_src();
  785.  
  786.         virtual bool fold_dispatch(expr_handler *ex);
  787.  
  788.         bool is_container() { return flags & NF_CONTAINER; }
  789.  
  790.         bool is_alu_packed() { return subtype == NST_ALU_PACKED_INST; }
  791.         bool is_alu_inst() { return subtype == NST_ALU_INST; }
  792.         bool is_alu_group() { return subtype == NST_ALU_GROUP; }
  793.         bool is_alu_clause() { return subtype == NST_ALU_CLAUSE; }
  794.  
  795.         bool is_fetch_clause() {
  796.                 return subtype == NST_TEX_CLAUSE || subtype == NST_VTX_CLAUSE;
  797.         }
  798.  
  799.         bool is_copy() { return subtype == NST_COPY; }
  800.         bool is_copy_mov() { return flags & NF_COPY_MOV; }
  801.         bool is_any_alu() { return is_alu_inst() || is_alu_packed() || is_copy(); }
  802.  
  803.         bool is_fetch_inst() { return subtype == NST_FETCH_INST; }
  804.         bool is_cf_inst() { return subtype == NST_CF_INST; }
  805.  
  806.         bool is_region() { return type == NT_REGION; }
  807.         bool is_depart() { return type == NT_DEPART; }
  808.         bool is_repeat() { return type == NT_REPEAT; }
  809.         bool is_if() { return type == NT_IF; }
  810.         bool is_bb() { return subtype == NST_BB; }
  811.  
  812.         bool is_phi() { return subtype == NST_PHI; }
  813.  
  814.         bool is_dead() { return flags & NF_DEAD; }
  815.  
  816.         bool is_cf_op(unsigned op);
  817.         bool is_alu_op(unsigned op);
  818.         bool is_fetch_op(unsigned op);
  819.  
  820.         unsigned cf_op_flags();
  821.         unsigned alu_op_flags();
  822.         unsigned alu_op_slot_flags();
  823.         unsigned fetch_op_flags();
  824.  
  825.         bool is_mova();
  826.         bool is_pred_set();
  827.  
  828.         bool vec_uses_ar(vvec &vv) {
  829.                 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
  830.                         value *v = *I;
  831.                         if (v && v->rel && !v->rel->is_const())
  832.                                 return true;
  833.                 }
  834.                 return false;
  835.         }
  836.  
  837.         bool uses_ar() {
  838.                 return vec_uses_ar(dst) || vec_uses_ar(src);
  839.         }
  840.  
  841.  
  842.         region_node* get_parent_region();
  843.  
  844.         friend class shader;
  845. };
  846.  
  847. class container_node : public node {
  848. public:
  849.  
  850.         container_node(node_type nt = NT_LIST, node_subtype nst = NST_LIST,
  851.                        node_flags flags = NF_EMPTY)
  852.         : node(nt, nst, flags | NF_CONTAINER), first(), last(),
  853.           live_after(), live_before() {}
  854.  
  855.         // child items list
  856.         node *first, *last;
  857.  
  858.         val_set live_after;
  859.         val_set live_before;
  860.  
  861.         class iterator {
  862.                 node *p;
  863.         public:
  864.                 iterator(node *pp = NULL) : p(pp) {}
  865.                 iterator & operator ++() { p = p->next; return *this;}
  866.                 iterator & operator --() { p = p->prev; return *this;}
  867.                 node* operator *() { return p; }
  868.                 node* operator ->() { return p; }
  869.                 const iterator advance(int n) {
  870.                         if (!n) return *this;
  871.                         iterator I(p);
  872.                         if (n > 0) while (n--) ++I;
  873.                         else while (n++) --I;
  874.                         return I;
  875.                 }
  876.                 const iterator operator +(int n) { return advance(n); }
  877.                 const iterator operator -(int n) { return advance(-n); }
  878.                 bool operator !=(const iterator &i) { return p != i.p; }
  879.                 bool operator ==(const iterator &i) { return p == i.p; }
  880.         };
  881.  
  882.         class riterator {
  883.                 iterator i;
  884.         public:
  885.                 riterator(node *p = NULL) : i(p) {}
  886.                 riterator & operator ++() { --i; return *this;}
  887.                 riterator & operator --() { ++i; return *this;}
  888.                 node* operator *() { return *i; }
  889.                 node* operator ->() { return *i; }
  890.                 bool operator !=(const riterator &r) { return i != r.i; }
  891.                 bool operator ==(const riterator &r) { return i == r.i; }
  892.         };
  893.  
  894.         iterator begin() { return first; }
  895.         iterator end() { return NULL; }
  896.         riterator rbegin() { return last; }
  897.         riterator rend() { return NULL; }
  898.  
  899.         bool empty() { assert(first != NULL || first == last); return !first; }
  900.         unsigned count();
  901.  
  902.         // used with node containers that represent shceduling queues
  903.         // ignores copies and takes into account alu_packed_node items
  904.         unsigned real_alu_count();
  905.  
  906.         void push_back(node *n);
  907.         void push_front(node *n);
  908.  
  909.         void insert_node_before(node *s, node *n);
  910.         void insert_node_after(node *s, node *n);
  911.  
  912.         void append_from(container_node *c);
  913.  
  914.         // remove range [b..e) from some container and assign to this container
  915.         void move(iterator b, iterator e);
  916.  
  917.         void expand();
  918.         void expand(container_node *n);
  919.         void remove_node(node *n);
  920.  
  921.         node *cut(iterator b, iterator e);
  922.  
  923.         void clear() { first = last = NULL; }
  924.  
  925.         virtual bool is_valid() { return true; }
  926.         virtual bool accept(vpass &p, bool enter);
  927.         virtual bool fold_dispatch(expr_handler *ex);
  928.  
  929.         node* front() { return first; }
  930.         node* back() { return last; }
  931.  
  932.         void collect_stats(node_stats &s);
  933.  
  934.         friend class shader;
  935.  
  936.  
  937. };
  938.  
  939. typedef container_node::iterator node_iterator;
  940. typedef container_node::riterator node_riterator;
  941.  
  942. class alu_group_node : public container_node {
  943. protected:
  944.         alu_group_node() : container_node(NT_LIST, NST_ALU_GROUP), literals() {}
  945. public:
  946.  
  947.         std::vector<literal> literals;
  948.  
  949.         virtual bool is_valid() { return subtype == NST_ALU_GROUP; }
  950.         virtual bool accept(vpass &p, bool enter);
  951.  
  952.  
  953.         unsigned literal_chan(literal l) {
  954.                 std::vector<literal>::iterator F =
  955.                                 std::find(literals.begin(), literals.end(), l);
  956.                 assert(F != literals.end());
  957.                 return F - literals.begin();
  958.         }
  959.  
  960.         friend class shader;
  961. };
  962.  
  963. class cf_node : public container_node {
  964. protected:
  965.         cf_node() : container_node(NT_OP, NST_CF_INST), jump_target(),
  966.                 jump_after_target() {};
  967. public:
  968.         bc_cf bc;
  969.  
  970.         cf_node *jump_target;
  971.         bool jump_after_target;
  972.  
  973.         virtual bool is_valid() { return subtype == NST_CF_INST; }
  974.         virtual bool accept(vpass &p, bool enter);
  975.         virtual bool fold_dispatch(expr_handler *ex);
  976.  
  977.         void jump(cf_node *c) { jump_target = c; jump_after_target = false; }
  978.         void jump_after(cf_node *c) { jump_target = c; jump_after_target = true; }
  979.  
  980.         friend class shader;
  981. };
  982.  
  983. class alu_node : public node {
  984. protected:
  985.         alu_node() : node(NT_OP, NST_ALU_INST) {};
  986. public:
  987.         bc_alu bc;
  988.  
  989.         virtual bool is_valid() { return subtype == NST_ALU_INST; }
  990.         virtual bool accept(vpass &p, bool enter);
  991.         virtual bool fold_dispatch(expr_handler *ex);
  992.  
  993.         unsigned forced_bank_swizzle() {
  994.                 return ((bc.op_ptr->flags & AF_INTERP) && (bc.slot_flags == AF_4V)) ?
  995.                                 VEC_210 : 0;
  996.         }
  997.  
  998.         // return param index + 1 if instruction references interpolation param,
  999.         // otherwise 0
  1000.         unsigned interp_param();
  1001.  
  1002.         alu_group_node *get_alu_group_node();
  1003.  
  1004.         friend class shader;
  1005. };
  1006.  
  1007. // for multi-slot instrs - DOT/INTERP/... (maybe useful for 64bit pairs later)
  1008. class alu_packed_node : public container_node {
  1009. protected:
  1010.         alu_packed_node() : container_node(NT_OP, NST_ALU_PACKED_INST) {}
  1011. public:
  1012.  
  1013.         const alu_op_info* op_ptr() {
  1014.                 return static_cast<alu_node*>(first)->bc.op_ptr;
  1015.         }
  1016.         unsigned op() { return static_cast<alu_node*>(first)->bc.op; }
  1017.         void init_args(bool repl);
  1018.  
  1019.         virtual bool is_valid() { return subtype == NST_ALU_PACKED_INST; }
  1020.         virtual bool accept(vpass &p, bool enter);
  1021.         virtual bool fold_dispatch(expr_handler *ex);
  1022.  
  1023.         unsigned get_slot_mask();
  1024.         void update_packed_items(sb_context &ctx);
  1025.  
  1026.         friend class shader;
  1027. };
  1028.  
  1029. class fetch_node : public node {
  1030. protected:
  1031.         fetch_node() : node(NT_OP, NST_FETCH_INST) {};
  1032. public:
  1033.         bc_fetch bc;
  1034.  
  1035.         virtual bool is_valid() { return subtype == NST_FETCH_INST; }
  1036.         virtual bool accept(vpass &p, bool enter);
  1037.         virtual bool fold_dispatch(expr_handler *ex);
  1038.  
  1039.         bool uses_grad() { return bc.op_ptr->flags & FF_USEGRAD; }
  1040.  
  1041.         friend class shader;
  1042. };
  1043.  
  1044. class region_node;
  1045.  
  1046. class repeat_node : public container_node {
  1047. protected:
  1048.         repeat_node(region_node *target, unsigned id)
  1049.         : container_node(NT_REPEAT, NST_LIST), target(target), rep_id(id) {}
  1050. public:
  1051.         region_node *target;
  1052.         unsigned rep_id;
  1053.  
  1054.         virtual bool accept(vpass &p, bool enter);
  1055.  
  1056.         friend class shader;
  1057. };
  1058.  
  1059. class depart_node : public container_node {
  1060. protected:
  1061.         depart_node(region_node *target, unsigned id)
  1062.         : container_node(NT_DEPART, NST_LIST), target(target), dep_id(id) {}
  1063. public:
  1064.         region_node *target;
  1065.         unsigned dep_id;
  1066.  
  1067.         virtual bool accept(vpass &p, bool enter);
  1068.  
  1069.         friend class shader;
  1070. };
  1071.  
  1072. class if_node : public container_node {
  1073. protected:
  1074.         if_node() : container_node(NT_IF, NST_LIST), cond() {};
  1075. public:
  1076.         value *cond; // glued to pseudo output (dst[2]) of the PRED_SETxxx
  1077.  
  1078.         virtual bool accept(vpass &p, bool enter);
  1079.  
  1080.         friend class shader;
  1081. };
  1082.  
  1083. typedef std::vector<depart_node*> depart_vec;
  1084. typedef std::vector<repeat_node*> repeat_vec;
  1085.  
  1086. class region_node : public container_node {
  1087. protected:
  1088.         region_node(unsigned id) : container_node(NT_REGION, NST_LIST), region_id(id),
  1089.                         loop_phi(), phi(), vars_defined(), departs(), repeats() {}
  1090. public:
  1091.         unsigned region_id;
  1092.  
  1093.         container_node *loop_phi;
  1094.         container_node *phi;
  1095.  
  1096.         val_set vars_defined;
  1097.  
  1098.         depart_vec departs;
  1099.         repeat_vec repeats;
  1100.  
  1101.         virtual bool accept(vpass &p, bool enter);
  1102.  
  1103.         unsigned dep_count() { return departs.size(); }
  1104.         unsigned rep_count() { return repeats.size() + 1; }
  1105.  
  1106.         bool is_loop() { return !repeats.empty(); }
  1107.  
  1108.         container_node* get_entry_code_location() {
  1109.                 node *p = first;
  1110.                 while (p && (p->is_depart() || p->is_repeat()))
  1111.                         p = static_cast<container_node*>(p)->first;
  1112.  
  1113.                 container_node *c = static_cast<container_node*>(p);
  1114.                 if (c->is_bb())
  1115.                         return c;
  1116.                 else
  1117.                         return c->parent;
  1118.         }
  1119.  
  1120.         void expand_depart(depart_node *d);
  1121.         void expand_repeat(repeat_node *r);
  1122.  
  1123.         friend class shader;
  1124. };
  1125.  
  1126. class bb_node : public container_node {
  1127. protected:
  1128.         bb_node(unsigned id, unsigned loop_level)
  1129.                 : container_node(NT_LIST, NST_BB), id(id), loop_level(loop_level) {}
  1130. public:
  1131.         unsigned id;
  1132.         unsigned loop_level;
  1133.  
  1134.         virtual bool accept(vpass &p, bool enter);
  1135.  
  1136.         friend class shader;
  1137. };
  1138.  
  1139.  
  1140. typedef std::vector<region_node*> regions_vec;
  1141. typedef std::vector<bb_node*> bbs_vec;
  1142. typedef std::list<node*> sched_queue;
  1143. typedef sched_queue::iterator sq_iterator;
  1144. typedef std::vector<node*> node_vec;
  1145. typedef std::list<node*> node_list;
  1146. typedef std::set<node*> node_set;
  1147.  
  1148.  
  1149.  
  1150. } // namespace r600_sb
  1151.  
  1152. #endif /* R600_SB_IR_H_ */
  1153.