aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2019-10-08 16:15:39 +0000
committerHeejin Ahn <aheejin@gmail.com>2019-10-08 16:15:39 +0000
commit6a37c5d6fcae2182856051f558aab6cb8ba7233c (patch)
treee4f1567c3de2fcb1a422da04e91c2ada2412d2f6 /llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
parent5d154c3e7d9dcd8f651ac6b34ee21aa553c82c74 (diff)
downloadllvm-6a37c5d6fcae2182856051f558aab6cb8ba7233c.zip
llvm-6a37c5d6fcae2182856051f558aab6cb8ba7233c.tar.gz
llvm-6a37c5d6fcae2182856051f558aab6cb8ba7233c.tar.bz2
[WebAssembly] Fix a bug in 'try' placement
Summary: When searching for local expression tree created by stackified registers, for 'block' placement, we start the search from the previous instruction of a BB's terminator. But in 'try''s case, we should start from the previous instruction of a call that can throw, or a EH_LABEL that precedes the call, because the return values of the call's previous instructions can be stackified and consumed by the throwing call. For example, ``` i32.call @foo call @bar ; may throw br $label0 ``` In this case, if we start the search from the previous instruction of the terminator (`br` here), we end up stopping at `call @bar` and place a 'try' between `i32.call @foo` and `call @bar`, because `call @bar` does not have a return value so it is not a local expression tree of `br`. But in this case, unlike when placing 'block's, we should start the search from `call @bar`, because the return value of `i32.call @foo` is stackified and used by `call @bar`. Reviewers: dschuff Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D68619 llvm-svn: 374073
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp36
1 files changed, 23 insertions, 13 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index d2a3557..1032709 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -526,40 +526,50 @@ void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) {
AfterSet.insert(&MI);
}
- // Local expression tree should go after the TRY.
- for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
- --I) {
- if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
- continue;
- if (WebAssembly::isChild(*std::prev(I), MFI))
- AfterSet.insert(&*std::prev(I));
- else
- break;
- }
-
// If Header unwinds to MBB (= Header contains 'invoke'), the try block should
// contain the call within it. So the call should go after the TRY. The
// exception is when the header's terminator is a rethrow instruction, in
// which case that instruction, not a call instruction before it, is gonna
// throw.
+ MachineInstr *ThrowingCall = nullptr;
if (MBB.isPredecessor(Header)) {
auto TermPos = Header->getFirstTerminator();
if (TermPos == Header->end() ||
TermPos->getOpcode() != WebAssembly::RETHROW) {
- for (const auto &MI : reverse(*Header)) {
+ for (auto &MI : reverse(*Header)) {
if (MI.isCall()) {
AfterSet.insert(&MI);
+ ThrowingCall = &MI;
// Possibly throwing calls are usually wrapped by EH_LABEL
// instructions. We don't want to split them and the call.
if (MI.getIterator() != Header->begin() &&
- std::prev(MI.getIterator())->isEHLabel())
+ std::prev(MI.getIterator())->isEHLabel()) {
AfterSet.insert(&*std::prev(MI.getIterator()));
+ ThrowingCall = &*std::prev(MI.getIterator());
+ }
break;
}
}
}
}
+ // Local expression tree should go after the TRY.
+ // For BLOCK placement, we start the search from the previous instruction of a
+ // BB's terminator, but in TRY's case, we should start from the previous
+ // instruction of a call that can throw, or a EH_LABEL that precedes the call,
+ // because the return values of the call's previous instructions can be
+ // stackified and consumed by the throwing call.
+ auto SearchStartPt = ThrowingCall ? MachineBasicBlock::iterator(ThrowingCall)
+ : Header->getFirstTerminator();
+ for (auto I = SearchStartPt, E = Header->begin(); I != E; --I) {
+ if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
+ continue;
+ if (WebAssembly::isChild(*std::prev(I), MFI))
+ AfterSet.insert(&*std::prev(I));
+ else
+ break;
+ }
+
// Add the TRY.
auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
MachineInstr *Begin =