* DEALINGS IN THE SOFTWARE.
*/
-#include <climits>
+#include <limits.h>
#include "main/compiler.h"
#include "glsl_types.h"
#include "loop_analysis.h"
calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
enum ir_expression_operation op)
{
- void *mem_ctx = talloc_init(__func__);
+ if (from == NULL || to == NULL || increment == NULL)
+ return -1;
+
+ void *mem_ctx = ralloc_context(NULL);
ir_expression *const sub =
new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from);
}
}
- talloc_free(mem_ctx);
+ ralloc_free(mem_ctx);
return (valid_loop) ? iter_value : -1;
}
* i is a loop induction variable, c is a constant, and < is any relative
* operator.
*/
- int max_iterations = INT_MAX;
+ int max_iterations = ls->max_iterations;
+
+ if(ir->from && ir->to && ir->increment)
+ max_iterations = calculate_iterations(ir->from, ir->to, ir->increment, (ir_expression_operation)ir->cmp);
+
+ if(max_iterations < 0)
+ max_iterations = INT_MAX;
+
foreach_list(node, &ls->terminators) {
loop_terminator *t = (loop_terminator *) node;
ir_if *if_stmt = t->ir;
* which.
*/
ir_rvalue *counter = cond->operands[0]->as_dereference_variable();
- ir_constant *limit = cond->operands[1]->constant_expression_value();
+ ir_constant *limit = cond->operands[1]->as_constant();
enum ir_expression_operation cmp = cond->operation;
if (limit == NULL) {
counter = cond->operands[1]->as_dereference_variable();
- limit = cond->operands[0]->constant_expression_value();
+ limit = cond->operands[0]->as_constant();
switch (cmp) {
case ir_binop_less: cmp = ir_binop_gequal; break;
const int iterations = calculate_iterations(init, limit,
lv->increment,
cmp);
- if (iterations > 0) {
+ if (iterations >= 0) {
/* If the new iteration count is lower than the previously
* believed iteration count, update the loop control values.
*/
* satisfied.
*/
if_stmt->remove();
+
+ assert(ls->num_loop_jumps > 0);
+ ls->num_loop_jumps--;
+
this->progress = true;
}
}
}
+ /* If we have proven the one of the loop exit conditions is satisifed before
+ * running the loop once, remove the loop.
+ */
+ if (max_iterations == 0)
+ ir->remove();
+ else
+ ls->max_iterations = max_iterations;
+
return visit_continue;
}