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. #include "sb_bc.h"
  28. #include "sb_shader.h"
  29. #include "sb_pass.h"
  30.  
  31. namespace r600_sb {
  32.  
  33. bool node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  34. bool container_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  35. bool alu_group_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  36. bool alu_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  37. bool cf_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  38. bool fetch_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  39. bool region_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  40.  
  41. bool repeat_node::accept(vpass& p, bool enter) {
  42.         return p.visit(*this, enter);
  43. }
  44.  
  45. bool depart_node::accept(vpass& p, bool enter) {
  46.         return p.visit(*this, enter);
  47. }
  48. bool if_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  49. bool bb_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
  50. bool alu_packed_node::accept(vpass& p, bool enter) {
  51.         return p.visit(*this, enter);
  52. }
  53.  
  54. void alu_packed_node::init_args(bool repl) {
  55.         alu_node *p = static_cast<alu_node*>(first);
  56.         assert(p->is_valid());
  57.         while (p) {
  58.                 dst.insert(dst.end(), p->dst.begin(), p->dst.end());
  59.                 src.insert(src.end(), p->src.begin(), p->src.end());
  60.                 p = static_cast<alu_node*>(p->next);
  61.         }
  62.  
  63.         value *replicated_value = NULL;
  64.  
  65.         for (vvec::iterator I = dst.begin(), E = dst.end(); I != E; ++I) {
  66.                 value *v = *I;
  67.                 if (v) {
  68.                         if (repl) {
  69.                                 if (replicated_value)
  70.                                         v->assign_source(replicated_value);
  71.                                 else
  72.                                         replicated_value = v;
  73.                         }
  74.  
  75.                         v->def = this;
  76.                 }
  77.         }
  78. }
  79.  
  80. void container_node::insert_node_before(node* s, node* n) {
  81.         if (s->prev) {
  82.                 node *sp = s->prev;
  83.                 sp->next = n;
  84.                 n->prev = sp;
  85.                 n->next = s;
  86.                 s->prev = n;
  87.         } else {
  88.                 n->next = s;
  89.                 s->prev = n;
  90.                 first = n;
  91.         }
  92.         n->parent = this;
  93. }
  94.  
  95. void container_node::insert_node_after(node* s, node* n) {
  96.         if (s->next) {
  97.                 node *sn = s->next;
  98.                 sn->prev = n;
  99.                 n->next = sn;
  100.                 n->prev = s;
  101.                 s->next = n;
  102.         } else {
  103.                 n->prev = s;
  104.                 s->next = n;
  105.                 last = n;
  106.         }
  107.         n->parent = this;
  108. }
  109.  
  110. void container_node::move(iterator b, iterator e) {
  111.         assert(b != e);
  112.  
  113.         container_node *source_container = b->parent;
  114.         node *l = source_container->cut(b, e);
  115.  
  116.         first = last = l;
  117.         first->parent = this;
  118.  
  119.         while (last->next) {
  120.                 last = last->next;
  121.                 last->parent = this;
  122.         }
  123. }
  124.  
  125. node* container_node::cut(iterator b, iterator e) {
  126.         assert(!*b || b->parent == this);
  127.         assert(!*e || e->parent == this);
  128.         assert(b != e);
  129.  
  130.         if (b->prev) {
  131.                 b->prev->next = *e;
  132.         } else {
  133.                 first = *e;
  134.         }
  135.  
  136.         if (*e) {
  137.                 e->prev->next = NULL;
  138.                 e->prev = b->prev;
  139.         } else {
  140.                 last->next = NULL;
  141.                 last = b->prev;
  142.         }
  143.  
  144.         b->prev = NULL;
  145.  
  146.         return *b;
  147. }
  148.  
  149. unsigned container_node::count() {
  150.         unsigned c = 0;
  151.         node *t = first;
  152.         while (t) {
  153.                 t = t->next;
  154.                 c++;
  155.         }
  156.         return c;
  157. }
  158.  
  159. void container_node::remove_node(node *n) {
  160.         if (n->prev)
  161.                 n->prev->next = n->next;
  162.         else
  163.                 first = n->next;
  164.         if (n->next)
  165.                 n->next->prev = n->prev;
  166.         else
  167.                 last = n->prev;
  168.         n->parent = NULL;
  169. }
  170.  
  171. void container_node::expand(container_node *n) {
  172.         if (!n->empty()) {
  173.                 node *e0 = n->first;
  174.                 node *e1 = n->last;
  175.  
  176.                 e0->prev = n->prev;
  177.                 if (e0->prev) {
  178.                         e0->prev->next = e0;
  179.                 } else {
  180.                         first = e0;
  181.                 }
  182.  
  183.                 e1->next = n->next;
  184.                 if (e1->next)
  185.                         e1->next->prev = e1;
  186.                 else
  187.                         last = e1;
  188.  
  189.                 do {
  190.                         e0->parent = this;
  191.                         e0 = e0->next;
  192.                 } while (e0 != e1->next);
  193.         } else
  194.                 remove_node(n);
  195. }
  196.  
  197. void container_node::push_back(node *n) {
  198.         if (last) {
  199.                 last->next = n;
  200.                 n->next = NULL;
  201.                 n->prev = last;
  202.                 last = n;
  203.         } else {
  204.                 assert(!first);
  205.                 first = last = n;
  206.                 n->prev = n->next = NULL;
  207.         }
  208.         n->parent = this;
  209. }
  210. void container_node::push_front(node *n) {
  211.         if (first) {
  212.                 first->prev = n;
  213.                 n->prev = NULL;
  214.                 n->next = first;
  215.                 first = n;
  216.         } else {
  217.                 assert(!last);
  218.                 first = last = n;
  219.                 n->prev = n->next = NULL;
  220.         }
  221.         n->parent = this;
  222. }
  223.  
  224. void node::insert_before(node* n) {
  225.          parent->insert_node_before(this, n);
  226. }
  227.  
  228. void node::insert_after(node* n) {
  229.          parent->insert_node_after(this, n);
  230. }
  231.  
  232. void node::replace_with(node* n) {
  233.         n->prev = prev;
  234.         n->next = next;
  235.         n->parent = parent;
  236.         if (prev)
  237.                 prev->next = n;
  238.         if (next)
  239.                 next->prev = n;
  240.  
  241.         if (parent->first == this)
  242.                 parent->first = n;
  243.  
  244.         if (parent->last == this)
  245.                 parent->last = n;
  246.  
  247.         parent = NULL;
  248.         next = prev = NULL;
  249. }
  250.  
  251. void container_node::expand() {
  252.          parent->expand(this);
  253. }
  254.  
  255. void node::remove() {parent->remove_node(this);
  256. }
  257.  
  258. value_hash node::hash_src() {
  259.  
  260.         value_hash h = 12345;
  261.  
  262.         for (int k = 0, e = src.size(); k < e; ++k) {
  263.                 value *s = src[k];
  264.                 if (s)
  265.                         h ^=  (s->hash());
  266.         }
  267.  
  268.         return h;
  269. }
  270.  
  271.  
  272. value_hash node::hash() {
  273.  
  274.         if (parent && parent->subtype == NST_LOOP_PHI_CONTAINER)
  275.                 return 47451;
  276.  
  277.         return hash_src() ^ (subtype << 13) ^ (type << 3);
  278. }
  279.  
  280. void r600_sb::container_node::append_from(container_node* c) {
  281.         if (!c->first)
  282.                 return;
  283.  
  284.         node *b = c->first;
  285.  
  286.         if (last) {
  287.                 last->next = c->first;
  288.                 last->next->prev = last;
  289.         } else {
  290.                 first = c->first;
  291.         }
  292.  
  293.         last = c->last;
  294.         c->first = NULL;
  295.         c->last = NULL;
  296.  
  297.         while (b) {
  298.                 b->parent = this;
  299.                 b = b->next;
  300.         }
  301. }
  302.  
  303. bool node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
  304. bool container_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
  305. bool alu_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
  306. bool alu_packed_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
  307. bool fetch_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
  308. bool cf_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
  309.  
  310. unsigned alu_packed_node::get_slot_mask() {
  311.         unsigned mask = 0;
  312.         for (node_iterator I = begin(), E = end(); I != E; ++I)
  313.                 mask |= 1 << static_cast<alu_node*>(*I)->bc.slot;
  314.         return mask;
  315. }
  316.  
  317. void alu_packed_node::update_packed_items(sb_context &ctx) {
  318.  
  319.         vvec::iterator SI(src.begin()), DI(dst.begin());
  320.  
  321.         assert(first);
  322.  
  323.         alu_node *c = static_cast<alu_node*>(first);
  324.         unsigned flags = c->bc.op_ptr->flags;
  325.         unsigned slot_flags = c->bc.slot_flags;
  326.  
  327.         // fixup dst for instructions that replicate output
  328.         if (((flags & AF_REPL) && slot_flags == AF_4V) ||
  329.                         (ctx.is_cayman() && slot_flags == AF_S)) {
  330.  
  331.                 value *swp[4] = {};
  332.  
  333.                 unsigned chan;
  334.  
  335.                 for (vvec::iterator I2 = dst.begin(), E2 = dst.end();
  336.                                 I2 != E2; ++I2) {
  337.                         value *v = *I2;
  338.                         if (v) {
  339.                                 chan = v->get_final_chan();
  340.                                 assert(!swp[chan] || swp[chan] == v);
  341.                                 swp[chan] = v;
  342.                         }
  343.                 }
  344.  
  345.                 chan = 0;
  346.                 for (vvec::iterator I2 = dst.begin(), E2 = dst.end();
  347.                                 I2 != E2; ++I2, ++chan) {
  348.                         *I2 = swp[chan];
  349.                 }
  350.         }
  351.  
  352.         for (node_iterator I = begin(), E = end(); I != E; ++I) {
  353.                 alu_node *n = static_cast<alu_node*>(*I);
  354.                 assert(n);
  355.  
  356.                 for (vvec::iterator I2 = n->src.begin(), E2 = n->src.end();
  357.                                 I2 != E2; ++I2, ++SI) {
  358.                         *I2 = *SI;
  359.                 }
  360.                 for (vvec::iterator I2 = n->dst.begin(), E2 = n->dst.end();
  361.                                 I2 != E2; ++I2, ++DI) {
  362.                         *I2 = *DI;
  363.                 }
  364.         }
  365. }
  366.  
  367. bool node::is_cf_op(unsigned op) {
  368.         if (!is_cf_inst())
  369.                 return false;
  370.         cf_node *c = static_cast<cf_node*>(this);
  371.         return c->bc.op == op;
  372. }
  373.  
  374. bool node::is_alu_op(unsigned op) {
  375.         if (!is_alu_inst())
  376.                 return false;
  377.         alu_node *c = static_cast<alu_node*>(this);
  378.         return c->bc.op == op;
  379. }
  380.  
  381. bool node::is_fetch_op(unsigned op) {
  382.         if (!is_fetch_inst())
  383.                 return false;
  384.         fetch_node *c = static_cast<fetch_node*>(this);
  385.         return c->bc.op == op;
  386. }
  387.  
  388.  
  389.  
  390. bool node::is_mova() {
  391.         if (!is_alu_inst())
  392.                 return false;
  393.         alu_node *a = static_cast<alu_node*>(this);
  394.         return (a->bc.op_ptr->flags & AF_MOVA);
  395. }
  396.  
  397. bool node::is_pred_set() {
  398.         if (!is_alu_inst())
  399.                 return false;
  400.         alu_node *a = static_cast<alu_node*>(this);
  401.         return (a->bc.op_ptr->flags & AF_ANY_PRED);
  402. }
  403.  
  404. unsigned node::cf_op_flags() {
  405.         assert(is_cf_inst());
  406.         cf_node *c = static_cast<cf_node*>(this);
  407.         return c->bc.op_ptr->flags;
  408. }
  409.  
  410. unsigned node::alu_op_flags() {
  411.         assert(is_alu_inst());
  412.         alu_node *c = static_cast<alu_node*>(this);
  413.         return c->bc.op_ptr->flags;
  414. }
  415.  
  416. unsigned node::fetch_op_flags() {
  417.         assert(is_fetch_inst());
  418.         fetch_node *c = static_cast<fetch_node*>(this);
  419.         return c->bc.op_ptr->flags;
  420. }
  421.  
  422. unsigned node::alu_op_slot_flags() {
  423.         assert(is_alu_inst());
  424.         alu_node *c = static_cast<alu_node*>(this);
  425.         return c->bc.slot_flags;
  426. }
  427.  
  428. region_node* node::get_parent_region() {
  429.         node *p = this;
  430.         while ((p = p->parent))
  431.                 if (p->is_region())
  432.                         return static_cast<region_node*>(p);
  433.         return NULL;
  434. }
  435.  
  436. unsigned container_node::real_alu_count() {
  437.         unsigned c = 0;
  438.         node *t = first;
  439.         while (t) {
  440.                 if (t->is_alu_inst())
  441.                         ++c;
  442.                 else if (t->is_alu_packed())
  443.                         c += static_cast<container_node*>(t)->count();
  444.                 t = t->next;
  445.         }
  446.         return c;
  447. }
  448.  
  449. void container_node::collect_stats(node_stats& s) {
  450.  
  451.         for (node_iterator I = begin(), E = end(); I != E; ++I) {
  452.                 node *n = *I;
  453.                 if (n->is_container()) {
  454.                         static_cast<container_node*>(n)->collect_stats(s);
  455.                 }
  456.  
  457.                 if (n->is_alu_inst()) {
  458.                         ++s.alu_count;
  459.                         alu_node *a = static_cast<alu_node*>(n);
  460.                         if (a->bc.op_ptr->flags & AF_KILL)
  461.                                 ++s.alu_kill_count;
  462.                         else if (a->is_copy_mov())
  463.                                 ++s.alu_copy_mov_count;
  464.                 } else if (n->is_fetch_inst())
  465.                         ++s.fetch_count;
  466.                 else if (n->is_cf_inst())
  467.                         ++s.cf_count;
  468.                 else if (n->is_region()) {
  469.                         ++s.region_count;
  470.                         region_node *r = static_cast<region_node*>(n);
  471.                         if(r->is_loop())
  472.                                 ++s.loop_count;
  473.  
  474.                         if (r->phi)
  475.                                 s.phi_count += r->phi->count();
  476.                         if (r->loop_phi)
  477.                                 s.loop_phi_count += r->loop_phi->count();
  478.                 }
  479.                 else if (n->is_depart())
  480.                         ++s.depart_count;
  481.                 else if (n->is_repeat())
  482.                         ++s.repeat_count;
  483.                 else if (n->is_if())
  484.                         ++s.if_count;
  485.         }
  486. }
  487.  
  488. void region_node::expand_depart(depart_node *d) {
  489.         depart_vec::iterator I = departs.begin() + d->dep_id, E;
  490.         I = departs.erase(I);
  491.         E = departs.end();
  492.         while (I != E) {
  493.                 --(*I)->dep_id;
  494.                 ++I;
  495.         }
  496.         d->expand();
  497. }
  498.  
  499. void region_node::expand_repeat(repeat_node *r) {
  500.         repeat_vec::iterator I = repeats.begin() + r->rep_id - 1, E;
  501.         I = repeats.erase(I);
  502.         E = repeats.end();
  503.         while (I != E) {
  504.                 --(*I)->rep_id;
  505.                 ++I;
  506.         }
  507.         r->expand();
  508. }
  509.  
  510. void node_stats::dump() {
  511.         sblog << "  alu_count : " << alu_count << "\n";
  512.         sblog << "  alu_kill_count : " << alu_kill_count << "\n";
  513.         sblog << "  alu_copy_mov_count : " << alu_copy_mov_count << "\n";
  514.         sblog << "  cf_count : " << cf_count << "\n";
  515.         sblog << "  fetch_count : " << fetch_count << "\n";
  516.         sblog << "  region_count : " << region_count << "\n";
  517.         sblog << "  loop_count : " << loop_count << "\n";
  518.         sblog << "  phi_count : " << phi_count << "\n";
  519.         sblog << "  loop_phi_count : " << loop_phi_count << "\n";
  520.         sblog << "  depart_count : " << depart_count << "\n";
  521.         sblog << "  repeat_count : " << repeat_count << "\n";
  522.         sblog << "  if_count : " << if_count << "\n";
  523. }
  524.  
  525. unsigned alu_node::interp_param() {
  526.         if (!(bc.op_ptr->flags & AF_INTERP))
  527.                 return 0;
  528.         unsigned param;
  529.         if (bc.op_ptr->src_count == 2) {
  530.                 param = src[1]->select.sel();
  531.         } else {
  532.                 param = src[0]->select.sel();
  533.         }
  534.         return param + 1;
  535. }
  536.  
  537. alu_group_node* alu_node::get_alu_group_node() {
  538.         node *p = parent;
  539.         if (p) {
  540.                 if (p->subtype == NST_ALU_PACKED_INST) {
  541.                         assert(p->parent && p->parent->subtype == NST_ALU_GROUP);
  542.                         p = p->parent;
  543.                 }
  544.                 return static_cast<alu_group_node*>(p);
  545.         }
  546.         return NULL;
  547. }
  548.  
  549. } // namespace r600_sb
  550.