glsl: fix function inlining with opaque parameters
authorRhys Perry <pendingchaos02@gmail.com>
Wed, 6 Jun 2018 19:55:08 +0000 (20:55 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 1 Aug 2018 04:10:01 +0000 (00:10 -0400)
Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Signed-off-by: Marek Olšák <marek.olsak@amd.com>
src/compiler/glsl/opt_function_inlining.cpp

index 04690b6cf45367f33a256d5e44d54cfab49fcaa0..52f57da936df0147aa079c41fb7dc6b48745dbfa 100644 (file)
@@ -131,6 +131,18 @@ ir_save_lvalue_visitor::visit_enter(ir_dereference_array *deref)
    return visit_stop;
 }
 
+static bool
+should_replace_variable(ir_variable *sig_param, ir_rvalue *param) {
+   /* For opaque types, we want the inlined variable references
+    * referencing the passed in variable, since that will have
+    * the location information, which an assignment of an opaque
+    * variable wouldn't.
+    */
+   return sig_param->type->contains_opaque() &&
+          param->is_dereference() &&
+          sig_param->data.mode == ir_var_function_in;
+}
+
 void
 ir_call::generate_inline(ir_instruction *next_ir)
 {
@@ -155,12 +167,8 @@ ir_call::generate_inline(ir_instruction *next_ir)
       ir_rvalue *param = (ir_rvalue *) actual_node;
 
       /* Generate a new variable for the parameter. */
-      if (sig_param->type->contains_opaque()) {
-        /* For opaque types, we want the inlined variable references
-         * referencing the passed in variable, since that will have
-         * the location information, which an assignment of an opaque
-         * variable wouldn't.  Fix it up below.
-         */
+      if (should_replace_variable(sig_param, param)) {
+         /* Actual replacement happens below */
         parameters[i] = NULL;
       } else {
         parameters[i] = sig_param->clone(ctx, ht);
@@ -242,10 +250,9 @@ ir_call::generate_inline(ir_instruction *next_ir)
       ir_rvalue *const param = (ir_rvalue *) actual_node;
       ir_variable *sig_param = (ir_variable *) formal_node;
 
-      if (sig_param->type->contains_opaque()) {
+      if (should_replace_variable(sig_param, param)) {
         ir_dereference *deref = param->as_dereference();
 
-        assert(deref);
         do_variable_replacement(&new_instructions, sig_param, deref);
       }
    }
@@ -351,6 +358,9 @@ public:
    virtual ir_visitor_status visit_leave(ir_dereference_array *);
    virtual ir_visitor_status visit_leave(ir_dereference_record *);
    virtual ir_visitor_status visit_leave(ir_texture *);
+   virtual ir_visitor_status visit_leave(ir_assignment *);
+   virtual ir_visitor_status visit_leave(ir_expression *);
+   virtual ir_visitor_status visit_leave(ir_return *);
 
    void replace_deref(ir_dereference **deref);
    void replace_rvalue(ir_rvalue **rvalue);
@@ -391,6 +401,32 @@ ir_variable_replacement_visitor::visit_leave(ir_texture *ir)
    return visit_continue;
 }
 
+ir_visitor_status
+ir_variable_replacement_visitor::visit_leave(ir_assignment *ir)
+{
+   replace_deref(&ir->lhs);
+   replace_rvalue(&ir->rhs);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_variable_replacement_visitor::visit_leave(ir_expression *ir)
+{
+   for (uint8_t i = 0; i < ir->num_operands; i++)
+      replace_rvalue(&ir->operands[i]);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_variable_replacement_visitor::visit_leave(ir_return *ir)
+{
+   replace_rvalue(&ir->value);
+
+   return visit_continue;
+}
+
 ir_visitor_status
 ir_variable_replacement_visitor::visit_leave(ir_dereference_array *ir)
 {