diff options
author | Heejin Ahn <aheejin@gmail.com> | 2021-02-25 12:50:04 -0800 |
---|---|---|
committer | Heejin Ahn <aheejin@gmail.com> | 2021-02-26 13:38:13 -0800 |
commit | d8b3dc5a6853467f75cc496ffd03973076d615b5 (patch) | |
tree | 45cffb187c50d1bcd64a84c475fb16e39d86ab6d /llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | |
parent | 83bc7815c4235786111aa2abf7193292e4a602f5 (diff) | |
download | llvm-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.cpp | 33 |
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); } } } |