glsl: Optimize -(-expr) into expr.
[mesa.git] / src / glsl / loop_unroll.cpp
index 46000524ba105fdc56358d32261b44dc952711d5..ff97766f17b64a72309888e10f1ee0efefaf1a55 100644 (file)
@@ -25,6 +25,8 @@
 #include "loop_analysis.h"
 #include "ir_hierarchical_visitor.h"
 
+namespace {
+
 class loop_unroll_visitor : public ir_hierarchical_visitor {
 public:
    loop_unroll_visitor(loop_state *state, unsigned max_iterations)
@@ -42,6 +44,7 @@ public:
    unsigned max_iterations;
 };
 
+} /* anonymous namespace */
 
 static bool
 is_break(ir_instruction *ir)
@@ -50,6 +53,38 @@ is_break(ir_instruction *ir)
                     && ((ir_loop_jump *) ir)->is_break();
 }
 
+class loop_unroll_count : public ir_hierarchical_visitor {
+public:
+   int nodes;
+   bool fail;
+
+   loop_unroll_count(exec_list *list)
+   {
+      nodes = 0;
+      fail = false;
+
+      run(list);
+   }
+
+   virtual ir_visitor_status visit_enter(ir_assignment *ir)
+   {
+      nodes++;
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_expression *ir)
+   {
+      nodes++;
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_loop *ir)
+   {
+      fail = true;
+      return visit_continue;
+   }
+};
+
 
 ir_visitor_status
 loop_unroll_visitor::visit_leave(ir_loop *ir)
@@ -78,6 +113,13 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
    if (iterations > (int) max_iterations)
       return visit_continue;
 
+   /* Don't try to unroll nested loops and loops with a huge body.
+    */
+   loop_unroll_count count(&ir->body_instructions);
+
+   if (count.fail || count.nodes * iterations > (int)max_iterations * 5)
+      return visit_continue;
+
    if (ls->num_loop_jumps > 1)
       return visit_continue;
    else if (ls->num_loop_jumps) {
@@ -150,7 +192,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
           */
          break_ir->remove();
 
-         void *const mem_ctx = talloc_parent(ir);
+         void *const mem_ctx = ralloc_parent(ir);
          ir_instruction *ir_to_replace = ir;
 
          for (int i = 0; i < iterations; i++) {
@@ -182,7 +224,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
       }
    }
 
-   void *const mem_ctx = talloc_parent(ir);
+   void *const mem_ctx = ralloc_parent(ir);
 
    for (int i = 0; i < iterations; i++) {
       exec_list copy_list;