diff options
author | Alon Zakai <azakai@google.com> | 2023-07-26 13:35:18 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-26 13:35:18 -0700 |
commit | 2f879c0c3089e54472860a23a27985ac687d375d (patch) | |
tree | 8e63776f5b186eb2b53247eaf9e4e8ff1f3c402f /src/ir | |
parent | 3ed34d275709acddb0e4ce7c4fa9ef7c6bb22f92 (diff) | |
download | binaryen-2f879c0c3089e54472860a23a27985ac687d375d.tar.gz binaryen-2f879c0c3089e54472860a23a27985ac687d375d.tar.bz2 binaryen-2f879c0c3089e54472860a23a27985ac687d375d.zip |
End the current basic block on a Call (#5823)
Before this PR, if a call had no paths to a catch in the same function then we skipped
creating a new basic block right after it. As a result, we could have a call in the middle
of a basic block. If EH is enabled that means we might transfer control flow out of
the function from the middle of a block. But it is better to have the property that
any transfer of control flow - to another basic block, or outside of the function - can
only happen at the end of a basic block.
This causes some overhead, but a subsequent PR (#5838) will remove that as a
followup, and this PR adds a little code to pass the module and check if EH is enabled,
and avoid the overhead if not, which at least avoids regressing the non-EH case
until that followup lands.
Diffstat (limited to 'src/ir')
-rw-r--r-- | src/ir/LocalGraph.cpp | 8 | ||||
-rw-r--r-- | src/ir/local-graph.h | 8 | ||||
-rw-r--r-- | src/ir/possible-contents.cpp | 2 |
3 files changed, 12 insertions, 6 deletions
diff --git a/src/ir/LocalGraph.cpp b/src/ir/LocalGraph.cpp index 8e7d2ccc0..ab8ce16ba 100644 --- a/src/ir/LocalGraph.cpp +++ b/src/ir/LocalGraph.cpp @@ -41,9 +41,11 @@ struct Flower : public CFGWalker<Flower, Visitor<Flower>, Info> { Flower(LocalGraph::GetSetses& getSetses, LocalGraph::Locations& locations, - Function* func) + Function* func, + Module* module) : getSetses(getSetses), locations(locations) { setFunction(func); + setModule(module); // create the CFG by walking the IR CFGWalker<Flower, Visitor<Flower>, Info>::doWalkFunction(func); // flow gets across blocks @@ -227,8 +229,8 @@ struct Flower : public CFGWalker<Flower, Visitor<Flower>, Info> { // LocalGraph implementation -LocalGraph::LocalGraph(Function* func) : func(func) { - LocalGraphInternal::Flower flower(getSetses, locations, func); +LocalGraph::LocalGraph(Function* func, Module* module) : func(func) { + LocalGraphInternal::Flower flower(getSetses, locations, func, module); #ifdef LOCAL_GRAPH_DEBUG std::cout << "LocalGraph::dump\n"; diff --git a/src/ir/local-graph.h b/src/ir/local-graph.h index 111f5c073..8cc92d0fd 100644 --- a/src/ir/local-graph.h +++ b/src/ir/local-graph.h @@ -33,8 +33,12 @@ namespace wasm { struct LocalGraph { // main API - // the constructor computes getSetses, the sets affecting each get - LocalGraph(Function* func); + // The constructor computes getSetses, the sets affecting each get. + // + // If a module is passed in, it is used to find which features are needed in + // the computation (for example, if exception handling is disabled, then we + // can generate a simpler CFG, as calls cannot throw). + LocalGraph(Function* func, Module* module = nullptr); // The local.sets relevant for an index or a get. The most common case is to // have a single set; after that, to be a phi of 2 items, so we use a small diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index db2655e8a..3430bc872 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -1177,7 +1177,7 @@ struct InfoCollector assert(handledPops == totalPops); // Handle local.get/sets: each set must write to the proper gets. - LocalGraph localGraph(func); + LocalGraph localGraph(func, getModule()); for (auto& [get, setsForGet] : localGraph.getSetses) { auto index = get->index; |