From daff631cf87db75bcae616605e759d281258d9e4 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 9 Mar 2021 10:39:58 +0200 Subject: [PATCH] Use accurate assignment targets in ExpressionInliner This fixes an issue where it inline an assignment to a subfield in place of a reference to the whole variable. --- source/glsl/optimize.cpp | 53 +++++++++++++++++----------------------- source/glsl/optimize.h | 2 +- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index 215466b2..87410d5a 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -393,35 +393,31 @@ void ExpressionInliner::visit(Block &block) { TraversingVisitor::visit(block); - for(map::iterator i=expressions.begin(); i!=expressions.end(); ) + for(map::iterator i=block.variables.begin(); i!=block.variables.end(); ++i) { - map::iterator j = block.variables.find(i->first->name); - if(j!=block.variables.end() && j->second==i->first) + map::iterator j = expressions.lower_bound(i->second); + for(; (j!=expressions.end() && j->first.declaration==i->second); ) { - if(i->second.expression && i->second.inline_point) - inline_expression(*i->second.expression, *i->second.inline_point, i->second.outer_oper, i->second.inner_oper, i->second.inline_on_rhs); + if(j->second.expression && j->second.inline_point) + inline_expression(*j->second.expression, *j->second.inline_point, j->second.outer_oper, j->second.inner_oper, j->second.inline_on_rhs); - expressions.erase(i++); - } - else - { - /* The expression was assigned in this block and may depend on local - variables of the block. If this is a conditionally executed block, - the assignment might not always happen. Mark the expression as not - available to any outer blocks. */ - if(i->second.assign_scope==&block) - i->second.available = false; - - ++i; + expressions.erase(j++); } } + + /* Expressions assigned in this block may depend on local variables of the + block. If this is a conditionally executed block, the assignments might not + always happen. Mark the expressions as not available to any outer blocks. */ + for(map::iterator i=expressions.begin(); i!=expressions.end(); ++i) + if(i->second.assign_scope==&block) + i->second.available = false; } void ExpressionInliner::visit(VariableReference &var) { if(var.declaration) { - map::iterator i = expressions.find(var.declaration); + map::iterator i = expressions.find(var.declaration); if(i!=expressions.end()) { /* If a non-trivial expression is referenced multiple times, don't @@ -479,19 +475,16 @@ void ExpressionInliner::visit(Assignment &assign) r_oper = 0; visit_and_record(assign.right, assign.oper, true); - if(VariableDeclaration *target_var = dynamic_cast(assign.target.declaration)) + map::iterator i = expressions.find(assign.target); + if(i!=expressions.end()) { - map::iterator i = expressions.find(target_var); - if(i!=expressions.end()) - { - /* Self-referencing assignments can't be inlined without additional - work. Just clear any previous expression. */ - i->second.expression = (assign.self_referencing ? 0 : assign.right.get()); - i->second.assign_scope = current_block; - i->second.inline_point = 0; - i->second.inner_oper = r_oper; - i->second.available = true; - } + /* Self-referencing assignments can't be inlined without additional + work. Just clear any previous expression. */ + i->second.expression = (assign.self_referencing ? 0 : assign.right.get()); + i->second.assign_scope = current_block; + i->second.inline_point = 0; + i->second.inner_oper = r_oper; + i->second.available = true; } r_oper = assign.oper; diff --git a/source/glsl/optimize.h b/source/glsl/optimize.h index 4f3bf8cc..4663c12e 100644 --- a/source/glsl/optimize.h +++ b/source/glsl/optimize.h @@ -120,7 +120,7 @@ private: ExpressionInfo(); }; - std::map expressions; + std::map expressions; ExpressionInfo *r_ref_info; bool r_any_inlined; bool r_trivial; -- 2.45.2