From b5ed7068608ccc454d33a7cbb34184d43a1e6684 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Thu, 5 Jul 2018 10:42:05 +0200 Subject: [PATCH] Hoist out variable scope analysis. --- spirv_common.hpp | 1 - spirv_cpp.cpp | 2 +- spirv_cross.cpp | 50 ++++++++++++++++++++++++++++++++++++++++-------- spirv_cross.hpp | 2 +- spirv_glsl.cpp | 37 +---------------------------------- spirv_hlsl.cpp | 2 +- spirv_msl.cpp | 2 +- 7 files changed, 47 insertions(+), 49 deletions(-) diff --git a/spirv_common.hpp b/spirv_common.hpp index e3fb2b723..3c430f86b 100644 --- a/spirv_common.hpp +++ b/spirv_common.hpp @@ -764,7 +764,6 @@ struct SPIRFunction : IVariant bool active = false; bool flush_undeclared = true; bool do_combined_parameters = true; - bool analyzed_variable_scope = false; }; struct SPIRAccessChain : IVariant diff --git a/spirv_cpp.cpp b/spirv_cpp.cpp index e16daba71..7d781e917 100644 --- a/spirv_cpp.cpp +++ b/spirv_cpp.cpp @@ -300,7 +300,7 @@ string CompilerCPP::compile() backend.explicit_struct_type = true; backend.use_initializer_list = true; - build_function_control_flow_graphs(); + build_function_control_flow_graphs_and_analyze(); update_active_builtins(); uint32_t pass_count = 0; diff --git a/spirv_cross.cpp b/spirv_cross.cpp index 95d6540ee..429503a0a 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -3647,20 +3647,20 @@ void Compiler::analyze_parameter_preservation( } } -Compiler::AnalyzeVariableScopeAccessHandler::AnalyzeVariableScopeAccessHandler(spirv_cross::Compiler &compiler_, - spirv_cross::SPIRFunction &entry_) +Compiler::AnalyzeVariableScopeAccessHandler::AnalyzeVariableScopeAccessHandler(Compiler &compiler_, + SPIRFunction &entry_) : compiler(compiler_) , entry(entry_) { } -bool Compiler::AnalyzeVariableScopeAccessHandler::follow_function_call(const spirv_cross::SPIRFunction &) +bool Compiler::AnalyzeVariableScopeAccessHandler::follow_function_call(const SPIRFunction &) { // Only analyze within this function. return false; } -void Compiler::AnalyzeVariableScopeAccessHandler::set_current_block(const spirv_cross::SPIRBlock &block) +void Compiler::AnalyzeVariableScopeAccessHandler::set_current_block(const SPIRBlock &block) { current_block = █ @@ -3848,7 +3848,6 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3 if (length < 3) return false; - bool is_pure = compiler.function_is_pure(compiler.get(args[2])); length -= 3; args += 3; @@ -3858,8 +3857,8 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3 if (var) { accessed_variables_to_block[var->self].insert(current_block->self); - if (!is_pure) // Assume we can get partial writes to this variable. - partial_write_variables_to_block[var->self].insert(current_block->self); + // Assume we can get partial writes to this variable. + partial_write_variables_to_block[var->self].insert(current_block->self); } // Cannot easily prove if argument we pass to a function is completely written. @@ -4414,12 +4413,47 @@ bool Compiler::CombinedImageSamplerDrefHandler::handle(spv::Op opcode, const uin return true; } -void Compiler::build_function_control_flow_graphs() +void Compiler::build_function_control_flow_graphs_and_analyze() { CFGBuilder handler(*this); handler.function_cfgs[entry_point].reset(new CFG(*this, get(entry_point))); traverse_all_reachable_opcodes(get(entry_point), handler); function_cfgs = move(handler.function_cfgs); + + for (auto &f : function_cfgs) + { + auto &func = get(f.first); + analyze_variable_scope(func); + + // Check if we can actually use the loop variables we found in analyze_variable_scope. + // To use multiple initializers, we need the same type and qualifiers. + for (auto block : func.blocks) + { + auto &b = get(block); + if (b.loop_variables.size() < 2) + continue; + + auto &flags = get_decoration_bitset(b.loop_variables.front()); + uint32_t type = get(b.loop_variables.front()).basetype; + bool invalid_initializers = false; + for (auto loop_variable : b.loop_variables) + { + if (flags != get_decoration_bitset(loop_variable) || + type != get(b.loop_variables.front()).basetype) + { + invalid_initializers = true; + break; + } + } + + if (invalid_initializers) + { + for (auto loop_variable : b.loop_variables) + get(loop_variable).loop_variable = false; + b.loop_variables.clear(); + } + } + } } Compiler::CFGBuilder::CFGBuilder(spirv_cross::Compiler &compiler_) diff --git a/spirv_cross.hpp b/spirv_cross.hpp index a6acb2a2d..069e19511 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -869,7 +869,7 @@ class Compiler bool need_subpass_input = false; }; - void build_function_control_flow_graphs(); + void build_function_control_flow_graphs_and_analyze(); std::unordered_map> function_cfgs; struct CFGBuilder : OpcodeHandler { diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 798441cee..4bab5d152 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -418,7 +418,7 @@ string CompilerGLSL::compile() backend.supports_extensions = true; // Scan the SPIR-V to find trivial uses of extensions. - build_function_control_flow_graphs(); + build_function_control_flow_graphs_and_analyze(); find_static_extensions(); fixup_image_load_store_access(); update_active_builtins(); @@ -8909,41 +8909,6 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags) current_function = &func; auto &entry_block = get(func.entry_block); - if (!func.analyzed_variable_scope) - { - analyze_variable_scope(func); - - // Check if we can actually use the loop variables we found in analyze_variable_scope. - // To use multiple initializers, we need the same type and qualifiers. - for (auto block : func.blocks) - { - auto &b = get(block); - if (b.loop_variables.size() < 2) - continue; - - auto &flags = get_decoration_bitset(b.loop_variables.front()); - uint32_t type = get(b.loop_variables.front()).basetype; - bool invalid_initializers = false; - for (auto loop_variable : b.loop_variables) - { - if (flags != get_decoration_bitset(loop_variable) || - type != get(b.loop_variables.front()).basetype) - { - invalid_initializers = true; - break; - } - } - - if (invalid_initializers) - { - for (auto loop_variable : b.loop_variables) - get(loop_variable).loop_variable = false; - b.loop_variables.clear(); - } - } - func.analyzed_variable_scope = true; - } - for (auto &v : func.local_variables) { auto &var = get(v); diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index cb38fe1c6..34e1d19fb 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -4572,7 +4572,7 @@ string CompilerHLSL::compile() backend.can_declare_arrays_inline = false; backend.can_return_array = false; - build_function_control_flow_graphs(); + build_function_control_flow_graphs_and_analyze(); update_active_builtins(); analyze_image_and_sampler_usage(); diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 1a7d31697..27d250a6e 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -280,7 +280,7 @@ string CompilerMSL::compile() struct_member_padding.clear(); - build_function_control_flow_graphs(); + build_function_control_flow_graphs_and_analyze(); update_active_builtins(); analyze_image_and_sampler_usage(); build_implicit_builtins();