vk/image: Check extent does not exceed surface type limits
[mesa.git] / src / glsl / opt_constant_folding.cpp
index 599b21525de8a4c94b76b47ac929fd0d35b138bc..4aae3f0ddf2809d2816be05af6c7d04901021921 100644 (file)
@@ -32,6 +32,8 @@
 #include "ir_optimization.h"
 #include "glsl_types.h"
 
+namespace {
+
 /**
  * Visitor class for replacing expressions with ir_constant values.
  */
@@ -48,6 +50,7 @@ public:
       /* empty */
    }
 
+   virtual ir_visitor_status visit_enter(ir_discard *ir);
    virtual ir_visitor_status visit_enter(ir_assignment *ir);
    virtual ir_visitor_status visit_enter(ir_call *ir);
 
@@ -56,6 +59,8 @@ public:
    bool progress;
 };
 
+} /* unnamed namespace */
+
 void
 ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
 {
@@ -75,6 +80,11 @@ ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
       }
    }
 
+   /* Ditto for swizzles. */
+   ir_swizzle *swiz = (*rvalue)->as_swizzle();
+   if (swiz && !swiz->val->as_constant())
+      return;
+
    ir_constant *constant = (*rvalue)->constant_expression_value();
    if (constant) {
       *rvalue = constant;
@@ -84,6 +94,29 @@ ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
    }
 }
 
+ir_visitor_status
+ir_constant_folding_visitor::visit_enter(ir_discard *ir)
+{
+   if (ir->condition) {
+      ir->condition->accept(this);
+      handle_rvalue(&ir->condition);
+
+      ir_constant *const_val = ir->condition->as_constant();
+      /* If the condition is constant, either remove the condition or
+       * remove the never-executed assignment.
+       */
+      if (const_val) {
+         if (const_val->value.b[0])
+            ir->condition = NULL;
+         else
+            ir->remove();
+         this->progress = true;
+      }
+   }
+
+   return visit_continue_with_parent;
+}
+
 ir_visitor_status
 ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
 {
@@ -117,12 +150,14 @@ ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
 ir_visitor_status
 ir_constant_folding_visitor::visit_enter(ir_call *ir)
 {
-   exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
-      ir_variable *sig_param = (ir_variable *)sig_iter.get();
-
-      if (sig_param->mode == ir_var_in || sig_param->mode == ir_var_const_in) {
+   /* Attempt to constant fold parameters */
+   foreach_two_lists(formal_node, &ir->callee->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+      ir_variable *sig_param = (ir_variable *) formal_node;
+
+      if (sig_param->data.mode == ir_var_function_in
+          || sig_param->data.mode == ir_var_const_in) {
         ir_rvalue *new_param = param_rval;
 
         handle_rvalue(&new_param);
@@ -130,7 +165,15 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir)
            param_rval->replace_with(new_param);
         }
       }
-      sig_iter.next();
+   }
+
+   /* Next, see if the call can be replaced with an assignment of a constant */
+   ir_constant *const_val = ir->constant_expression_value();
+
+   if (const_val != NULL) {
+      ir_assignment *assignment =
+        new(ralloc_parent(ir)) ir_assignment(ir->return_deref, const_val);
+      ir->replace_with(assignment);
    }
 
    return visit_continue_with_parent;