19434a0749f26c640305f68ef85d17a31063a5705Ian Romanick/*
29434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * Copyright © 2010 Intel Corporation
39434a0749f26c640305f68ef85d17a31063a5705Ian Romanick *
49434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * Permission is hereby granted, free of charge, to any person obtaining a
59434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * copy of this software and associated documentation files (the "Software"),
69434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * to deal in the Software without restriction, including without limitation
79434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * the rights to use, copy, modify, merge, publish, distribute, sublicense,
89434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * and/or sell copies of the Software, and to permit persons to whom the
99434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * Software is furnished to do so, subject to the following conditions:
109434a0749f26c640305f68ef85d17a31063a5705Ian Romanick *
119434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * The above copyright notice and this permission notice (including the next
129434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * paragraph) shall be included in all copies or substantial portions of the
139434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * Software.
149434a0749f26c640305f68ef85d17a31063a5705Ian Romanick *
159434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
169434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
179434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
189434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
199434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
209434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
219434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * DEALINGS IN THE SOFTWARE.
229434a0749f26c640305f68ef85d17a31063a5705Ian Romanick */
239434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
249434a0749f26c640305f68ef85d17a31063a5705Ian Romanick#include "glsl_types.h"
259434a0749f26c640305f68ef85d17a31063a5705Ian Romanick#include "loop_analysis.h"
269434a0749f26c640305f68ef85d17a31063a5705Ian Romanick#include "ir_hierarchical_visitor.h"
279434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
289434a0749f26c640305f68ef85d17a31063a5705Ian Romanickstatic bool is_loop_terminator(ir_if *ir);
299434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
309434a0749f26c640305f68ef85d17a31063a5705Ian Romanickstatic bool all_expression_operands_are_loop_constant(ir_rvalue *,
319434a0749f26c640305f68ef85d17a31063a5705Ian Romanick						      hash_table *);
329434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
339434a0749f26c640305f68ef85d17a31063a5705Ian Romanickstatic ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *);
349434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
359434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
369434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_state::loop_state()
379434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
389434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->ht = hash_table_ctor(0, hash_table_pointer_hash,
399434a0749f26c640305f68ef85d17a31063a5705Ian Romanick			      hash_table_pointer_compare);
40d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   this->mem_ctx = ralloc_context(NULL);
4158c988ada56114b56477983f66b4039219f1a82cEric Anholt   this->loop_found = false;
429434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
439434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
449434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
459434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_state::~loop_state()
469434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
479434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   hash_table_dtor(this->ht);
48d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   ralloc_free(this->mem_ctx);
499434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
509434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
519434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
529434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_variable_state *
539434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_state::insert(ir_loop *ir)
549434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
559434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_variable_state *ls = new(this->mem_ctx) loop_variable_state;
5658c988ada56114b56477983f66b4039219f1a82cEric Anholt
579434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   hash_table_insert(this->ht, ls, ir);
5858c988ada56114b56477983f66b4039219f1a82cEric Anholt   this->loop_found = true;
599434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
609434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return ls;
619434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
629434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
639434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
649434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_variable_state *
659434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_state::get(const ir_loop *ir)
669434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
679434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return (loop_variable_state *) hash_table_find(this->ht, ir);
689434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
699434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
709434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
719434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_variable *
729434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_variable_state::get(const ir_variable *ir)
739434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
749434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return (loop_variable *) hash_table_find(this->var_hash, ir);
759434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
769434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
779434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
789434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_variable *
799434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_variable_state::insert(ir_variable *var)
809434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
81d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   void *mem_ctx = ralloc_parent(this);
82d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   loop_variable *lv = rzalloc(mem_ctx, loop_variable);
839434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
849434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   lv->var = var;
859434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
869434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   hash_table_insert(this->var_hash, lv, lv->var);
879434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->variables.push_tail(lv);
889434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
899434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return lv;
909434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
919434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
929434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
939434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_terminator *
949434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_variable_state::insert(ir_if *if_stmt)
959434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
96d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   void *mem_ctx = ralloc_parent(this);
97d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   loop_terminator *t = rzalloc(mem_ctx, loop_terminator);
989434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
999434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   t->ir = if_stmt;
1009434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->terminators.push_tail(t);
1019434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1029434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return t;
1039434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
1049434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1059434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1069434a0749f26c640305f68ef85d17a31063a5705Ian Romanickclass loop_analysis : public ir_hierarchical_visitor {
1079434a0749f26c640305f68ef85d17a31063a5705Ian Romanickpublic:
1089434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_analysis();
1099434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1103bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick   virtual ir_visitor_status visit(ir_loop_jump *);
1119434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit(ir_dereference_variable *);
1129434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1130405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   virtual ir_visitor_status visit_enter(ir_call *);
1140405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke
1159434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit_enter(ir_loop *);
1169434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit_leave(ir_loop *);
1179434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit_enter(ir_assignment *);
1189434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit_leave(ir_assignment *);
1199434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit_enter(ir_if *);
1209434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit_leave(ir_if *);
1219434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1229434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_state *loops;
1239434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1249434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   int if_statement_depth;
1259434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1269434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_assignment *current_assignment;
1279434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1289434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   exec_list state;
1299434a0749f26c640305f68ef85d17a31063a5705Ian Romanick};
1309434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1319434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1329434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::loop_analysis()
1339434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
1349434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->loops = new loop_state;
1359434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1369434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->if_statement_depth = 0;
1379434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->current_assignment = NULL;
1389434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
1399434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1409434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1419434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_visitor_status
1423bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanickloop_analysis::visit(ir_loop_jump *ir)
1433bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick{
1443bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick   (void) ir;
1453bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick
1463bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick   assert(!this->state.is_empty());
1473bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick
1483bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick   loop_variable_state *const ls =
1493bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick      (loop_variable_state *) this->state.get_head();
1503bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick
1513bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick   ls->num_loop_jumps++;
1523bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick
1533bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick   return visit_continue;
1543bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick}
1553bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick
1563bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanick
1573bcfafcf0320ee5407716ff67062e80d162760d4Ian Romanickir_visitor_status
1580405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunkeloop_analysis::visit_enter(ir_call *ir)
1590405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke{
1600405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   /* If we're not somewhere inside a loop, there's nothing to do. */
1610405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   if (this->state.is_empty())
1620405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke      return visit_continue;
1630405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke
1640405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   loop_variable_state *const ls =
1650405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke      (loop_variable_state *) this->state.get_head();
1660405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke
1670405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   ls->contains_calls = true;
1680405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   return visit_continue_with_parent;
1690405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke}
1700405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke
1710405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke
1720405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunkeir_visitor_status
1739434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::visit(ir_dereference_variable *ir)
1749434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
1759434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   /* If we're not somewhere inside a loop, there's nothing to do.
1769434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    */
1779434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (this->state.is_empty())
178956f049fd24eb5239361e68a1f27e1bebb3315a0Ian Romanick      return visit_continue;
1799434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1809434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_variable_state *const ls =
1819434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      (loop_variable_state *) this->state.get_head();
1829434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1839434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_variable *var = ir->variable_referenced();
1849434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_variable *lv = ls->get(var);
1859434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1869434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (lv == NULL) {
1879434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      lv = ls->insert(var);
1889434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      lv->read_before_write = !this->in_assignee;
1899434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
1909434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1919434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (this->in_assignee) {
1929434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      assert(this->current_assignment != NULL);
1939434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1949434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      lv->conditional_assignment = (this->if_statement_depth > 0)
1959434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 || (this->current_assignment->condition != NULL);
1969434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
1979434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (lv->first_assignment == NULL) {
1989434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 assert(lv->num_assignments == 0);
1999434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2009434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 lv->first_assignment = this->current_assignment;
2019434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      }
2029434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2039434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      lv->num_assignments++;
2049434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   } else if (lv->first_assignment == this->current_assignment) {
2059434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      /* This catches the case where the variable is used in the RHS of an
2069434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * assignment where it is also in the LHS.
2079434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       */
2089434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      lv->read_before_write = true;
2099434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
2109434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2119434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return visit_continue;
2129434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
2139434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2149434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_visitor_status
2159434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::visit_enter(ir_loop *ir)
2169434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
2179434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_variable_state *ls = this->loops->insert(ir);
2189434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->state.push_head(ls);
2199434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2209434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return visit_continue;
2219434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
2229434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2239434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_visitor_status
2249434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::visit_leave(ir_loop *ir)
2259434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
2269434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_variable_state *const ls =
2279434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      (loop_variable_state *) this->state.pop_head();
2289434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2290405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   /* Function calls may contain side effects.  These could alter any of our
2300405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    * variables in ways that cannot be known, and may even terminate shader
2310405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    * execution (say, calling discard in the fragment shader).  So we can't
2320405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    * rely on any of our analysis about assignments to variables.
2330405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    *
2340405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    * We could perform some conservative analysis (prove there's no statically
2350405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    * possible assignment, etc.) but it isn't worth it for now; function
2360405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    * inlining will allow us to unroll loops anyway.
2370405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke    */
2380405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke   if (ls->contains_calls)
2390405bd08ca0e01ebc68891ee1ff47d320983f775Kenneth Graunke      return visit_continue;
2409434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2419434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   foreach_list(node, &ir->body_instructions) {
2429434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      /* Skip over declarations at the start of a loop.
2439434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       */
2449434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (((ir_instruction *) node)->as_variable())
2459434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 continue;
2469434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2479434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      ir_if *if_stmt = ((ir_instruction *) node)->as_if();
2489434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2499434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if ((if_stmt != NULL) && is_loop_terminator(if_stmt))
2509434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 ls->insert(if_stmt);
2519434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      else
2529434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 break;
2539434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
2549434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2559434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2569434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   foreach_list_safe(node, &ls->variables) {
2579434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      loop_variable *lv = (loop_variable *) node;
2589434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2599434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      /* Move variables that are already marked as being loop constant to
2609434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * a separate list.  These trivially don't need to be tested.
2619434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       */
2629434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (lv->is_loop_constant()) {
2639434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 lv->remove();
2649434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 ls->constants.push_tail(lv);
2659434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      }
2669434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
2679434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2689434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   /* Each variable assigned in the loop that isn't already marked as being loop
2699434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * constant might still be loop constant.  The requirements at this point
2709434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * are:
2719434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    *
2729434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    *    - Variable is written before it is read.
2739434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    *
2749434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    *    - Only one assignment to the variable.
2759434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    *
2769434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    *    - All operands on the RHS of the assignment are also loop constants.
2779434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    *
2789434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * The last requirement is the reason for the progress loop.  A variable
2799434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * marked as a loop constant on one pass may allow other variables to be
2809434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * marked as loop constant on following passes.
2819434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    */
2829434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   bool progress;
2839434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   do {
2849434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      progress = false;
2859434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2869434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      foreach_list_safe(node, &ls->variables) {
2879434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 loop_variable *lv = (loop_variable *) node;
2889434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2899434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 if (lv->conditional_assignment || (lv->num_assignments > 1))
2909434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	    continue;
2919434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2929434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 /* Process the RHS of the assignment.  If all of the variables
2939434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	  * accessed there are loop constants, then add this
2949434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	  */
2959434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 ir_rvalue *const rhs = lv->first_assignment->rhs;
2969434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 if (all_expression_operands_are_loop_constant(rhs, ls->var_hash)) {
2979434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	    lv->rhs_clean = true;
2989434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
2999434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	    if (lv->is_loop_constant()) {
3009434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	       progress = true;
3019434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3029434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	       lv->remove();
3039434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	       ls->constants.push_tail(lv);
3049434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	    }
3059434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 }
3069434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      }
3079434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   } while (progress);
3089434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3099434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   /* The remaining variables that are not loop invariant might be loop
3109434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * induction variables.
3119434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    */
3129434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   foreach_list_safe(node, &ls->variables) {
3139434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      loop_variable *lv = (loop_variable *) node;
3149434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3159434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      /* If there is more than one assignment to a variable, it cannot be a
3169434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * loop induction variable.  This isn't strictly true, but this is a
3179434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * very simple induction variable detector, and it can't handle more
3189434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * complex cases.
3199434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       */
3209434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (lv->num_assignments > 1)
3219434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 continue;
3229434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3239434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      /* All of the variables with zero assignments in the loop are loop
3249434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * invariant, and they should have already been filtered out.
3259434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       */
3269434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      assert(lv->num_assignments == 1);
3279434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      assert(lv->first_assignment != NULL);
3289434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3299434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      /* The assignmnet to the variable in the loop must be unconditional.
3309434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       */
3319434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (lv->conditional_assignment)
3329434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 continue;
3339434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3349434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      /* Basic loop induction variables have a single assignment in the loop
3359434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * that has the form 'VAR = VAR + i' or 'VAR = VAR - i' where i is a
3369434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       * loop invariant.
3379434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       */
3389434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      ir_rvalue *const inc =
3399434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 get_basic_induction_increment(lv->first_assignment, ls->var_hash);
3409434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (inc != NULL) {
3419434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 lv->iv_scale = NULL;
3429434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 lv->biv = lv->var;
3439434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 lv->increment = inc;
3449434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3459434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 lv->remove();
3469434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 ls->induction_variables.push_tail(lv);
3479434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      }
3489434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
3499434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3509434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return visit_continue;
3519434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
3529434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3539434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_visitor_status
3549434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::visit_enter(ir_if *ir)
3559434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
3569434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   (void) ir;
3579434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3589434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (!this->state.is_empty())
3599434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      this->if_statement_depth++;
3609434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3619434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return visit_continue;
3629434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
3639434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3649434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_visitor_status
3659434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::visit_leave(ir_if *ir)
3669434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
3679434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   (void) ir;
3689434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3699434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (!this->state.is_empty())
3709434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      this->if_statement_depth--;
3719434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3729434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return visit_continue;
3739434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
3749434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3759434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_visitor_status
3769434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::visit_enter(ir_assignment *ir)
3779434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
3789434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   /* If we're not somewhere inside a loop, there's nothing to do.
3799434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    */
3809434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (this->state.is_empty())
3819434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      return visit_continue_with_parent;
3829434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3839434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->current_assignment = ir;
3849434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3859434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return visit_continue;
3869434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
3879434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3889434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_visitor_status
3899434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_analysis::visit_leave(ir_assignment *ir)
3909434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
3919434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   /* Since the visit_enter exits with visit_continue_with_parent for this
3929434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * case, the loop state stack should never be empty here.
3939434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    */
3949434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   assert(!this->state.is_empty());
3959434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3969434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   assert(this->current_assignment == ir);
3979434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   this->current_assignment = NULL;
3989434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
3999434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return visit_continue;
4009434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
4019434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4029434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4039434a0749f26c640305f68ef85d17a31063a5705Ian Romanickclass examine_rhs : public ir_hierarchical_visitor {
4049434a0749f26c640305f68ef85d17a31063a5705Ian Romanickpublic:
4059434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   examine_rhs(hash_table *loop_variables)
4069434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   {
4079434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      this->only_uses_loop_constants = true;
4089434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      this->loop_variables = loop_variables;
4099434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
4109434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4119434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   virtual ir_visitor_status visit(ir_dereference_variable *ir)
4129434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   {
4139434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      loop_variable *lv =
4149434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 (loop_variable *) hash_table_find(this->loop_variables, ir->var);
4159434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4169434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      assert(lv != NULL);
4179434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4189434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (lv->is_loop_constant()) {
4199434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 return visit_continue;
4209434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      } else {
4219434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 this->only_uses_loop_constants = false;
4229434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 return visit_stop;
4239434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      }
4249434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
4259434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4269434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   hash_table *loop_variables;
4279434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   bool only_uses_loop_constants;
4289434a0749f26c640305f68ef85d17a31063a5705Ian Romanick};
4299434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4309434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4319434a0749f26c640305f68ef85d17a31063a5705Ian Romanickbool
4329434a0749f26c640305f68ef85d17a31063a5705Ian Romanickall_expression_operands_are_loop_constant(ir_rvalue *ir, hash_table *variables)
4339434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
4349434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   examine_rhs v(variables);
4359434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4369434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir->accept(&v);
4379434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4389434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return v.only_uses_loop_constants;
4399434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
4409434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4419434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4429434a0749f26c640305f68ef85d17a31063a5705Ian Romanickir_rvalue *
4439434a0749f26c640305f68ef85d17a31063a5705Ian Romanickget_basic_induction_increment(ir_assignment *ir, hash_table *var_hash)
4449434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
4459434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   /* The RHS must be a binary expression.
4469434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    */
4479434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_expression *const rhs = ir->rhs->as_expression();
4489434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if ((rhs == NULL)
4499434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       || ((rhs->operation != ir_binop_add)
4509434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	   && (rhs->operation != ir_binop_sub)))
4519434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      return NULL;
4529434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4539434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   /* One of the of operands of the expression must be the variable assigned.
4549434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * If the operation is subtraction, the variable in question must be the
4559434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    * "left" operand.
4569434a0749f26c640305f68ef85d17a31063a5705Ian Romanick    */
4579434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_variable *const var = ir->lhs->variable_referenced();
4589434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4599434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_variable *const op0 = rhs->operands[0]->variable_referenced();
4609434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_variable *const op1 = rhs->operands[1]->variable_referenced();
4619434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4629434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (((op0 != var) && (op1 != var))
4639434a0749f26c640305f68ef85d17a31063a5705Ian Romanick       || ((op1 == var) && (rhs->operation == ir_binop_sub)))
4649434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      return NULL;
4659434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4669434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_rvalue *inc = (op0 == var) ? rhs->operands[1] : rhs->operands[0];
4679434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
468f061524f0737bf59dad6ab9bb2e0015df804e4b5Ian Romanick   if (inc->as_constant() == NULL) {
4699434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      ir_variable *const inc_var = inc->variable_referenced();
4709434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      if (inc_var != NULL) {
4719434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 loop_variable *lv =
4729434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	    (loop_variable *) hash_table_find(var_hash, inc_var);
4739434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4749434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 if (!lv->is_loop_constant())
4759434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	    inc = NULL;
4769434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      } else
4779434a0749f26c640305f68ef85d17a31063a5705Ian Romanick	 inc = NULL;
4789434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
4799434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4809434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if ((inc != NULL) && (rhs->operation == ir_binop_sub)) {
481d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      void *mem_ctx = ralloc_parent(ir);
4829434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4839434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      inc = new(mem_ctx) ir_expression(ir_unop_neg,
4849434a0749f26c640305f68ef85d17a31063a5705Ian Romanick				       inc->type,
4859434a0749f26c640305f68ef85d17a31063a5705Ian Romanick				       inc->clone(mem_ctx, NULL),
4869434a0749f26c640305f68ef85d17a31063a5705Ian Romanick				       NULL);
4879434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   }
4889434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4899434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return inc;
4909434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
4919434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4929434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
4939434a0749f26c640305f68ef85d17a31063a5705Ian Romanick/**
4949434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * Detect whether an if-statement is a loop terminating condition
4959434a0749f26c640305f68ef85d17a31063a5705Ian Romanick *
4969434a0749f26c640305f68ef85d17a31063a5705Ian Romanick * Detects if-statements of the form
4979434a0749f26c640305f68ef85d17a31063a5705Ian Romanick *
4989434a0749f26c640305f68ef85d17a31063a5705Ian Romanick *  (if (expression bool ...) (break))
4999434a0749f26c640305f68ef85d17a31063a5705Ian Romanick */
5009434a0749f26c640305f68ef85d17a31063a5705Ian Romanickbool
5019434a0749f26c640305f68ef85d17a31063a5705Ian Romanickis_loop_terminator(ir_if *ir)
5029434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
5039434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (!ir->else_instructions.is_empty())
5049434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      return false;
5059434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
5069434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_instruction *const inst =
5079434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      (ir_instruction *) ir->then_instructions.get_head();
5089434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   assert(inst != NULL);
5099434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
5109434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (inst->ir_type != ir_type_loop_jump)
5119434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      return false;
5129434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
5139434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   ir_loop_jump *const jump = (ir_loop_jump *) inst;
5149434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   if (jump->mode != ir_loop_jump::jump_break)
5159434a0749f26c640305f68ef85d17a31063a5705Ian Romanick      return false;
5169434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
5179434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return true;
5189434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
5199434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
5209434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
5219434a0749f26c640305f68ef85d17a31063a5705Ian Romanickloop_state *
5229434a0749f26c640305f68ef85d17a31063a5705Ian Romanickanalyze_loop_variables(exec_list *instructions)
5239434a0749f26c640305f68ef85d17a31063a5705Ian Romanick{
5249434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   loop_analysis v;
5259434a0749f26c640305f68ef85d17a31063a5705Ian Romanick
5269434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   v.run(instructions);
5279434a0749f26c640305f68ef85d17a31063a5705Ian Romanick   return v.loops;
5289434a0749f26c640305f68ef85d17a31063a5705Ian Romanick}
529