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 29#include "sb_pass.h" 30 31namespace r600_sb { 32 33bool r600_sb::psi_ops::visit(alu_node& n, bool enter) { 34 if (enter) { 35 } 36 return false; 37} 38 39bool psi_ops::visit(node& n, bool enter) { 40 if (enter) { 41 assert(n.subtype == NST_PSI); 42 43 try_inline(n); 44 45 // TODO eliminate predication until there is full support in all passes 46 // unpredicate instructions and replace psi-nodes with conditional moves 47 eliminate(n); 48 } 49 return false; 50} 51 52value* get_pred_val(node &n) { 53 value *pred_val = NULL; 54 55 for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; I += 3) { 56 value* &pred = *I; 57 if (pred) { 58 if (!pred_val) 59 pred_val = pred; 60 else { 61 assert(pred == pred_val); 62 } 63 } 64 } 65 return pred_val; 66} 67 68// for now we'll never inline psi's with different predicate values, 69// so psi node may only contain the refs to one predicate value. 70bool psi_ops::try_inline(node& n) { 71 assert(n.subtype == NST_PSI); 72 73 vvec &ns = n.src; 74 75 int sz = ns.size(); 76 assert(sz && (sz % 3 == 0)); 77 78 value *pred_val = get_pred_val(n); 79 80 int ps_mask = 0; 81 82 bool r = false; 83 84 for (int i = sz - 1; i >= 0; i -= 3) { 85 86 if (ps_mask == 3) { 87 ns.erase(ns.begin(), ns.begin() + i + 1); 88 return r; 89 } 90 91 value* val = ns[i]; 92 value* predsel = ns[i-1]; 93 int ps = !predsel ? 3 : predsel == sh.get_pred_sel(0) ? 1 : 2; 94 95 assert(val->def); 96 97 if (val->def->subtype == NST_PSI && ps == 3) { 98 if (get_pred_val(*val->def) != pred_val) 99 continue; 100 101 vvec &ds = val->def->src; 102 103 ns.insert(ns.begin() + i + 1, ds.begin(), ds.end()); 104 ns.erase(ns.begin() + i - 2, ns.begin() + i + 1); 105 i += ds.size(); 106 r = true; 107 108 } else { 109 if ((ps_mask & ps) == ps) { 110 // this predicate select is subsumed by already handled ops 111 ns.erase(ns.begin() + i - 2, ns.begin() + i + 1); 112 } else { 113 ps_mask |= ps; 114 } 115 } 116 } 117 return r; 118} 119 120bool psi_ops::try_reduce(node& n) { 121 assert(n.subtype == NST_PSI); 122 assert(n.src.size() % 3 == 0); 123 124 // TODO 125 126 return false; 127} 128 129void psi_ops::unpredicate(node *n) { 130 131 if (!n->is_alu_inst()) 132 return; 133 134 alu_node *a = static_cast<alu_node*>(n); 135 a->pred = NULL; 136} 137 138bool psi_ops::eliminate(node& n) { 139 assert(n.subtype == NST_PSI); 140 assert(n.src.size() == 6); 141 142 value *d = n.dst[0]; 143 144 value *s1 = n.src[2]; 145 value *s2 = n.src[5]; 146 147 value *pred = n.src[3]; 148 149 bool psel = n.src[4] == sh.get_pred_sel(0); 150 151 value *sel = get_select_value_for_em(sh, pred); 152 153 if (s1->is_undef()) { 154 if (s2->is_undef()) { 155 156 } else { 157 n.insert_after(sh.create_mov(d, s2)); 158 } 159 } else if (s2->is_undef()) { 160 n.insert_after(sh.create_mov(d, s1)); 161 } else { 162 alu_node *a = sh.create_alu(); 163 a->bc.set_op(ALU_OP3_CNDE_INT); 164 165 a->dst.push_back(d); 166 a->src.push_back(sel); 167 168 if (psel) { 169 a->src.push_back(s1); 170 a->src.push_back(s2); 171 } else { 172 a->src.push_back(s2); 173 a->src.push_back(s1); 174 } 175 176 n.insert_after(a); 177 } 178 179 n.remove(); 180 181 if (s1->is_any_gpr() && !s1->is_undef() && s1->def) 182 unpredicate(s1->def); 183 if (s2->is_any_gpr() && !s2->is_undef() && s2->def) 184 unpredicate(s2->def); 185 186 return false; 187} 188 189} // namespace r600_sb 190