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