aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2021-02-25 12:50:04 -0800
committerHeejin Ahn <aheejin@gmail.com>2021-02-26 13:38:13 -0800
commitd8b3dc5a6853467f75cc496ffd03973076d615b5 (patch)
tree45cffb187c50d1bcd64a84c475fb16e39d86ab6d /llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
parent83bc7815c4235786111aa2abf7193292e4a602f5 (diff)
downloadllvm-d8b3dc5a6853467f75cc496ffd03973076d615b5.zip
llvm-d8b3dc5a6853467f75cc496ffd03973076d615b5.tar.gz
llvm-d8b3dc5a6853467f75cc496ffd03973076d615b5.tar.bz2
[WebAssembly] Fix remapping branch dests in fixCatchUnwindMismatches
This is a case D97178 tried to solve but missed. D97178 could not handle the case when multiple consecutive delegates are generated: - Before: ``` block br (a) try catch end_try end_block <- (a) ``` - After ``` block br (a) try ... try try catch end_try <- (a) delegate delegate end_block <- (b) ``` (The `br` should point to (b) now) D97178 assumed `end_block` exists two BBs later than `end_try`, because it assumed the order as `end_try` BB -> `delegate` BB -> `end_block` BB. But it turned out there can be multiple `delegate`s in between. This patch changes the logic so we just search from `end_try` BB until we find `end_block`. Fixes https://github.com/emscripten-core/emscripten/issues/13515. (More precisely, fixes https://github.com/emscripten-core/emscripten/issues/13515#issuecomment-784711318.) Reviewed By: dschuff, tlively Differential Revision: https://reviews.llvm.org/D97569
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp33
1 files changed, 21 insertions, 12 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 73826d8..96cc7e8 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -1368,9 +1368,7 @@ bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) {
if (EHPadToUnwindDest.empty())
return false;
NumCatchUnwindMismatches += EHPadToUnwindDest.size();
- // <current branch dest, future branch dest> map, because fixing catch unwind
- // mismatches can invalidate branch destinations
- DenseMap<MachineBasicBlock *, MachineBasicBlock *> BrDestMap;
+ SmallPtrSet<MachineBasicBlock *, 4> NewEndTryBBs;
for (auto &P : EHPadToUnwindDest) {
MachineBasicBlock *EHPad = P.first;
@@ -1378,8 +1376,7 @@ bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) {
MachineInstr *Try = EHPadToTry[EHPad];
MachineInstr *EndTry = BeginToEnd[Try];
addTryDelegate(Try, EndTry, UnwindDest);
- BrDestMap[EndTry->getParent()] =
- EndTry->getParent()->getNextNode()->getNextNode();
+ NewEndTryBBs.insert(EndTry->getParent());
}
// Adding a try-delegate wrapping an existing try-catch-end can make existing
@@ -1423,17 +1420,29 @@ bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) {
// As we can see in this case, when branches target a BB that has both
// 'end_try' and 'end_block' and the BB is split to insert a 'delegate', we
// have to remap existing branch destinations so that they target not the
- // 'end_try' BB but the new 'end_block' BB, which should be the second next BB
- // of 'end_try' (because there is a 'delegate' BB in between). In this
- // example, the 'br bb3' instruction should be remapped to 'br split_bb'.
+ // 'end_try' BB but the new 'end_block' BB. There can be multiple 'delegate's
+ // in between, so we try to find the next BB with 'end_block' instruction. In
+ // this example, the 'br bb3' instruction should be remapped to 'br split_bb'.
for (auto &MBB : MF) {
for (auto &MI : MBB) {
if (MI.isTerminator()) {
for (auto &MO : MI.operands()) {
- if (MO.isMBB()) {
- auto It = BrDestMap.find(MO.getMBB());
- if (It != BrDestMap.end())
- MO.setMBB(It->second);
+ if (MO.isMBB() && NewEndTryBBs.count(MO.getMBB())) {
+ auto *BrDest = MO.getMBB();
+ bool FoundEndBlock = false;
+ for (; std::next(BrDest->getIterator()) != MF.end();
+ BrDest = BrDest->getNextNode()) {
+ for (const auto &MI : *BrDest) {
+ if (MI.getOpcode() == WebAssembly::END_BLOCK) {
+ FoundEndBlock = true;
+ break;
+ }
+ }
+ if (FoundEndBlock)
+ break;
+ }
+ assert(FoundEndBlock);
+ MO.setMBB(BrDest);
}
}
}