Home | History | Annotate | Download | only in sb
      1 /*
      2  * Copyright 2013 Vadim Girlin <vadimgirlin (at) 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 
     29 #include "sb_pass.h"
     30 
     31 namespace r600_sb {
     32 
     33 int dce_cleanup::run() {
     34 	int r;
     35 
     36 	// Run cleanup for as long as there are unused nodes.
     37 	do {
     38 		nodes_changed = false;
     39 		r = vpass::run();
     40 	} while (r == 0 && nodes_changed);
     41 
     42 	return r;
     43 }
     44 
     45 bool dce_cleanup::visit(node& n, bool enter) {
     46 	if (enter) {
     47 	} else {
     48 		if (n.flags & NF_DEAD)
     49 			n.remove();
     50 		else
     51 			cleanup_dst(n);
     52 	}
     53 	return true;
     54 }
     55 
     56 bool dce_cleanup::visit(alu_group_node& n, bool enter) {
     57 	if (enter) {
     58 	} else {
     59 		n.expand();
     60 	}
     61 	return true;
     62 }
     63 
     64 bool dce_cleanup::visit(cf_node& n, bool enter) {
     65 	if (enter) {
     66 		if (n.flags & NF_DEAD)
     67 			n.remove();
     68 		else
     69 			cleanup_dst(n);
     70 	} else {
     71 		if ((sh.dce_flags & DF_EXPAND) &&
     72 				(n.bc.op_ptr->flags & (CF_CLAUSE | CF_BRANCH | CF_LOOP)))
     73 			n.expand();
     74 	}
     75 	return true;
     76 }
     77 
     78 bool dce_cleanup::visit(alu_node& n, bool enter) {
     79 	if (enter) {
     80 	} else {
     81 		if (n.flags & NF_DEAD)
     82 			n.remove();
     83 		else
     84 			cleanup_dst(n);
     85 	}
     86 	return true;
     87 }
     88 
     89 bool dce_cleanup::visit(alu_packed_node& n, bool enter) {
     90 	if (enter) {
     91 	} else {
     92 		if (n.flags & NF_DEAD)
     93 			n.remove();
     94 		else
     95 			cleanup_dst(n);
     96 	}
     97 	return false;
     98 }
     99 
    100 bool dce_cleanup::visit(fetch_node& n, bool enter) {
    101 	if (enter) {
    102 	} else {
    103 		if (n.flags & NF_DEAD)
    104 			n.remove();
    105 		else
    106 			cleanup_dst(n);
    107 	}
    108 	return true;
    109 }
    110 
    111 bool dce_cleanup::visit(region_node& n, bool enter) {
    112 	if (enter) {
    113 		if (n.loop_phi)
    114 			run_on(*n.loop_phi);
    115 	} else {
    116 		if (n.phi)
    117 			run_on(*n.phi);
    118 	}
    119 	return true;
    120 }
    121 
    122 void dce_cleanup::cleanup_dst(node& n) {
    123 	if (!cleanup_dst_vec(n.dst) && remove_unused &&
    124 			!n.dst.empty() && !(n.flags & NF_DONT_KILL) && n.parent)
    125 	{
    126 		// Delete use references to the removed node from the src values.
    127 		for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
    128 			value* v = *I;
    129 			if (v && v->def && v->uses.size())
    130 			{
    131 				v->remove_use(&n);
    132 			}
    133 		}
    134 		n.remove();
    135 		nodes_changed = true;
    136 	}
    137 }
    138 
    139 bool dce_cleanup::visit(container_node& n, bool enter) {
    140 	if (enter)
    141 		cleanup_dst(n);
    142 	return true;
    143 }
    144 
    145 bool dce_cleanup::cleanup_dst_vec(vvec& vv) {
    146 	bool alive = false;
    147 
    148 	for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
    149 		value* &v = *I;
    150 		if (!v)
    151 			continue;
    152 
    153 		if (v->gvn_source && v->gvn_source->is_dead())
    154 			v->gvn_source = NULL;
    155 
    156 		if (v->is_dead() || (remove_unused && !v->is_rel() && !v->uses.size()))
    157 			v = NULL;
    158 		else
    159 			alive = true;
    160 	}
    161 
    162 	return alive;
    163 }
    164 
    165 } // namespace r600_sb
    166