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_bc.h" 28 #include "sb_shader.h" 29 #include "sb_pass.h" 30 31 namespace r600_sb { 32 33 bool node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 34 bool container_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 35 bool alu_group_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 36 bool alu_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 37 bool cf_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 38 bool fetch_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 39 bool region_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 40 41 bool repeat_node::accept(vpass& p, bool enter) { 42 return p.visit(*this, enter); 43 } 44 45 bool depart_node::accept(vpass& p, bool enter) { 46 return p.visit(*this, enter); 47 } 48 bool if_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 49 bool bb_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); } 50 bool alu_packed_node::accept(vpass& p, bool enter) { 51 return p.visit(*this, enter); 52 } 53 54 void alu_packed_node::init_args(bool repl) { 55 alu_node *p = static_cast<alu_node*>(first); 56 assert(p->is_valid()); 57 while (p) { 58 dst.insert(dst.end(), p->dst.begin(), p->dst.end()); 59 src.insert(src.end(), p->src.begin(), p->src.end()); 60 p = static_cast<alu_node*>(p->next); 61 } 62 63 value *replicated_value = NULL; 64 65 for (vvec::iterator I = dst.begin(), E = dst.end(); I != E; ++I) { 66 value *v = *I; 67 if (v) { 68 if (repl) { 69 if (replicated_value) 70 v->assign_source(replicated_value); 71 else 72 replicated_value = v; 73 } 74 75 v->def = this; 76 } 77 } 78 } 79 80 void container_node::insert_node_before(node* s, node* n) { 81 if (s->prev) { 82 node *sp = s->prev; 83 sp->next = n; 84 n->prev = sp; 85 n->next = s; 86 s->prev = n; 87 } else { 88 n->next = s; 89 s->prev = n; 90 first = n; 91 } 92 n->parent = this; 93 } 94 95 void container_node::insert_node_after(node* s, node* n) { 96 if (s->next) { 97 node *sn = s->next; 98 sn->prev = n; 99 n->next = sn; 100 n->prev = s; 101 s->next = n; 102 } else { 103 n->prev = s; 104 s->next = n; 105 last = n; 106 } 107 n->parent = this; 108 } 109 110 void container_node::move(iterator b, iterator e) { 111 assert(b != e); 112 113 container_node *source_container = b->parent; 114 node *l = source_container->cut(b, e); 115 116 first = last = l; 117 first->parent = this; 118 119 while (last->next) { 120 last = last->next; 121 last->parent = this; 122 } 123 } 124 125 node* container_node::cut(iterator b, iterator e) { 126 assert(!*b || b->parent == this); 127 assert(!*e || e->parent == this); 128 assert(b != e); 129 130 if (b->prev) { 131 b->prev->next = *e; 132 } else { 133 first = *e; 134 } 135 136 if (*e) { 137 e->prev->next = NULL; 138 e->prev = b->prev; 139 } else { 140 last->next = NULL; 141 last = b->prev; 142 } 143 144 b->prev = NULL; 145 146 return *b; 147 } 148 149 unsigned container_node::count() { 150 unsigned c = 0; 151 node *t = first; 152 while (t) { 153 t = t->next; 154 c++; 155 } 156 return c; 157 } 158 159 void container_node::remove_node(node *n) { 160 if (n->prev) 161 n->prev->next = n->next; 162 else 163 first = n->next; 164 if (n->next) 165 n->next->prev = n->prev; 166 else 167 last = n->prev; 168 n->parent = NULL; 169 } 170 171 void container_node::expand(container_node *n) { 172 if (!n->empty()) { 173 node *e0 = n->first; 174 node *e1 = n->last; 175 176 e0->prev = n->prev; 177 if (e0->prev) { 178 e0->prev->next = e0; 179 } else { 180 first = e0; 181 } 182 183 e1->next = n->next; 184 if (e1->next) 185 e1->next->prev = e1; 186 else 187 last = e1; 188 189 do { 190 e0->parent = this; 191 e0 = e0->next; 192 } while (e0 != e1->next); 193 } else 194 remove_node(n); 195 } 196 197 void container_node::push_back(node *n) { 198 if (last) { 199 last->next = n; 200 n->next = NULL; 201 n->prev = last; 202 last = n; 203 } else { 204 assert(!first); 205 first = last = n; 206 n->prev = n->next = NULL; 207 } 208 n->parent = this; 209 } 210 void container_node::push_front(node *n) { 211 if (first) { 212 first->prev = n; 213 n->prev = NULL; 214 n->next = first; 215 first = n; 216 } else { 217 assert(!last); 218 first = last = n; 219 n->prev = n->next = NULL; 220 } 221 n->parent = this; 222 } 223 224 void node::insert_before(node* n) { 225 parent->insert_node_before(this, n); 226 } 227 228 void node::insert_after(node* n) { 229 parent->insert_node_after(this, n); 230 } 231 232 void node::replace_with(node* n) { 233 n->prev = prev; 234 n->next = next; 235 n->parent = parent; 236 if (prev) 237 prev->next = n; 238 if (next) 239 next->prev = n; 240 241 if (parent->first == this) 242 parent->first = n; 243 244 if (parent->last == this) 245 parent->last = n; 246 247 parent = NULL; 248 next = prev = NULL; 249 } 250 251 void container_node::expand() { 252 parent->expand(this); 253 } 254 255 void node::remove() {parent->remove_node(this); 256 } 257 258 value_hash node::hash_src() const { 259 260 value_hash h = 12345; 261 262 for (int k = 0, e = src.size(); k < e; ++k) { 263 value *s = src[k]; 264 if (s) 265 h ^= (s->hash()); 266 } 267 268 return h; 269 } 270 271 272 value_hash node::hash() const { 273 274 if (parent && parent->subtype == NST_LOOP_PHI_CONTAINER) 275 return 47451; 276 277 return hash_src() ^ (subtype << 13) ^ (type << 3); 278 } 279 280 void r600_sb::container_node::append_from(container_node* c) { 281 if (!c->first) 282 return; 283 284 node *b = c->first; 285 286 if (last) { 287 last->next = c->first; 288 last->next->prev = last; 289 } else { 290 first = c->first; 291 } 292 293 last = c->last; 294 c->first = NULL; 295 c->last = NULL; 296 297 while (b) { 298 b->parent = this; 299 b = b->next; 300 } 301 } 302 303 bool node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); } 304 bool container_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); } 305 bool alu_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); } 306 bool alu_packed_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); } 307 bool fetch_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); } 308 bool cf_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); } 309 310 unsigned alu_packed_node::get_slot_mask() { 311 unsigned mask = 0; 312 for (node_iterator I = begin(), E = end(); I != E; ++I) 313 mask |= 1 << static_cast<alu_node*>(*I)->bc.slot; 314 return mask; 315 } 316 317 void alu_packed_node::update_packed_items(sb_context &ctx) { 318 319 vvec::iterator SI(src.begin()), DI(dst.begin()); 320 321 assert(first); 322 323 alu_node *c = static_cast<alu_node*>(first); 324 unsigned flags = c->bc.op_ptr->flags; 325 unsigned slot_flags = c->bc.slot_flags; 326 327 // fixup dst for instructions that replicate output 328 if (((flags & AF_REPL) && slot_flags == AF_4V) || 329 (ctx.is_cayman() && slot_flags == AF_S)) { 330 331 value *swp[4] = {}; 332 333 unsigned chan; 334 335 for (vvec::iterator I2 = dst.begin(), E2 = dst.end(); 336 I2 != E2; ++I2) { 337 value *v = *I2; 338 if (v) { 339 chan = v->get_final_chan(); 340 assert(!swp[chan] || swp[chan] == v); 341 swp[chan] = v; 342 } 343 } 344 345 chan = 0; 346 for (vvec::iterator I2 = dst.begin(), E2 = dst.end(); 347 I2 != E2; ++I2, ++chan) { 348 *I2 = swp[chan]; 349 } 350 } 351 352 for (node_iterator I = begin(), E = end(); I != E; ++I) { 353 alu_node *n = static_cast<alu_node*>(*I); 354 assert(n); 355 356 for (vvec::iterator I2 = n->src.begin(), E2 = n->src.end(); 357 I2 != E2; ++I2, ++SI) { 358 *I2 = *SI; 359 } 360 for (vvec::iterator I2 = n->dst.begin(), E2 = n->dst.end(); 361 I2 != E2; ++I2, ++DI) { 362 *I2 = *DI; 363 } 364 } 365 } 366 367 bool node::is_cf_op(unsigned op) { 368 if (!is_cf_inst()) 369 return false; 370 cf_node *c = static_cast<cf_node*>(this); 371 return c->bc.op == op; 372 } 373 374 bool node::is_alu_op(unsigned op) { 375 if (!is_alu_inst()) 376 return false; 377 alu_node *c = static_cast<alu_node*>(this); 378 return c->bc.op == op; 379 } 380 381 bool node::is_fetch_op(unsigned op) { 382 if (!is_fetch_inst()) 383 return false; 384 fetch_node *c = static_cast<fetch_node*>(this); 385 return c->bc.op == op; 386 } 387 388 389 390 bool node::is_mova() { 391 if (!is_alu_inst()) 392 return false; 393 alu_node *a = static_cast<alu_node*>(this); 394 return (a->bc.op_ptr->flags & AF_MOVA); 395 } 396 397 bool node::is_pred_set() { 398 if (!is_alu_inst()) 399 return false; 400 alu_node *a = static_cast<alu_node*>(this); 401 return (a->bc.op_ptr->flags & AF_ANY_PRED); 402 } 403 404 unsigned node::cf_op_flags() { 405 assert(is_cf_inst()); 406 cf_node *c = static_cast<cf_node*>(this); 407 return c->bc.op_ptr->flags; 408 } 409 410 unsigned node::alu_op_flags() { 411 assert(is_alu_inst()); 412 alu_node *c = static_cast<alu_node*>(this); 413 return c->bc.op_ptr->flags; 414 } 415 416 unsigned node::fetch_op_flags() { 417 assert(is_fetch_inst()); 418 fetch_node *c = static_cast<fetch_node*>(this); 419 return c->bc.op_ptr->flags; 420 } 421 422 unsigned node::alu_op_slot_flags() { 423 assert(is_alu_inst()); 424 alu_node *c = static_cast<alu_node*>(this); 425 return c->bc.slot_flags; 426 } 427 428 region_node* node::get_parent_region() { 429 node *p = this; 430 while ((p = p->parent)) 431 if (p->is_region()) 432 return static_cast<region_node*>(p); 433 return NULL; 434 } 435 436 unsigned container_node::real_alu_count() { 437 unsigned c = 0; 438 node *t = first; 439 while (t) { 440 if (t->is_alu_inst()) 441 ++c; 442 else if (t->is_alu_packed()) 443 c += static_cast<container_node*>(t)->count(); 444 t = t->next; 445 } 446 return c; 447 } 448 449 void container_node::collect_stats(node_stats& s) { 450 451 for (node_iterator I = begin(), E = end(); I != E; ++I) { 452 node *n = *I; 453 if (n->is_container()) { 454 static_cast<container_node*>(n)->collect_stats(s); 455 } 456 457 if (n->is_alu_inst()) { 458 ++s.alu_count; 459 alu_node *a = static_cast<alu_node*>(n); 460 if (a->bc.op_ptr->flags & AF_KILL) 461 ++s.alu_kill_count; 462 else if (a->is_copy_mov()) 463 ++s.alu_copy_mov_count; 464 } else if (n->is_fetch_inst()) 465 ++s.fetch_count; 466 else if (n->is_cf_inst()) 467 ++s.cf_count; 468 else if (n->is_region()) { 469 ++s.region_count; 470 region_node *r = static_cast<region_node*>(n); 471 if(r->is_loop()) 472 ++s.loop_count; 473 474 if (r->phi) 475 s.phi_count += r->phi->count(); 476 if (r->loop_phi) 477 s.loop_phi_count += r->loop_phi->count(); 478 } 479 else if (n->is_depart()) 480 ++s.depart_count; 481 else if (n->is_repeat()) 482 ++s.repeat_count; 483 else if (n->is_if()) 484 ++s.if_count; 485 } 486 } 487 488 void region_node::expand_depart(depart_node *d) { 489 depart_vec::iterator I = departs.begin() + d->dep_id, E; 490 I = departs.erase(I); 491 E = departs.end(); 492 while (I != E) { 493 --(*I)->dep_id; 494 ++I; 495 } 496 d->expand(); 497 } 498 499 void region_node::expand_repeat(repeat_node *r) { 500 repeat_vec::iterator I = repeats.begin() + r->rep_id - 1, E; 501 I = repeats.erase(I); 502 E = repeats.end(); 503 while (I != E) { 504 --(*I)->rep_id; 505 ++I; 506 } 507 r->expand(); 508 } 509 510 void node_stats::dump() { 511 sblog << " alu_count : " << alu_count << "\n"; 512 sblog << " alu_kill_count : " << alu_kill_count << "\n"; 513 sblog << " alu_copy_mov_count : " << alu_copy_mov_count << "\n"; 514 sblog << " cf_count : " << cf_count << "\n"; 515 sblog << " fetch_count : " << fetch_count << "\n"; 516 sblog << " region_count : " << region_count << "\n"; 517 sblog << " loop_count : " << loop_count << "\n"; 518 sblog << " phi_count : " << phi_count << "\n"; 519 sblog << " loop_phi_count : " << loop_phi_count << "\n"; 520 sblog << " depart_count : " << depart_count << "\n"; 521 sblog << " repeat_count : " << repeat_count << "\n"; 522 sblog << " if_count : " << if_count << "\n"; 523 } 524 525 unsigned alu_node::interp_param() { 526 if (!(bc.op_ptr->flags & AF_INTERP)) 527 return 0; 528 unsigned param; 529 if (bc.op_ptr->src_count == 2) { 530 param = src[1]->select.sel(); 531 } else { 532 param = src[0]->select.sel(); 533 } 534 return param + 1; 535 } 536 537 alu_group_node* alu_node::get_alu_group_node() { 538 node *p = parent; 539 if (p) { 540 if (p->subtype == NST_ALU_PACKED_INST) { 541 assert(p->parent && p->parent->subtype == NST_ALU_GROUP); 542 p = p->parent; 543 } 544 return static_cast<alu_group_node*>(p); 545 } 546 return NULL; 547 } 548 549 } // namespace r600_sb 550