Subversion Repositories Kolibri OS

Rev

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. #define GVN_DEBUG 0
  28.  
  29. #if GVN_DEBUG
  30. #define GVN_DUMP(q) do { q } while (0)
  31. #else
  32. #define GVN_DUMP(q)
  33. #endif
  34.  
  35. #include "sb_shader.h"
  36. #include "sb_pass.h"
  37. #include "sb_sched.h"
  38.  
  39. namespace r600_sb {
  40.  
  41. bool gvn::visit(node& n, bool enter) {
  42.         if (enter) {
  43.  
  44.  
  45.                 bool rewrite = true;
  46.  
  47.                 if (n.dst[0]->is_agpr()) {
  48.                         rewrite = false;
  49.                 }
  50.  
  51.  
  52.                 process_op(n, rewrite);
  53.  
  54.                 assert(n.parent);
  55.  
  56.                 if (n.parent->subtype == NST_LOOP_PHI_CONTAINER) {
  57.                         // There is a problem - sometimes with nested loops
  58.                         // loop counter initialization for inner loop is incorrectly hoisted
  59.                         // out of the outer loop
  60.  
  61.                         // FIXME not sure if this is enough to fix a problem completely,
  62.                         // possibly more complete fix is needed (anyway, the
  63.                         // problem was seen only in relatively complex
  64.                         // case involving nested loops and
  65.                         // indirect access to loop counters (without proper array info
  66.                         // loop counters may be considered as array elements too),
  67.                         // was not seen in any tests
  68.                         // or real apps when proper array information is available in TGSI).
  69.  
  70.                         // For now just mark the instructions that initialize loop counters
  71.                         // with DONT_HOIST flag to prevent the insts like MOV r, 0
  72.                         // (initialization of inner loop's counter with const)
  73.                         // from being hoisted out of the outer loop
  74.  
  75.                         assert(!n.src.empty());
  76.                         value *v = n.src[0];
  77.  
  78.                         if (v->is_any_gpr() && v->def)
  79.                                 v->def->flags |= NF_DONT_HOIST;
  80.                 }
  81.  
  82.         } else {
  83.         }
  84.         return true;
  85. }
  86.  
  87. bool gvn::visit(cf_node& n, bool enter) {
  88.         if (enter) {
  89.                 process_op(n);
  90.         } else {
  91.         }
  92.         return true;
  93. }
  94.  
  95. bool gvn::visit(alu_node& n, bool enter) {
  96.         if (enter) {
  97.                 process_op(n);
  98.         } else {
  99.         }
  100.         return true;
  101. }
  102.  
  103. bool gvn::visit(alu_packed_node& n, bool enter) {
  104.         if (enter) {
  105.                 process_op(n);
  106.         } else {
  107.         }
  108.         return false;
  109. }
  110.  
  111. bool gvn::visit(fetch_node& n, bool enter) {
  112.         if (enter) {
  113.                 process_op(n);
  114.         } else {
  115.         }
  116.         return true;
  117. }
  118.  
  119. bool gvn::visit(region_node& n, bool enter) {
  120.         if (enter) {
  121. // FIXME: loop_phi sources are undefined yet (except theone from the preceding
  122. // code), can we handle that somehow?
  123. //              if (n.loop_phi)
  124. //                      run_on(*n.loop_phi);
  125.         } else {
  126.                 if (n.loop_phi)
  127.                         run_on(*n.loop_phi);
  128.  
  129.                 if (n.phi)
  130.                         run_on(*n.phi);
  131.         }
  132.         return true;
  133. }
  134.  
  135. bool gvn::process_src(value* &v, bool rewrite) {
  136.         if (!v->gvn_source)
  137.                 sh.vt.add_value(v);
  138.  
  139.         if (rewrite && !v->gvn_source->is_rel()) {
  140.                 v = v->gvn_source;
  141.                 return true;
  142.         }
  143.         return false;
  144. }
  145.  
  146. // FIXME: maybe handle it in the scheduler?
  147. void gvn::process_alu_src_constants(node &n, value* &v) {
  148.         if (n.src.size() < 3) {
  149.                 process_src(v, true);
  150.                 return;
  151.         }
  152.  
  153.         if (!v->gvn_source)
  154.                 sh.vt.add_value(v);
  155.  
  156.         rp_kcache_tracker kc(sh);
  157.  
  158.         if (v->gvn_source->is_kcache())
  159.                 kc.try_reserve(v->gvn_source->select);
  160.  
  161.         // don't propagate 3rd constant to the trans-only instruction
  162.         if (!n.is_alu_packed()) {
  163.                 alu_node *a = static_cast<alu_node*>(&n);
  164.                 if (a->bc.op_ptr->src_count == 3 && !(a->bc.slot_flags & AF_V)) {
  165.                         unsigned const_count = 0;
  166.                         for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E;
  167.                                         ++I) {
  168.                                 value *c = (*I);
  169.                                 if (c && c->is_readonly() && ++const_count == 2) {
  170.                                         process_src(v, false);
  171.                                         return;
  172.                                 }
  173.                         }
  174.                 }
  175.         }
  176.  
  177.         for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
  178.                 value *c = (*I);
  179.  
  180.                 if (c->is_kcache() && !kc.try_reserve(c->select)) {
  181.                         process_src(v, false);
  182.                         return;
  183.                 }
  184.         }
  185.         process_src(v, true);
  186. }
  187.  
  188. void gvn::process_op(node& n, bool rewrite) {
  189.  
  190.         for(vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
  191.                 value* &v = *I;
  192.                 if (v) {
  193.                         if (v->rel) {
  194.                                 process_src(v->rel, rewrite);
  195.                         }
  196.  
  197.                         if (rewrite && v->gvn_source && v->gvn_source->is_readonly() &&
  198.                                         n.is_any_alu()) {
  199.                                 process_alu_src_constants(n, v);
  200.                         } else if (rewrite && v->gvn_source && v->gvn_source->is_const() &&
  201.                                         (n.is_fetch_op(FETCH_OP_VFETCH) ||
  202.                                                         n.is_fetch_op(FETCH_OP_SEMFETCH)))
  203.                                 process_src(v, false);
  204.                         else
  205.                                 process_src(v, rewrite);
  206.                 }
  207.         }
  208.         if (n.pred)
  209.                 process_src(n.pred, false);
  210.  
  211.         if (n.type == NT_IF) {
  212.                 if_node &i = (if_node&)n;
  213.                 if (i.cond)
  214.                         process_src(i.cond, false);
  215.         }
  216.  
  217.         for(vvec::iterator I = n.dst.begin(), E = n.dst.end(); I != E; ++I) {
  218.                 value *v = *I;
  219.                 if (v) {
  220.                         if (v->rel)
  221.                                 process_src(v->rel, rewrite);
  222.                         sh.vt.add_value(v);
  223.                 }
  224.         }
  225. }
  226.  
  227. } // namespace r600_sb
  228.