Merge pull request #1594 from KhronosGroup/fix-1591
Fix pathological complexity explosion for certain shaders.
diff --git a/spirv_cross.cpp b/spirv_cross.cpp
index 597f03a..199d0fd 100644
--- a/spirv_cross.cpp
+++ b/spirv_cross.cpp
@@ -2829,7 +2829,8 @@
return get<SPIRConstant>(id);
}
-static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, const unordered_set<uint32_t> &blocks)
+static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, const unordered_set<uint32_t> &blocks,
+ unordered_set<uint32_t> &visit_cache)
{
// This block accesses the variable.
if (blocks.find(block) != end(blocks))
@@ -2841,8 +2842,14 @@
// If any of our successors have a path to the end, there exists a path from block.
for (auto &succ : cfg.get_succeeding_edges(block))
- if (exists_unaccessed_path_to_return(cfg, succ, blocks))
- return true;
+ {
+ if (visit_cache.count(succ) == 0)
+ {
+ if (exists_unaccessed_path_to_return(cfg, succ, blocks, visit_cache))
+ return true;
+ visit_cache.insert(succ);
+ }
+ }
return false;
}
@@ -2899,7 +2906,8 @@
// void foo(int &var) { if (cond) var = 10; }
// Using read/write counts, we will think it's just an out variable, but it really needs to be inout,
// because if we don't write anything whatever we put into the function must return back to the caller.
- if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second))
+ unordered_set<uint32_t> visit_cache;
+ if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second, visit_cache))
arg.read_count++;
}
}