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