[llvm] r355996 - [WebAssembly] Place 'try' and 'catch' correctly wrt EH_LABELs
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 12 17:37:31 PDT 2019
Author: aheejin
Date: Tue Mar 12 17:37:31 2019
New Revision: 355996
URL: http://llvm.org/viewvc/llvm-project?rev=355996&view=rev
Log:
[WebAssembly] Place 'try' and 'catch' correctly wrt EH_LABELs
Summary:
After instruction selection phase, possibly-throwing calls, which were
previously invoke, are wrapped in `EH_LABEL` instructions. For example:
```
EH_LABEL <mcsymbol .Ltmp0>
CALL_VOID @foo ...
EH_LABEL <mcsymbol .Ltmp1>
```
`EH_LABEL` is placed also in the beginning of EH pads:
```
bb.1 (landing-pad):
EH_LABEL <mcsymbol .Ltmp2>
...
```
And we'd like to maintian this relationship, so when we place a `try`,
```
TRY ...
EH_LABEL <mcsymbol .Ltmp0>
CALL_VOID @foo ...
EH_LABEL <mcsymbol .Ltmp1>
```
When we place a `catch`,
```
bb.1 (landing-pad):
EH_LABEL <mcsymbol .Ltmp2>
%0:except_ref = CATCH ...
...
```
Previously we didn't treat EH_LABELs specially, so `try` was placed
right before a call, and `catch` was placed in the beginning of an EH
pad.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58914
Added:
llvm/trunk/test/CodeGen/WebAssembly/eh-labels.mir
Modified:
llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
llvm/trunk/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp?rev=355996&r1=355995&r2=355996&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp Tue Mar 12 17:37:31 2019
@@ -543,6 +543,11 @@ void WebAssemblyCFGStackify::placeTryMar
for (const auto &MI : reverse(*Header)) {
if (MI.isCall()) {
AfterSet.insert(&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())
+ AfterSet.insert(&*std::prev(MI.getIterator()));
break;
}
}
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp?rev=355996&r1=355995&r2=355996&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp Tue Mar 12 17:37:31 2019
@@ -21,7 +21,7 @@
#include "llvm/MC/MCAsmInfo.h"
using namespace llvm;
-#define DEBUG_TYPE "wasm-exception-prepare"
+#define DEBUG_TYPE "wasm-late-eh-prepare"
namespace {
class WebAssemblyLateEHPrepare final : public MachineFunctionPass {
@@ -185,9 +185,12 @@ bool WebAssemblyLateEHPrepare::addCatche
for (auto &MBB : MF) {
if (MBB.isEHPad()) {
Changed = true;
+ auto InsertPos = MBB.begin();
+ if (InsertPos->isEHLabel()) // EH pad starts with an EH label
+ ++InsertPos;
unsigned DstReg =
MRI.createVirtualRegister(&WebAssembly::EXCEPT_REFRegClass);
- BuildMI(MBB, MBB.begin(), MBB.begin()->getDebugLoc(),
+ BuildMI(MBB, InsertPos, MBB.begin()->getDebugLoc(),
TII.get(WebAssembly::CATCH), DstReg);
}
}
@@ -255,7 +258,11 @@ bool WebAssemblyLateEHPrepare::addExcept
for (auto *Extract : ExtractInstrs) {
MachineBasicBlock *EHPad = getMatchingEHPad(Extract);
assert(EHPad && "No matching EH pad for extract_exception");
- MachineInstr *Catch = &*EHPad->begin();
+ auto CatchPos = EHPad->begin();
+ if (CatchPos->isEHLabel()) // EH pad starts with an EH label
+ ++CatchPos;
+ MachineInstr *Catch = &*CatchPos;
+
if (Catch->getNextNode() != Extract)
EHPad->insert(Catch->getNextNode(), Extract->removeFromParent());
@@ -359,8 +366,10 @@ bool WebAssemblyLateEHPrepare::restoreSt
// with leaf functions, and we don't restore __stack_pointer in leaf
// functions anyway.
auto InsertPos = MBB.begin();
- if (MBB.begin()->getOpcode() == WebAssembly::CATCH)
- InsertPos++;
+ if (InsertPos->isEHLabel()) // EH pad starts with an EH label
+ ++InsertPos;
+ if (InsertPos->getOpcode() == WebAssembly::CATCH)
+ ++InsertPos;
FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos,
MBB.begin()->getDebugLoc());
}
Added: llvm/trunk/test/CodeGen/WebAssembly/eh-labels.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/eh-labels.mir?rev=355996&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/eh-labels.mir (added)
+++ llvm/trunk/test/CodeGen/WebAssembly/eh-labels.mir Tue Mar 12 17:37:31 2019
@@ -0,0 +1,46 @@
+# RUN: llc -mtriple=wasm32-unknown-unknown -exception-model=wasm -mattr=+exception-handling -run-pass wasm-late-eh-prepare -run-pass wasm-cfg-stackify %s -o - | FileCheck %s
+
+# This tests 'try' and 'catch' instructions are correctly placed with respect to
+# EH_LABEL instructions.
+--- |
+ target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+ target triple = "wasm32-unknown-unknown"
+
+ declare i32 @__gxx_wasm_personality_v0(...)
+ declare void @foo()
+ define void @eh_label_test() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
+ ret void
+ }
+...
+
+---
+# CHECK-LABEL: eh_label_test
+name: eh_label_test
+liveins:
+ - { reg: '$arguments' }
+body: |
+ bb.0:
+ ; TRY should be before EH_LABEL wrappers of throwing calls
+ ; CHECK: TRY
+ ; CHECK-NEXT: EH_LABEL
+ ; CHECK-NEXT: CALL_VOID @foo
+ ; CHECK-NEXT: EH_LABEL
+ successors: %bb.1, %bb.2
+ EH_LABEL <mcsymbol .Ltmp0>
+ CALL_VOID @foo, implicit-def dead $arguments, implicit $sp32, implicit $sp64
+ EH_LABEL <mcsymbol .Ltmp1>
+
+ bb.1 (landing-pad):
+ ; predecessors: %bb.0
+ successors: %bb.2
+ ; CATCH should be after an EH_LABEL at the beginning of an EH pad
+ ; CHECK: EH_LABEL
+ ; CHECK-NEXT: CATCH
+ EH_LABEL <mcsymbol .Ltmp2>
+ dead %0:i32 = EXTRACT_EXCEPTION_I32 implicit-def dead $arguments
+ CATCHRET %bb.2, %bb.0, implicit-def dead $arguments
+
+ bb.2:
+ ; predecessors: %bb.0, %bb.1
+ RETURN_VOID implicit-def dead $arguments
+...
More information about the llvm-commits
mailing list