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 
28 static void try_add_loop_terminator(loop_variable_state *ls, ir_if *ir);
29 
30 static bool all_expression_operands_are_loop_constant(ir_rvalue *,
31 						      hash_table *);
32 
33 static 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  */
49 static ir_rvalue *
find_initial_value(ir_loop * loop,ir_variable * var)50 find_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->rhs;
75 
76          break;
77       }
78 
79       default:
80          break;
81       }
82    }
83 
84    return NULL;
85 }
86 
87 
88 static int
calculate_iterations(ir_rvalue * from,ir_rvalue * to,ir_rvalue * increment,enum ir_expression_operation op,bool continue_from_then,bool swap_compare_operands,bool inc_before_terminator)89 calculate_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 
224 static bool
incremented_before_terminator(ir_loop * loop,ir_variable * var,ir_if * terminator)225 incremented_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             return true;
245          }
246 
247          break;
248       }
249 
250       default:
251          break;
252       }
253    }
254 
255    unreachable("Unable to find induction variable");
256 }
257 
258 /**
259  * Record the fact that the given loop variable was referenced inside the loop.
260  *
261  * \arg in_assignee is true if the reference was on the LHS of an assignment.
262  *
263  * \arg in_conditional_code_or_nested_loop is true if the reference occurred
264  * inside an if statement or a nested loop.
265  *
266  * \arg current_assignment is the ir_assignment node that the loop variable is
267  * on the LHS of, if any (ignored if \c in_assignee is false).
268  */
269 void
record_reference(bool in_assignee,bool in_conditional_code_or_nested_loop,ir_assignment * current_assignment)270 loop_variable::record_reference(bool in_assignee,
271                                 bool in_conditional_code_or_nested_loop,
272                                 ir_assignment *current_assignment)
273 {
274    if (in_assignee) {
275       assert(current_assignment != NULL);
276 
277       if (in_conditional_code_or_nested_loop) {
278          this->conditional_or_nested_assignment = true;
279       }
280 
281       if (this->first_assignment == NULL) {
282          assert(this->num_assignments == 0);
283 
284          this->first_assignment = current_assignment;
285       }
286 
287       this->num_assignments++;
288    } else if (this->first_assignment == current_assignment) {
289       /* This catches the case where the variable is used in the RHS of an
290        * assignment where it is also in the LHS.
291        */
292       this->read_before_write = true;
293    }
294 }
295 
296 
loop_state()297 loop_state::loop_state()
298 {
299    this->ht = _mesa_pointer_hash_table_create(NULL);
300    this->mem_ctx = ralloc_context(NULL);
301    this->loop_found = false;
302 }
303 
304 
~loop_state()305 loop_state::~loop_state()
306 {
307    _mesa_hash_table_destroy(this->ht, NULL);
308    ralloc_free(this->mem_ctx);
309 }
310 
311 
312 loop_variable_state *
insert(ir_loop * ir)313 loop_state::insert(ir_loop *ir)
314 {
315    loop_variable_state *ls = new(this->mem_ctx) loop_variable_state;
316 
317    _mesa_hash_table_insert(this->ht, ir, ls);
318    this->loop_found = true;
319 
320    return ls;
321 }
322 
323 
324 loop_variable_state *
get(const ir_loop * ir)325 loop_state::get(const ir_loop *ir)
326 {
327    hash_entry *entry = _mesa_hash_table_search(this->ht, ir);
328    return entry ? (loop_variable_state *) entry->data : NULL;
329 }
330 
331 
332 loop_variable *
get(const ir_variable * ir)333 loop_variable_state::get(const ir_variable *ir)
334 {
335    if (ir == NULL)
336       return NULL;
337 
338    hash_entry *entry = _mesa_hash_table_search(this->var_hash, ir);
339    return entry ? (loop_variable *) entry->data : NULL;
340 }
341 
342 
343 loop_variable *
insert(ir_variable * var)344 loop_variable_state::insert(ir_variable *var)
345 {
346    void *mem_ctx = ralloc_parent(this);
347    loop_variable *lv = rzalloc(mem_ctx, loop_variable);
348 
349    lv->var = var;
350 
351    _mesa_hash_table_insert(this->var_hash, lv->var, lv);
352    this->variables.push_tail(lv);
353 
354    return lv;
355 }
356 
357 
358 loop_terminator *
insert(ir_if * if_stmt,bool continue_from_then)359 loop_variable_state::insert(ir_if *if_stmt, bool continue_from_then)
360 {
361    void *mem_ctx = ralloc_parent(this);
362    loop_terminator *t = new(mem_ctx) loop_terminator(if_stmt,
363                                                      continue_from_then);
364 
365    this->terminators.push_tail(t);
366 
367    return t;
368 }
369 
370 
371 /**
372  * If the given variable already is recorded in the state for this loop,
373  * return the corresponding loop_variable object that records information
374  * about it.
375  *
376  * Otherwise, create a new loop_variable object to record information about
377  * the variable, and set its \c read_before_write field appropriately based on
378  * \c in_assignee.
379  *
380  * \arg in_assignee is true if this variable was encountered on the LHS of an
381  * assignment.
382  */
383 loop_variable *
get_or_insert(ir_variable * var,bool in_assignee)384 loop_variable_state::get_or_insert(ir_variable *var, bool in_assignee)
385 {
386    loop_variable *lv = this->get(var);
387 
388    if (lv == NULL) {
389       lv = this->insert(var);
390       lv->read_before_write = !in_assignee;
391    }
392 
393    return lv;
394 }
395 
396 
397 namespace {
398 
399 class loop_analysis : public ir_hierarchical_visitor {
400 public:
401    loop_analysis(loop_state *loops);
402 
403    virtual ir_visitor_status visit(ir_loop_jump *);
404    virtual ir_visitor_status visit(ir_dereference_variable *);
405 
406    virtual ir_visitor_status visit_enter(ir_call *);
407 
408    virtual ir_visitor_status visit_enter(ir_loop *);
409    virtual ir_visitor_status visit_leave(ir_loop *);
410    virtual ir_visitor_status visit_enter(ir_assignment *);
411    virtual ir_visitor_status visit_leave(ir_assignment *);
412    virtual ir_visitor_status visit_enter(ir_if *);
413    virtual ir_visitor_status visit_leave(ir_if *);
414 
415    loop_state *loops;
416 
417    int if_statement_depth;
418 
419    ir_assignment *current_assignment;
420 
421    exec_list state;
422 };
423 
424 } /* anonymous namespace */
425 
loop_analysis(loop_state * loops)426 loop_analysis::loop_analysis(loop_state *loops)
427    : loops(loops), if_statement_depth(0), current_assignment(NULL)
428 {
429    /* empty */
430 }
431 
432 
433 ir_visitor_status
visit(ir_loop_jump * ir)434 loop_analysis::visit(ir_loop_jump *ir)
435 {
436    (void) ir;
437 
438    assert(!this->state.is_empty());
439 
440    loop_variable_state *const ls =
441       (loop_variable_state *) this->state.get_head();
442 
443    ls->num_loop_jumps++;
444 
445    return visit_continue;
446 }
447 
448 
449 ir_visitor_status
visit_enter(ir_call *)450 loop_analysis::visit_enter(ir_call *)
451 {
452    /* Mark every loop that we're currently analyzing as containing an ir_call
453     * (even those at outer nesting levels).
454     */
455    foreach_in_list(loop_variable_state, ls, &this->state) {
456       ls->contains_calls = true;
457    }
458 
459    return visit_continue_with_parent;
460 }
461 
462 
463 ir_visitor_status
visit(ir_dereference_variable * ir)464 loop_analysis::visit(ir_dereference_variable *ir)
465 {
466    /* If we're not somewhere inside a loop, there's nothing to do.
467     */
468    if (this->state.is_empty())
469       return visit_continue;
470 
471    bool nested = false;
472 
473    foreach_in_list(loop_variable_state, ls, &this->state) {
474       ir_variable *var = ir->variable_referenced();
475       loop_variable *lv = ls->get_or_insert(var, this->in_assignee);
476 
477       lv->record_reference(this->in_assignee,
478                            nested || this->if_statement_depth > 0,
479                            this->current_assignment);
480       nested = true;
481    }
482 
483    return visit_continue;
484 }
485 
486 ir_visitor_status
visit_enter(ir_loop * ir)487 loop_analysis::visit_enter(ir_loop *ir)
488 {
489    loop_variable_state *ls = this->loops->insert(ir);
490    this->state.push_head(ls);
491 
492    return visit_continue;
493 }
494 
495 ir_visitor_status
visit_leave(ir_loop * ir)496 loop_analysis::visit_leave(ir_loop *ir)
497 {
498    loop_variable_state *const ls =
499       (loop_variable_state *) this->state.pop_head();
500 
501    /* Function calls may contain side effects.  These could alter any of our
502     * variables in ways that cannot be known, and may even terminate shader
503     * execution (say, calling discard in the fragment shader).  So we can't
504     * rely on any of our analysis about assignments to variables.
505     *
506     * We could perform some conservative analysis (prove there's no statically
507     * possible assignment, etc.) but it isn't worth it for now; function
508     * inlining will allow us to unroll loops anyway.
509     */
510    if (ls->contains_calls)
511       return visit_continue;
512 
513    foreach_in_list(ir_instruction, node, &ir->body_instructions) {
514       /* Skip over declarations at the start of a loop.
515        */
516       if (node->as_variable())
517 	 continue;
518 
519       ir_if *if_stmt = ((ir_instruction *) node)->as_if();
520 
521       if (if_stmt != NULL)
522          try_add_loop_terminator(ls, if_stmt);
523    }
524 
525 
526    foreach_in_list_safe(loop_variable, lv, &ls->variables) {
527       /* Move variables that are already marked as being loop constant to
528        * a separate list.  These trivially don't need to be tested.
529        */
530       if (lv->is_loop_constant()) {
531 	 lv->remove();
532 	 ls->constants.push_tail(lv);
533       }
534    }
535 
536    /* Each variable assigned in the loop that isn't already marked as being loop
537     * constant might still be loop constant.  The requirements at this point
538     * are:
539     *
540     *    - Variable is written before it is read.
541     *
542     *    - Only one assignment to the variable.
543     *
544     *    - All operands on the RHS of the assignment are also loop constants.
545     *
546     * The last requirement is the reason for the progress loop.  A variable
547     * marked as a loop constant on one pass may allow other variables to be
548     * marked as loop constant on following passes.
549     */
550    bool progress;
551    do {
552       progress = false;
553 
554       foreach_in_list_safe(loop_variable, lv, &ls->variables) {
555 	 if (lv->conditional_or_nested_assignment || (lv->num_assignments > 1))
556 	    continue;
557 
558 	 /* Process the RHS of the assignment.  If all of the variables
559 	  * accessed there are loop constants, then add this
560 	  */
561 	 ir_rvalue *const rhs = lv->first_assignment->rhs;
562 	 if (all_expression_operands_are_loop_constant(rhs, ls->var_hash)) {
563 	    lv->rhs_clean = true;
564 
565 	    if (lv->is_loop_constant()) {
566 	       progress = true;
567 
568 	       lv->remove();
569 	       ls->constants.push_tail(lv);
570 	    }
571 	 }
572       }
573    } while (progress);
574 
575    /* The remaining variables that are not loop invariant might be loop
576     * induction variables.
577     */
578    foreach_in_list_safe(loop_variable, lv, &ls->variables) {
579       /* If there is more than one assignment to a variable, it cannot be a
580        * loop induction variable.  This isn't strictly true, but this is a
581        * very simple induction variable detector, and it can't handle more
582        * complex cases.
583        */
584       if (lv->num_assignments > 1)
585 	 continue;
586 
587       /* All of the variables with zero assignments in the loop are loop
588        * invariant, and they should have already been filtered out.
589        */
590       assert(lv->num_assignments == 1);
591       assert(lv->first_assignment != NULL);
592 
593       /* The assignment to the variable in the loop must be unconditional and
594        * not inside a nested loop.
595        */
596       if (lv->conditional_or_nested_assignment)
597 	 continue;
598 
599       /* Basic loop induction variables have a single assignment in the loop
600        * that has the form 'VAR = VAR + i' or 'VAR = VAR - i' where i is a
601        * loop invariant.
602        */
603       ir_rvalue *const inc =
604 	 get_basic_induction_increment(lv->first_assignment, ls->var_hash);
605       if (inc != NULL) {
606 	 lv->increment = inc;
607 
608 	 lv->remove();
609 	 ls->induction_variables.push_tail(lv);
610       }
611    }
612 
613    /* Search the loop terminating conditions for those of the form 'i < c'
614     * where i is a loop induction variable, c is a constant, and < is any
615     * relative operator.  From each of these we can infer an iteration count.
616     * Also figure out which terminator (if any) produces the smallest
617     * iteration count--this is the limiting terminator.
618     */
619    foreach_in_list(loop_terminator, t, &ls->terminators) {
620       ir_if *if_stmt = t->ir;
621 
622       /* If-statements can be either 'if (expr)' or 'if (deref)'.  We only care
623        * about the former here.
624        */
625       ir_expression *cond = if_stmt->condition->as_expression();
626       if (cond == NULL)
627 	 continue;
628 
629       switch (cond->operation) {
630       case ir_binop_less:
631       case ir_binop_gequal: {
632 	 /* The expressions that we care about will either be of the form
633 	  * 'counter < limit' or 'limit < counter'.  Figure out which is
634 	  * which.
635 	  */
636 	 ir_rvalue *counter = cond->operands[0]->as_dereference_variable();
637 	 ir_constant *limit = cond->operands[1]->as_constant();
638 	 enum ir_expression_operation cmp = cond->operation;
639          bool swap_compare_operands = false;
640 
641 	 if (limit == NULL) {
642 	    counter = cond->operands[1]->as_dereference_variable();
643 	    limit = cond->operands[0]->as_constant();
644             swap_compare_operands = true;
645 	 }
646 
647 	 if ((counter == NULL) || (limit == NULL))
648 	    break;
649 
650 	 ir_variable *var = counter->variable_referenced();
651 
652 	 ir_rvalue *init = find_initial_value(ir, var);
653 
654          loop_variable *lv = ls->get(var);
655          if (lv != NULL && lv->is_induction_var()) {
656             bool inc_before_terminator =
657                incremented_before_terminator(ir, var, t->ir);
658 
659             t->iterations = calculate_iterations(init, limit, lv->increment,
660                                                  cmp, t->continue_from_then,
661                                                  swap_compare_operands,
662                                                  inc_before_terminator);
663 
664             if (t->iterations >= 0 &&
665                 (ls->limiting_terminator == NULL ||
666                  t->iterations < ls->limiting_terminator->iterations)) {
667                ls->limiting_terminator = t;
668             }
669          }
670          break;
671       }
672 
673       default:
674          break;
675       }
676    }
677 
678    return visit_continue;
679 }
680 
681 ir_visitor_status
visit_enter(ir_if * ir)682 loop_analysis::visit_enter(ir_if *ir)
683 {
684    (void) ir;
685 
686    if (!this->state.is_empty())
687       this->if_statement_depth++;
688 
689    return visit_continue;
690 }
691 
692 ir_visitor_status
visit_leave(ir_if * ir)693 loop_analysis::visit_leave(ir_if *ir)
694 {
695    (void) ir;
696 
697    if (!this->state.is_empty())
698       this->if_statement_depth--;
699 
700    return visit_continue;
701 }
702 
703 ir_visitor_status
visit_enter(ir_assignment * ir)704 loop_analysis::visit_enter(ir_assignment *ir)
705 {
706    /* If we're not somewhere inside a loop, there's nothing to do.
707     */
708    if (this->state.is_empty())
709       return visit_continue_with_parent;
710 
711    this->current_assignment = ir;
712 
713    return visit_continue;
714 }
715 
716 ir_visitor_status
visit_leave(ir_assignment * ir)717 loop_analysis::visit_leave(ir_assignment *ir)
718 {
719    /* Since the visit_enter exits with visit_continue_with_parent for this
720     * case, the loop state stack should never be empty here.
721     */
722    assert(!this->state.is_empty());
723 
724    assert(this->current_assignment == ir);
725    this->current_assignment = NULL;
726 
727    return visit_continue;
728 }
729 
730 
731 class examine_rhs : public ir_hierarchical_visitor {
732 public:
examine_rhs(hash_table * loop_variables)733    examine_rhs(hash_table *loop_variables)
734    {
735       this->only_uses_loop_constants = true;
736       this->loop_variables = loop_variables;
737    }
738 
visit(ir_dereference_variable * ir)739    virtual ir_visitor_status visit(ir_dereference_variable *ir)
740    {
741       hash_entry *entry = _mesa_hash_table_search(this->loop_variables,
742                                                   ir->var);
743       loop_variable *lv = entry ? (loop_variable *) entry->data : NULL;
744 
745       assert(lv != NULL);
746 
747       if (lv->is_loop_constant()) {
748 	 return visit_continue;
749       } else {
750 	 this->only_uses_loop_constants = false;
751 	 return visit_stop;
752       }
753    }
754 
755    hash_table *loop_variables;
756    bool only_uses_loop_constants;
757 };
758 
759 
760 bool
all_expression_operands_are_loop_constant(ir_rvalue * ir,hash_table * variables)761 all_expression_operands_are_loop_constant(ir_rvalue *ir, hash_table *variables)
762 {
763    examine_rhs v(variables);
764 
765    ir->accept(&v);
766 
767    return v.only_uses_loop_constants;
768 }
769 
770 
771 ir_rvalue *
get_basic_induction_increment(ir_assignment * ir,hash_table * var_hash)772 get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash)
773 {
774    /* The RHS must be a binary expression.
775     */
776    ir_expression *const rhs = ir->rhs->as_expression();
777    if ((rhs == NULL)
778        || ((rhs->operation != ir_binop_add)
779 	   && (rhs->operation != ir_binop_sub)))
780       return NULL;
781 
782    /* One of the of operands of the expression must be the variable assigned.
783     * If the operation is subtraction, the variable in question must be the
784     * "left" operand.
785     */
786    ir_variable *const var = ir->lhs->variable_referenced();
787 
788    ir_variable *const op0 = rhs->operands[0]->variable_referenced();
789    ir_variable *const op1 = rhs->operands[1]->variable_referenced();
790 
791    if (((op0 != var) && (op1 != var))
792        || ((op1 == var) && (rhs->operation == ir_binop_sub)))
793       return NULL;
794 
795    ir_rvalue *inc = (op0 == var) ? rhs->operands[1] : rhs->operands[0];
796 
797    if (inc->as_constant() == NULL) {
798       ir_variable *const inc_var = inc->variable_referenced();
799       if (inc_var != NULL) {
800          hash_entry *entry = _mesa_hash_table_search(var_hash, inc_var);
801          loop_variable *lv = entry ? (loop_variable *) entry->data : NULL;
802 
803          if (lv == NULL || !lv->is_loop_constant()) {
804             assert(lv != NULL);
805             inc = NULL;
806          }
807       } else
808 	 inc = NULL;
809    }
810 
811    if ((inc != NULL) && (rhs->operation == ir_binop_sub)) {
812       void *mem_ctx = ralloc_parent(ir);
813 
814       inc = new(mem_ctx) ir_expression(ir_unop_neg,
815 				       inc->type,
816 				       inc->clone(mem_ctx, NULL),
817 				       NULL);
818    }
819 
820    return inc;
821 }
822 
823 
824 /**
825  * Detect whether an if-statement is a loop terminating condition, if so
826  * add it to the list of loop terminators.
827  *
828  * Detects if-statements of the form
829  *
830  *  (if (expression bool ...) (...then_instrs...break))
831  *
832  *     or
833  *
834  *  (if (expression bool ...) ... (...else_instrs...break))
835  */
836 void
try_add_loop_terminator(loop_variable_state * ls,ir_if * ir)837 try_add_loop_terminator(loop_variable_state *ls, ir_if *ir)
838 {
839    ir_instruction *inst = (ir_instruction *) ir->then_instructions.get_tail();
840    ir_instruction *else_inst =
841       (ir_instruction *) ir->else_instructions.get_tail();
842 
843    if (is_break(inst) || is_break(else_inst))
844       ls->insert(ir, is_break(else_inst));
845 }
846 
847 
848 loop_state *
analyze_loop_variables(exec_list * instructions)849 analyze_loop_variables(exec_list *instructions)
850 {
851    loop_state *loops = new loop_state;
852    loop_analysis v(loops);
853 
854    v.run(instructions);
855    return v.loops;
856 }
857