summaryrefslogtreecommitdiff
path: root/src/ir
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-07-26 13:35:18 -0700
committerGitHub <noreply@github.com>2023-07-26 13:35:18 -0700
commit2f879c0c3089e54472860a23a27985ac687d375d (patch)
tree8e63776f5b186eb2b53247eaf9e4e8ff1f3c402f /src/ir
parent3ed34d275709acddb0e4ce7c4fa9ef7c6bb22f92 (diff)
downloadbinaryen-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.cpp8
-rw-r--r--src/ir/local-graph.h8
-rw-r--r--src/ir/possible-contents.cpp2
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;