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