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