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. #include "sb_shader.h"
  28. #include "sb_pass.h"
  29.  
  30. namespace r600_sb {
  31.  
  32. bool dump::visit(node& n, bool enter) {
  33.         if (enter) {
  34.                 indent();
  35.                 dump_flags(n);
  36.  
  37.                 switch (n.subtype) {
  38.                         case NST_PHI:
  39.                                 dump_op(n, "* phi");
  40.                                 break;
  41.                         case NST_PSI:
  42.                                 dump_op(n, "* psi");
  43.                                 break;
  44.                         case NST_COPY:
  45.                                 dump_op(n, "* copy");
  46.                                 break;
  47.                         default:
  48.                                 assert(!"invalid node subtype");
  49.                                 break;
  50.                 }
  51.                 sblog << "\n";
  52.         }
  53.         return false;
  54. }
  55.  
  56. bool dump::visit(container_node& n, bool enter) {
  57.         if (enter) {
  58.                 if (!n.empty()) {
  59.                         indent();
  60.                         dump_flags(n);
  61.                         sblog << "{  ";
  62.                         if (!n.dst.empty()) {
  63.                                 sblog << " preloaded inputs [";
  64.                                 dump_vec(n.dst);
  65.                                 sblog << "]  ";
  66.                         }
  67.                         dump_live_values(n, true);
  68.                 }
  69.                 ++level;
  70.         } else {
  71.                 --level;
  72.                 if (!n.empty()) {
  73.                         indent();
  74.                         sblog << "}  ";
  75.                         if (!n.src.empty()) {
  76.                                 sblog << " results [";
  77.                                 dump_vec(n.src);
  78.                                 sblog << "]  ";
  79.                         }
  80.                         dump_live_values(n, false);
  81.                 }
  82.         }
  83.         return true;
  84. }
  85.  
  86. bool dump::visit(bb_node& n, bool enter) {
  87.         if (enter) {
  88.                 indent();
  89.                 dump_flags(n);
  90.                 sblog << "{ BB_" << n.id << "    loop_level = " << n.loop_level << "  ";
  91.                 dump_live_values(n, true);
  92.                 ++level;
  93.         } else {
  94.                 --level;
  95.                 indent();
  96.                 sblog << "} end BB_" << n.id << "  ";
  97.                 dump_live_values(n, false);
  98.         }
  99.         return true;
  100. }
  101.  
  102. bool dump::visit(alu_group_node& n, bool enter) {
  103.         if (enter) {
  104.                 indent();
  105.                 dump_flags(n);
  106.                 sblog << "[  ";
  107.                 dump_live_values(n, true);
  108.  
  109.                 ++level;
  110.         } else {
  111.                 --level;
  112.  
  113.                 indent();
  114.                 sblog << "]  ";
  115.                 dump_live_values(n, false);
  116.         }
  117.         return true;
  118. }
  119.  
  120. bool dump::visit(cf_node& n, bool enter) {
  121.         if (enter) {
  122.                 indent();
  123.                 dump_flags(n);
  124.                 dump_op(n, n.bc.op_ptr->name);
  125.  
  126.                 if (n.bc.op_ptr->flags & CF_BRANCH) {
  127.                         sblog << " @" << (n.bc.addr << 1);
  128.                 }
  129.  
  130.                 dump_common(n);
  131.                 sblog << "\n";
  132.  
  133.                 if (!n.empty()) {
  134.                         indent();
  135.                         sblog << "<  ";
  136.                         dump_live_values(n, true);
  137.                 }
  138.  
  139.                 ++level;
  140.         } else {
  141.                 --level;
  142.                 if (!n.empty()) {
  143.                         indent();
  144.                         sblog << ">  ";
  145.                         dump_live_values(n, false);
  146.                 }
  147.         }
  148.         return true;
  149. }
  150.  
  151. bool dump::visit(alu_node& n, bool enter) {
  152.         if (enter) {
  153.                 indent();
  154.                 dump_flags(n);
  155.                 dump_alu(&n);
  156.                 dump_common(n);
  157.                 sblog << "\n";
  158.  
  159.                 ++level;
  160.         } else {
  161.                 --level;
  162.  
  163.         }
  164.         return true;
  165. }
  166.  
  167. bool dump::visit(alu_packed_node& n, bool enter) {
  168.         if (enter) {
  169.                 indent();
  170.                 dump_flags(n);
  171.                 dump_op(n, n.op_ptr()->name);
  172.                 sblog << "  ";
  173.                 dump_live_values(n, true);
  174.  
  175.                 ++level;
  176.         } else {
  177.                 --level;
  178.                 if (!n.live_after.empty()) {
  179.                         indent();
  180.                         dump_live_values(n, false);
  181.                 }
  182.  
  183.         }
  184.         // proccess children only if their src/dst aren't moved to this node yet
  185.         return n.src.empty();
  186. }
  187.  
  188. bool dump::visit(fetch_node& n, bool enter) {
  189.         if (enter) {
  190.                 indent();
  191.                 dump_flags(n);
  192.                 dump_op(n, n.bc.op_ptr->name);
  193.                 sblog << "\n";
  194.  
  195.                 ++level;
  196.         } else {
  197.                 --level;
  198.         }
  199.         return true;
  200. }
  201.  
  202. bool dump::visit(region_node& n, bool enter) {
  203.         if (enter) {
  204.                 indent();
  205.                 dump_flags(n);
  206.                 sblog << "region #" << n.region_id << "   ";
  207.                 dump_common(n);
  208.  
  209.                 if (!n.vars_defined.empty()) {
  210.                         sblog << "vars_defined: ";
  211.                         dump_set(sh, n.vars_defined);
  212.                 }
  213.  
  214.                 dump_live_values(n, true);
  215.  
  216.                 ++level;
  217.  
  218.                 if (n.loop_phi)
  219.                         run_on(*n.loop_phi);
  220.         } else {
  221.                 --level;
  222.  
  223.                 if (n.phi)
  224.                         run_on(*n.phi);
  225.  
  226.                 indent();
  227.                 dump_live_values(n, false);
  228.         }
  229.         return true;
  230. }
  231.  
  232. bool dump::visit(repeat_node& n, bool enter) {
  233.         if (enter) {
  234.                 indent();
  235.                 dump_flags(n);
  236.                 sblog << "repeat region #" << n.target->region_id;
  237.                 sblog << (n.empty() ? "   " : " after {  ");
  238.                 dump_common(n);
  239.                 sblog << "   ";
  240.                 dump_live_values(n, true);
  241.  
  242.                 ++level;
  243.         } else {
  244.                 --level;
  245.  
  246.                 if (!n.empty()) {
  247.                         indent();
  248.                         sblog << "} end_repeat   ";
  249.                         dump_live_values(n, false);
  250.                 }
  251.         }
  252.         return true;
  253. }
  254.  
  255. bool dump::visit(depart_node& n, bool enter) {
  256.         if (enter) {
  257.                 indent();
  258.                 dump_flags(n);
  259.                 sblog << "depart region #" << n.target->region_id;
  260.                 sblog << (n.empty() ? "   " : " after {  ");
  261.                 dump_common(n);
  262.                 sblog << "  ";
  263.                 dump_live_values(n, true);
  264.  
  265.                 ++level;
  266.         } else {
  267.                 --level;
  268.                 if (!n.empty()) {
  269.                         indent();
  270.                         sblog << "} end_depart   ";
  271.                         dump_live_values(n, false);
  272.                 }
  273.         }
  274.         return true;
  275. }
  276.  
  277. bool dump::visit(if_node& n, bool enter) {
  278.         if (enter) {
  279.                 indent();
  280.                 dump_flags(n);
  281.                 sblog << "if " << *n.cond << "    ";
  282.                 dump_common(n);
  283.                 sblog << "   ";
  284.                 dump_live_values(n, true);
  285.  
  286.                 indent();
  287.                 sblog <<"{\n";
  288.  
  289.                 ++level;
  290.         } else {
  291.                 --level;
  292.                 indent();
  293.                 sblog << "} endif   ";
  294.                 dump_live_values(n, false);
  295.         }
  296.         return true;
  297. }
  298.  
  299. void dump::indent() {
  300.         sblog.print_wl("", level * 4);
  301. }
  302.  
  303. void dump::dump_vec(const vvec & vv) {
  304.         bool first = true;
  305.         for(vvec::const_iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
  306.                 value *v = *I;
  307.                 if (!first)
  308.                         sblog << ", ";
  309.                 else
  310.                         first = false;
  311.  
  312.                 if (v) {
  313.                         sblog << *v;
  314.                 } else {
  315.                         sblog << "__";
  316.                 }
  317.         }
  318. }
  319.  
  320. void dump::dump_rels(vvec & vv) {
  321.         for(vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
  322.                 value *v = *I;
  323.  
  324.                 if (!v || !v->is_rel())
  325.                         continue;
  326.  
  327.                 sblog << "\n\t\t\t\t\t";
  328.                 sblog << "    rels: " << *v << " : ";
  329.                 dump_vec(v->mdef);
  330.                 sblog << " <= ";
  331.                 dump_vec(v->muse);
  332.         }
  333. }
  334.  
  335. void dump::dump_op(node &n, const char *name) {
  336.  
  337.         if (n.pred) {
  338.                 alu_node &a = static_cast<alu_node&>(n);
  339.                 sblog << (a.bc.pred_sel-2) << " [" << *a.pred << "] ";
  340.         }
  341.  
  342.         sblog << name;
  343.  
  344.         bool has_dst = !n.dst.empty();
  345.  
  346.         if (n.subtype == NST_CF_INST) {
  347.                 cf_node *c = static_cast<cf_node*>(&n);
  348.                 if (c->bc.op_ptr->flags & CF_EXP) {
  349.                         static const char *exp_type[] = {"PIXEL", "POS  ", "PARAM"};
  350.                         sblog << "  " << exp_type[c->bc.type] << " " << c->bc.array_base;
  351.                         has_dst = false;
  352.                 } else if (c->bc.op_ptr->flags & (CF_MEM)) {
  353.                         static const char *exp_type[] = {"WRITE", "WRITE_IND", "WRITE_ACK",
  354.                                         "WRITE_IND_ACK"};
  355.                         sblog << "  " << exp_type[c->bc.type] << " " << c->bc.array_base
  356.                                         << "   ES:" << c->bc.elem_size;
  357.                         if (!(c->bc.op_ptr->flags & CF_EMIT)) {
  358.                                 has_dst = false;
  359.                         }
  360.                 }
  361.         }
  362.  
  363.         sblog << "     ";
  364.  
  365.         if (has_dst) {
  366.                 dump_vec(n.dst);
  367.                 sblog << ",       ";
  368.         }
  369.  
  370.         dump_vec(n.src);
  371. }
  372.  
  373. void dump::dump_set(shader &sh, val_set& v) {
  374.         sblog << "[";
  375.         for(val_set::iterator I = v.begin(sh), E = v.end(sh); I != E; ++I) {
  376.                 value *val = *I;
  377.                 sblog << *val << " ";
  378.         }
  379.         sblog << "]";
  380. }
  381.  
  382. void dump::dump_common(node& n) {
  383. }
  384.  
  385. void dump::dump_flags(node &n) {
  386.         if (n.flags & NF_DEAD)
  387.                 sblog << "### DEAD  ";
  388.         if (n.flags & NF_REG_CONSTRAINT)
  389.                 sblog << "R_CONS  ";
  390.         if (n.flags & NF_CHAN_CONSTRAINT)
  391.                 sblog << "CH_CONS  ";
  392.         if (n.flags & NF_ALU_4SLOT)
  393.                 sblog << "4S  ";
  394. }
  395.  
  396. void dump::dump_val(value* v) {
  397.         sblog << *v;
  398. }
  399.  
  400. void dump::dump_alu(alu_node *n) {
  401.  
  402.         if (n->is_copy_mov())
  403.                 sblog << "(copy) ";
  404.  
  405.         if (n->pred) {
  406.                 sblog << (n->bc.pred_sel-2) << " [" << *n->pred << "] ";
  407.         }
  408.  
  409.         sblog << n->bc.op_ptr->name;
  410.  
  411.         if (n->bc.omod) {
  412.                 static const char *omod_str[] = {"", "*2", "*4", "/2"};
  413.                 sblog << omod_str[n->bc.omod];
  414.         }
  415.  
  416.         if (n->bc.clamp) {
  417.                 sblog << "_sat";
  418.         }
  419.  
  420.         bool has_dst = !n->dst.empty();
  421.  
  422.         sblog << "     ";
  423.  
  424.         if (has_dst) {
  425.                 dump_vec(n->dst);
  426.                 sblog << ",    ";
  427.         }
  428.  
  429.         unsigned s = 0;
  430.         for (vvec::iterator I = n->src.begin(), E = n->src.end(); I != E;
  431.                         ++I, ++s) {
  432.  
  433.                 bc_alu_src &src = n->bc.src[s];
  434.  
  435.                 if (src.neg)
  436.                         sblog << "-";
  437.  
  438.                 if (src.abs)
  439.                         sblog << "|";
  440.  
  441.                 dump_val(*I);
  442.  
  443.                 if (src.abs)
  444.                         sblog << "|";
  445.  
  446.                 if (I + 1 != E)
  447.                         sblog << ", ";
  448.         }
  449.  
  450.         dump_rels(n->dst);
  451.         dump_rels(n->src);
  452.  
  453. }
  454.  
  455. void dump::dump_op(node* n) {
  456.         if (n->type == NT_IF) {
  457.                 dump_op(*n, "IF ");
  458.                 return;
  459.         }
  460.  
  461.         switch(n->subtype) {
  462.         case NST_ALU_INST:
  463.                 dump_alu(static_cast<alu_node*>(n));
  464.                 break;
  465.         case NST_FETCH_INST:
  466.                 dump_op(*n, static_cast<fetch_node*>(n)->bc.op_ptr->name);
  467.                 break;
  468.         case NST_CF_INST:
  469.         case NST_ALU_CLAUSE:
  470.         case NST_TEX_CLAUSE:
  471.         case NST_VTX_CLAUSE:
  472.                 dump_op(*n, static_cast<cf_node*>(n)->bc.op_ptr->name);
  473.                 break;
  474.         case NST_ALU_PACKED_INST:
  475.                 dump_op(*n, static_cast<alu_packed_node*>(n)->op_ptr()->name);
  476.                 break;
  477.         case NST_PHI:
  478.                 dump_op(*n, "PHI");
  479.                 break;
  480.         case NST_PSI:
  481.                 dump_op(*n, "PSI");
  482.                 break;
  483.         case NST_COPY:
  484.                 dump_op(*n, "COPY");
  485.                 break;
  486.         default:
  487.                 dump_op(*n, "??unknown_op");
  488.         }
  489. }
  490.  
  491. void dump::dump_op_list(container_node* c) {
  492.         for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) {
  493.                 dump_op(*I);
  494.                 sblog << "\n";
  495.         }
  496. }
  497.  
  498. void dump::dump_queue(sched_queue& q) {
  499.         for (sched_queue::iterator I = q.begin(), E = q.end(); I != E; ++I) {
  500.                 dump_op(*I);
  501.                 sblog << "\n";
  502.         }
  503. }
  504.  
  505. void dump::dump_live_values(container_node &n, bool before) {
  506.         if (before) {
  507.                 if (!n.live_before.empty()) {
  508.                         sblog << "live_before: ";
  509.                         dump_set(sh, n.live_before);
  510.                 }
  511.         } else {
  512.                 if (!n.live_after.empty()) {
  513.                         sblog << "live_after: ";
  514.                         dump_set(sh, n.live_after);
  515.                 }
  516.         }
  517.         sblog << "\n";
  518. }
  519.  
  520. } // namespace r600_sb
  521.