loop_analysis.cpp revision 7ec681f3
1/* 2 * Copyright © 2010 Intel Corporation 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * 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 NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "compiler/glsl_types.h" 25#include "loop_analysis.h" 26#include "ir_hierarchical_visitor.h" 27 28static void try_add_loop_terminator(loop_variable_state *ls, ir_if *ir); 29 30static bool all_expression_operands_are_loop_constant(ir_rvalue *, 31 hash_table *); 32 33static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *); 34 35/** 36 * Find an initializer of a variable outside a loop 37 * 38 * Works backwards from the loop to find the pre-loop value of the variable. 39 * This is used, for example, to find the initial value of loop induction 40 * variables. 41 * 42 * \param loop Loop where \c var is an induction variable 43 * \param var Variable whose initializer is to be found 44 * 45 * \return 46 * The \c ir_rvalue assigned to the variable outside the loop. May return 47 * \c NULL if no initializer can be found. 48 */ 49static ir_rvalue * 50find_initial_value(ir_loop *loop, ir_variable *var) 51{ 52 for (exec_node *node = loop->prev; !node->is_head_sentinel(); 53 node = node->prev) { 54 ir_instruction *ir = (ir_instruction *) node; 55 56 switch (ir->ir_type) { 57 case ir_type_call: 58 case ir_type_loop: 59 case ir_type_loop_jump: 60 case ir_type_return: 61 case ir_type_if: 62 return NULL; 63 64 case ir_type_function: 65 case ir_type_function_signature: 66 assert(!"Should not get here."); 67 return NULL; 68 69 case ir_type_assignment: { 70 ir_assignment *assign = ir->as_assignment(); 71 ir_variable *assignee = assign->lhs->whole_variable_referenced(); 72 73 if (assignee == var) 74 return (assign->condition != NULL) ? NULL : assign->rhs; 75 76 break; 77 } 78 79 default: 80 break; 81 } 82 } 83 84 return NULL; 85} 86 87 88static int 89calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, 90 enum ir_expression_operation op, bool continue_from_then, 91 bool swap_compare_operands, bool inc_before_terminator) 92{ 93 if (from == NULL || to == NULL || increment == NULL) 94 return -1; 95 96 void *mem_ctx = ralloc_context(NULL); 97 98 ir_expression *const sub = 99 new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from); 100 101 ir_expression *const div = 102 new(mem_ctx) ir_expression(ir_binop_div, sub->type, sub, increment); 103 104 ir_constant *iter = div->constant_expression_value(mem_ctx); 105 if (iter == NULL) { 106 ralloc_free(mem_ctx); 107 return -1; 108 } 109 110 if (!iter->type->is_integer()) { 111 const ir_expression_operation op = iter->type->is_double() 112 ? ir_unop_d2i : ir_unop_f2i; 113 ir_rvalue *cast = 114 new(mem_ctx) ir_expression(op, glsl_type::int_type, iter, NULL); 115 116 iter = cast->constant_expression_value(mem_ctx); 117 } 118 119 int64_t iter_value = iter->get_int64_component(0); 120 121 /* Code after this block works under assumption that iterator will be 122 * incremented or decremented until it hits the limit, 123 * however the loop condition can be false on the first iteration. 124 * Handle such loops first. 125 */ 126 { 127 ir_rvalue *first_value = from; 128 if (inc_before_terminator) { 129 first_value = 130 new(mem_ctx) ir_expression(ir_binop_add, from->type, from, increment); 131 } 132 133 ir_expression *cmp = swap_compare_operands 134 ? new(mem_ctx) ir_expression(op, glsl_type::bool_type, to, first_value) 135 : new(mem_ctx) ir_expression(op, glsl_type::bool_type, first_value, to); 136 if (continue_from_then) 137 cmp = new(mem_ctx) ir_expression(ir_unop_logic_not, cmp); 138 139 ir_constant *const cmp_result = cmp->constant_expression_value(mem_ctx); 140 assert(cmp_result != NULL); 141 if (cmp_result->get_bool_component(0)) { 142 ralloc_free(mem_ctx); 143 return 0; 144 } 145 } 146 147 /* Make sure that the calculated number of iterations satisfies the exit 148 * condition. This is needed to catch off-by-one errors and some types of 149 * ill-formed loops. For example, we need to detect that the following 150 * loop does not have a maximum iteration count. 151 * 152 * for (float x = 0.0; x != 0.9; x += 0.2) 153 * ; 154 */ 155 const int bias[] = { -1, 0, 1 }; 156 bool valid_loop = false; 157 158 for (unsigned i = 0; i < ARRAY_SIZE(bias); i++) { 159 /* Increment may be of type int, uint or float. */ 160 switch (increment->type->base_type) { 161 case GLSL_TYPE_INT: 162 iter = new(mem_ctx) ir_constant(int32_t(iter_value + bias[i])); 163 break; 164 case GLSL_TYPE_INT16: 165 iter = new(mem_ctx) ir_constant(int16_t(iter_value + bias[i])); 166 break; 167 case GLSL_TYPE_INT64: 168 iter = new(mem_ctx) ir_constant(int64_t(iter_value + bias[i])); 169 break; 170 case GLSL_TYPE_UINT: 171 iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i])); 172 break; 173 case GLSL_TYPE_UINT16: 174 iter = new(mem_ctx) ir_constant(uint16_t(iter_value + bias[i])); 175 break; 176 case GLSL_TYPE_UINT64: 177 iter = new(mem_ctx) ir_constant(uint64_t(iter_value + bias[i])); 178 break; 179 case GLSL_TYPE_FLOAT: 180 iter = new(mem_ctx) ir_constant(float(iter_value + bias[i])); 181 break; 182 case GLSL_TYPE_FLOAT16: 183 iter = new(mem_ctx) ir_constant(float16_t(float(iter_value + bias[i]))); 184 break; 185 case GLSL_TYPE_DOUBLE: 186 iter = new(mem_ctx) ir_constant(double(iter_value + bias[i])); 187 break; 188 default: 189 unreachable("Unsupported type for loop iterator."); 190 } 191 192 ir_expression *const mul = 193 new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter, 194 increment); 195 196 ir_expression *const add = 197 new(mem_ctx) ir_expression(ir_binop_add, mul->type, mul, from); 198 199 ir_expression *cmp = swap_compare_operands 200 ? new(mem_ctx) ir_expression(op, glsl_type::bool_type, to, add) 201 : new(mem_ctx) ir_expression(op, glsl_type::bool_type, add, to); 202 if (continue_from_then) 203 cmp = new(mem_ctx) ir_expression(ir_unop_logic_not, cmp); 204 205 ir_constant *const cmp_result = cmp->constant_expression_value(mem_ctx); 206 207 assert(cmp_result != NULL); 208 if (cmp_result->get_bool_component(0)) { 209 iter_value += bias[i]; 210 valid_loop = true; 211 break; 212 } 213 } 214 215 ralloc_free(mem_ctx); 216 217 if (inc_before_terminator) { 218 iter_value--; 219 } 220 221 return (valid_loop) ? iter_value : -1; 222} 223 224static bool 225incremented_before_terminator(ir_loop *loop, ir_variable *var, 226 ir_if *terminator) 227{ 228 for (exec_node *node = loop->body_instructions.get_head(); 229 !node->is_tail_sentinel(); 230 node = node->get_next()) { 231 ir_instruction *ir = (ir_instruction *) node; 232 233 switch (ir->ir_type) { 234 case ir_type_if: 235 if (ir->as_if() == terminator) 236 return false; 237 break; 238 239 case ir_type_assignment: { 240 ir_assignment *assign = ir->as_assignment(); 241 ir_variable *assignee = assign->lhs->whole_variable_referenced(); 242 243 if (assignee == var) { 244 assert(assign->condition == NULL); 245 return true; 246 } 247 248 break; 249 } 250 251 default: 252 break; 253 } 254 } 255 256 unreachable("Unable to find induction variable"); 257} 258 259/** 260 * Record the fact that the given loop variable was referenced inside the loop. 261 * 262 * \arg in_assignee is true if the reference was on the LHS of an assignment. 263 * 264 * \arg in_conditional_code_or_nested_loop is true if the reference occurred 265 * inside an if statement or a nested loop. 266 * 267 * \arg current_assignment is the ir_assignment node that the loop variable is 268 * on the LHS of, if any (ignored if \c in_assignee is false). 269 */ 270void 271loop_variable::record_reference(bool in_assignee, 272 bool in_conditional_code_or_nested_loop, 273 ir_assignment *current_assignment) 274{ 275 if (in_assignee) { 276 assert(current_assignment != NULL); 277 278 if (in_conditional_code_or_nested_loop || 279 current_assignment->condition != NULL) { 280 this->conditional_or_nested_assignment = true; 281 } 282 283 if (this->first_assignment == NULL) { 284 assert(this->num_assignments == 0); 285 286 this->first_assignment = current_assignment; 287 } 288 289 this->num_assignments++; 290 } else if (this->first_assignment == current_assignment) { 291 /* This catches the case where the variable is used in the RHS of an 292 * assignment where it is also in the LHS. 293 */ 294 this->read_before_write = true; 295 } 296} 297 298 299loop_state::loop_state() 300{ 301 this->ht = _mesa_pointer_hash_table_create(NULL); 302 this->mem_ctx = ralloc_context(NULL); 303 this->loop_found = false; 304} 305 306 307loop_state::~loop_state() 308{ 309 _mesa_hash_table_destroy(this->ht, NULL); 310 ralloc_free(this->mem_ctx); 311} 312 313 314loop_variable_state * 315loop_state::insert(ir_loop *ir) 316{ 317 loop_variable_state *ls = new(this->mem_ctx) loop_variable_state; 318 319 _mesa_hash_table_insert(this->ht, ir, ls); 320 this->loop_found = true; 321 322 return ls; 323} 324 325 326loop_variable_state * 327loop_state::get(const ir_loop *ir) 328{ 329 hash_entry *entry = _mesa_hash_table_search(this->ht, ir); 330 return entry ? (loop_variable_state *) entry->data : NULL; 331} 332 333 334loop_variable * 335loop_variable_state::get(const ir_variable *ir) 336{ 337 if (ir == NULL) 338 return NULL; 339 340 hash_entry *entry = _mesa_hash_table_search(this->var_hash, ir); 341 return entry ? (loop_variable *) entry->data : NULL; 342} 343 344 345loop_variable * 346loop_variable_state::insert(ir_variable *var) 347{ 348 void *mem_ctx = ralloc_parent(this); 349 loop_variable *lv = rzalloc(mem_ctx, loop_variable); 350 351 lv->var = var; 352 353 _mesa_hash_table_insert(this->var_hash, lv->var, lv); 354 this->variables.push_tail(lv); 355 356 return lv; 357} 358 359 360loop_terminator * 361loop_variable_state::insert(ir_if *if_stmt, bool continue_from_then) 362{ 363 void *mem_ctx = ralloc_parent(this); 364 loop_terminator *t = new(mem_ctx) loop_terminator(if_stmt, 365 continue_from_then); 366 367 this->terminators.push_tail(t); 368 369 return t; 370} 371 372 373/** 374 * If the given variable already is recorded in the state for this loop, 375 * return the corresponding loop_variable object that records information 376 * about it. 377 * 378 * Otherwise, create a new loop_variable object to record information about 379 * the variable, and set its \c read_before_write field appropriately based on 380 * \c in_assignee. 381 * 382 * \arg in_assignee is true if this variable was encountered on the LHS of an 383 * assignment. 384 */ 385loop_variable * 386loop_variable_state::get_or_insert(ir_variable *var, bool in_assignee) 387{ 388 loop_variable *lv = this->get(var); 389 390 if (lv == NULL) { 391 lv = this->insert(var); 392 lv->read_before_write = !in_assignee; 393 } 394 395 return lv; 396} 397 398 399namespace { 400 401class loop_analysis : public ir_hierarchical_visitor { 402public: 403 loop_analysis(loop_state *loops); 404 405 virtual ir_visitor_status visit(ir_loop_jump *); 406 virtual ir_visitor_status visit(ir_dereference_variable *); 407 408 virtual ir_visitor_status visit_enter(ir_call *); 409 410 virtual ir_visitor_status visit_enter(ir_loop *); 411 virtual ir_visitor_status visit_leave(ir_loop *); 412 virtual ir_visitor_status visit_enter(ir_assignment *); 413 virtual ir_visitor_status visit_leave(ir_assignment *); 414 virtual ir_visitor_status visit_enter(ir_if *); 415 virtual ir_visitor_status visit_leave(ir_if *); 416 417 loop_state *loops; 418 419 int if_statement_depth; 420 421 ir_assignment *current_assignment; 422 423 exec_list state; 424}; 425 426} /* anonymous namespace */ 427 428loop_analysis::loop_analysis(loop_state *loops) 429 : loops(loops), if_statement_depth(0), current_assignment(NULL) 430{ 431 /* empty */ 432} 433 434 435ir_visitor_status 436loop_analysis::visit(ir_loop_jump *ir) 437{ 438 (void) ir; 439 440 assert(!this->state.is_empty()); 441 442 loop_variable_state *const ls = 443 (loop_variable_state *) this->state.get_head(); 444 445 ls->num_loop_jumps++; 446 447 return visit_continue; 448} 449 450 451ir_visitor_status 452loop_analysis::visit_enter(ir_call *) 453{ 454 /* Mark every loop that we're currently analyzing as containing an ir_call 455 * (even those at outer nesting levels). 456 */ 457 foreach_in_list(loop_variable_state, ls, &this->state) { 458 ls->contains_calls = true; 459 } 460 461 return visit_continue_with_parent; 462} 463 464 465ir_visitor_status 466loop_analysis::visit(ir_dereference_variable *ir) 467{ 468 /* If we're not somewhere inside a loop, there's nothing to do. 469 */ 470 if (this->state.is_empty()) 471 return visit_continue; 472 473 bool nested = false; 474 475 foreach_in_list(loop_variable_state, ls, &this->state) { 476 ir_variable *var = ir->variable_referenced(); 477 loop_variable *lv = ls->get_or_insert(var, this->in_assignee); 478 479 lv->record_reference(this->in_assignee, 480 nested || this->if_statement_depth > 0, 481 this->current_assignment); 482 nested = true; 483 } 484 485 return visit_continue; 486} 487 488ir_visitor_status 489loop_analysis::visit_enter(ir_loop *ir) 490{ 491 loop_variable_state *ls = this->loops->insert(ir); 492 this->state.push_head(ls); 493 494 return visit_continue; 495} 496 497ir_visitor_status 498loop_analysis::visit_leave(ir_loop *ir) 499{ 500 loop_variable_state *const ls = 501 (loop_variable_state *) this->state.pop_head(); 502 503 /* Function calls may contain side effects. These could alter any of our 504 * variables in ways that cannot be known, and may even terminate shader 505 * execution (say, calling discard in the fragment shader). So we can't 506 * rely on any of our analysis about assignments to variables. 507 * 508 * We could perform some conservative analysis (prove there's no statically 509 * possible assignment, etc.) but it isn't worth it for now; function 510 * inlining will allow us to unroll loops anyway. 511 */ 512 if (ls->contains_calls) 513 return visit_continue; 514 515 foreach_in_list(ir_instruction, node, &ir->body_instructions) { 516 /* Skip over declarations at the start of a loop. 517 */ 518 if (node->as_variable()) 519 continue; 520 521 ir_if *if_stmt = ((ir_instruction *) node)->as_if(); 522 523 if (if_stmt != NULL) 524 try_add_loop_terminator(ls, if_stmt); 525 } 526 527 528 foreach_in_list_safe(loop_variable, lv, &ls->variables) { 529 /* Move variables that are already marked as being loop constant to 530 * a separate list. These trivially don't need to be tested. 531 */ 532 if (lv->is_loop_constant()) { 533 lv->remove(); 534 ls->constants.push_tail(lv); 535 } 536 } 537 538 /* Each variable assigned in the loop that isn't already marked as being loop 539 * constant might still be loop constant. The requirements at this point 540 * are: 541 * 542 * - Variable is written before it is read. 543 * 544 * - Only one assignment to the variable. 545 * 546 * - All operands on the RHS of the assignment are also loop constants. 547 * 548 * The last requirement is the reason for the progress loop. A variable 549 * marked as a loop constant on one pass may allow other variables to be 550 * marked as loop constant on following passes. 551 */ 552 bool progress; 553 do { 554 progress = false; 555 556 foreach_in_list_safe(loop_variable, lv, &ls->variables) { 557 if (lv->conditional_or_nested_assignment || (lv->num_assignments > 1)) 558 continue; 559 560 /* Process the RHS of the assignment. If all of the variables 561 * accessed there are loop constants, then add this 562 */ 563 ir_rvalue *const rhs = lv->first_assignment->rhs; 564 if (all_expression_operands_are_loop_constant(rhs, ls->var_hash)) { 565 lv->rhs_clean = true; 566 567 if (lv->is_loop_constant()) { 568 progress = true; 569 570 lv->remove(); 571 ls->constants.push_tail(lv); 572 } 573 } 574 } 575 } while (progress); 576 577 /* The remaining variables that are not loop invariant might be loop 578 * induction variables. 579 */ 580 foreach_in_list_safe(loop_variable, lv, &ls->variables) { 581 /* If there is more than one assignment to a variable, it cannot be a 582 * loop induction variable. This isn't strictly true, but this is a 583 * very simple induction variable detector, and it can't handle more 584 * complex cases. 585 */ 586 if (lv->num_assignments > 1) 587 continue; 588 589 /* All of the variables with zero assignments in the loop are loop 590 * invariant, and they should have already been filtered out. 591 */ 592 assert(lv->num_assignments == 1); 593 assert(lv->first_assignment != NULL); 594 595 /* The assignment to the variable in the loop must be unconditional and 596 * not inside a nested loop. 597 */ 598 if (lv->conditional_or_nested_assignment) 599 continue; 600 601 /* Basic loop induction variables have a single assignment in the loop 602 * that has the form 'VAR = VAR + i' or 'VAR = VAR - i' where i is a 603 * loop invariant. 604 */ 605 ir_rvalue *const inc = 606 get_basic_induction_increment(lv->first_assignment, ls->var_hash); 607 if (inc != NULL) { 608 lv->increment = inc; 609 610 lv->remove(); 611 ls->induction_variables.push_tail(lv); 612 } 613 } 614 615 /* Search the loop terminating conditions for those of the form 'i < c' 616 * where i is a loop induction variable, c is a constant, and < is any 617 * relative operator. From each of these we can infer an iteration count. 618 * Also figure out which terminator (if any) produces the smallest 619 * iteration count--this is the limiting terminator. 620 */ 621 foreach_in_list(loop_terminator, t, &ls->terminators) { 622 ir_if *if_stmt = t->ir; 623 624 /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care 625 * about the former here. 626 */ 627 ir_expression *cond = if_stmt->condition->as_expression(); 628 if (cond == NULL) 629 continue; 630 631 switch (cond->operation) { 632 case ir_binop_less: 633 case ir_binop_gequal: { 634 /* The expressions that we care about will either be of the form 635 * 'counter < limit' or 'limit < counter'. Figure out which is 636 * which. 637 */ 638 ir_rvalue *counter = cond->operands[0]->as_dereference_variable(); 639 ir_constant *limit = cond->operands[1]->as_constant(); 640 enum ir_expression_operation cmp = cond->operation; 641 bool swap_compare_operands = false; 642 643 if (limit == NULL) { 644 counter = cond->operands[1]->as_dereference_variable(); 645 limit = cond->operands[0]->as_constant(); 646 swap_compare_operands = true; 647 } 648 649 if ((counter == NULL) || (limit == NULL)) 650 break; 651 652 ir_variable *var = counter->variable_referenced(); 653 654 ir_rvalue *init = find_initial_value(ir, var); 655 656 loop_variable *lv = ls->get(var); 657 if (lv != NULL && lv->is_induction_var()) { 658 bool inc_before_terminator = 659 incremented_before_terminator(ir, var, t->ir); 660 661 t->iterations = calculate_iterations(init, limit, lv->increment, 662 cmp, t->continue_from_then, 663 swap_compare_operands, 664 inc_before_terminator); 665 666 if (t->iterations >= 0 && 667 (ls->limiting_terminator == NULL || 668 t->iterations < ls->limiting_terminator->iterations)) { 669 ls->limiting_terminator = t; 670 } 671 } 672 break; 673 } 674 675 default: 676 break; 677 } 678 } 679 680 return visit_continue; 681} 682 683ir_visitor_status 684loop_analysis::visit_enter(ir_if *ir) 685{ 686 (void) ir; 687 688 if (!this->state.is_empty()) 689 this->if_statement_depth++; 690 691 return visit_continue; 692} 693 694ir_visitor_status 695loop_analysis::visit_leave(ir_if *ir) 696{ 697 (void) ir; 698 699 if (!this->state.is_empty()) 700 this->if_statement_depth--; 701 702 return visit_continue; 703} 704 705ir_visitor_status 706loop_analysis::visit_enter(ir_assignment *ir) 707{ 708 /* If we're not somewhere inside a loop, there's nothing to do. 709 */ 710 if (this->state.is_empty()) 711 return visit_continue_with_parent; 712 713 this->current_assignment = ir; 714 715 return visit_continue; 716} 717 718ir_visitor_status 719loop_analysis::visit_leave(ir_assignment *ir) 720{ 721 /* Since the visit_enter exits with visit_continue_with_parent for this 722 * case, the loop state stack should never be empty here. 723 */ 724 assert(!this->state.is_empty()); 725 726 assert(this->current_assignment == ir); 727 this->current_assignment = NULL; 728 729 return visit_continue; 730} 731 732 733class examine_rhs : public ir_hierarchical_visitor { 734public: 735 examine_rhs(hash_table *loop_variables) 736 { 737 this->only_uses_loop_constants = true; 738 this->loop_variables = loop_variables; 739 } 740 741 virtual ir_visitor_status visit(ir_dereference_variable *ir) 742 { 743 hash_entry *entry = _mesa_hash_table_search(this->loop_variables, 744 ir->var); 745 loop_variable *lv = entry ? (loop_variable *) entry->data : NULL; 746 747 assert(lv != NULL); 748 749 if (lv->is_loop_constant()) { 750 return visit_continue; 751 } else { 752 this->only_uses_loop_constants = false; 753 return visit_stop; 754 } 755 } 756 757 hash_table *loop_variables; 758 bool only_uses_loop_constants; 759}; 760 761 762bool 763all_expression_operands_are_loop_constant(ir_rvalue *ir, hash_table *variables) 764{ 765 examine_rhs v(variables); 766 767 ir->accept(&v); 768 769 return v.only_uses_loop_constants; 770} 771 772 773ir_rvalue * 774get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash) 775{ 776 /* The RHS must be a binary expression. 777 */ 778 ir_expression *const rhs = ir->rhs->as_expression(); 779 if ((rhs == NULL) 780 || ((rhs->operation != ir_binop_add) 781 && (rhs->operation != ir_binop_sub))) 782 return NULL; 783 784 /* One of the of operands of the expression must be the variable assigned. 785 * If the operation is subtraction, the variable in question must be the 786 * "left" operand. 787 */ 788 ir_variable *const var = ir->lhs->variable_referenced(); 789 790 ir_variable *const op0 = rhs->operands[0]->variable_referenced(); 791 ir_variable *const op1 = rhs->operands[1]->variable_referenced(); 792 793 if (((op0 != var) && (op1 != var)) 794 || ((op1 == var) && (rhs->operation == ir_binop_sub))) 795 return NULL; 796 797 ir_rvalue *inc = (op0 == var) ? rhs->operands[1] : rhs->operands[0]; 798 799 if (inc->as_constant() == NULL) { 800 ir_variable *const inc_var = inc->variable_referenced(); 801 if (inc_var != NULL) { 802 hash_entry *entry = _mesa_hash_table_search(var_hash, inc_var); 803 loop_variable *lv = entry ? (loop_variable *) entry->data : NULL; 804 805 if (lv == NULL || !lv->is_loop_constant()) { 806 assert(lv != NULL); 807 inc = NULL; 808 } 809 } else 810 inc = NULL; 811 } 812 813 if ((inc != NULL) && (rhs->operation == ir_binop_sub)) { 814 void *mem_ctx = ralloc_parent(ir); 815 816 inc = new(mem_ctx) ir_expression(ir_unop_neg, 817 inc->type, 818 inc->clone(mem_ctx, NULL), 819 NULL); 820 } 821 822 return inc; 823} 824 825 826/** 827 * Detect whether an if-statement is a loop terminating condition, if so 828 * add it to the list of loop terminators. 829 * 830 * Detects if-statements of the form 831 * 832 * (if (expression bool ...) (...then_instrs...break)) 833 * 834 * or 835 * 836 * (if (expression bool ...) ... (...else_instrs...break)) 837 */ 838void 839try_add_loop_terminator(loop_variable_state *ls, ir_if *ir) 840{ 841 ir_instruction *inst = (ir_instruction *) ir->then_instructions.get_tail(); 842 ir_instruction *else_inst = 843 (ir_instruction *) ir->else_instructions.get_tail(); 844 845 if (is_break(inst) || is_break(else_inst)) 846 ls->insert(ir, is_break(else_inst)); 847} 848 849 850loop_state * 851analyze_loop_variables(exec_list *instructions) 852{ 853 loop_state *loops = new loop_state; 854 loop_analysis v(loops); 855 856 v.run(instructions); 857 return v.loops; 858} 859