[llvm] r354939 - [WebAssembly] Remove unnecessary instructions after TRY marker placement
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 26 16:50:53 PST 2019
Author: aheejin
Date: Tue Feb 26 16:50:53 2019
New Revision: 354939
URL: http://llvm.org/viewvc/llvm-project?rev=354939&view=rev
Log:
[WebAssembly] Remove unnecessary instructions after TRY marker placement
Summary:
This removes unnecessary instructions after TRY marker placement. There
are two cases:
- `end`/`end_block` can be removed if they overlap with `try`/`end_try`
and they have the same return types.
- `br` right before `catch` that branches to after `end_try` can be
deleted.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58591
Modified:
llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
llvm/trunk/test/CodeGen/WebAssembly/exception.ll
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp?rev=354939&r1=354938&r2=354939&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp Tue Feb 26 16:50:53 2019
@@ -64,6 +64,7 @@ class WebAssemblyCFGStackify final : pub
void placeBlockMarker(MachineBasicBlock &MBB);
void placeLoopMarker(MachineBasicBlock &MBB);
void placeTryMarker(MachineBasicBlock &MBB);
+ void removeUnnecessaryInstrs(MachineFunction &MF);
void rewriteDepthImmediates(MachineFunction &MF);
void fixEndsAtEndOfFunction(MachineFunction &MF);
@@ -76,11 +77,12 @@ class WebAssemblyCFGStackify final : pub
// <EH pad, TRY marker> map
DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
- // Helper functions to register scope information created by marker
- // instructions.
+ // Helper functions to register / unregister scope information created by
+ // marker instructions.
void registerScope(MachineInstr *Begin, MachineInstr *End);
void registerTryScope(MachineInstr *Begin, MachineInstr *End,
MachineBasicBlock *EHPad);
+ void unregisterScope(MachineInstr *Begin);
public:
static char ID; // Pass identification, replacement for typeid
@@ -175,6 +177,20 @@ void WebAssemblyCFGStackify::registerTry
EHPadToTry[EHPad] = Begin;
}
+void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) {
+ assert(BeginToEnd.count(Begin));
+ MachineInstr *End = BeginToEnd[Begin];
+ assert(EndToBegin.count(End));
+ BeginToEnd.erase(Begin);
+ EndToBegin.erase(End);
+ MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin);
+ if (EHPad) {
+ assert(EHPadToTry.count(EHPad));
+ TryToEHPad.erase(Begin);
+ EHPadToTry.erase(EHPad);
+ }
+}
+
/// Insert a BLOCK marker for branches to MBB (if needed).
void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) {
// This should have been handled in placeTryMarker.
@@ -585,6 +601,76 @@ void WebAssemblyCFGStackify::placeTryMar
ScopeTops[Number] = Header;
}
+void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {
+ const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
+
+ // When there is an unconditional branch right before a catch instruction and
+ // it branches to the end of end_try marker, we don't need the branch, because
+ // it there is no exception, the control flow transfers to that point anyway.
+ // bb0:
+ // try
+ // ...
+ // br bb2 <- Not necessary
+ // bb1:
+ // catch
+ // ...
+ // bb2:
+ // end
+ for (auto &MBB : MF) {
+ if (!MBB.isEHPad())
+ continue;
+
+ MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
+ SmallVector<MachineOperand, 4> Cond;
+ MachineBasicBlock *EHPadLayoutPred =
+ &*std::prev(MachineFunction::iterator(&MBB));
+ MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent();
+ bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
+ if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) ||
+ (!Cond.empty() && FBB && FBB == Cont)))
+ TII.removeBranch(*EHPadLayoutPred);
+ }
+
+ // When there are block / end_block markers that overlap with try / end_try
+ // markers, and the block and try markers' return types are the same, the
+ // block /end_block markers are not necessary, because try / end_try markers
+ // also can serve as boundaries for branches.
+ // block <- Not necessary
+ // try
+ // ...
+ // catch
+ // ...
+ // end
+ // end <- Not necessary
+ SmallVector<MachineInstr *, 32> ToDelete;
+ for (auto &MBB : MF) {
+ for (auto &MI : MBB) {
+ if (MI.getOpcode() != WebAssembly::TRY)
+ continue;
+
+ MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try];
+ MachineBasicBlock *TryBB = Try->getParent();
+ MachineBasicBlock *Cont = EndTry->getParent();
+ int64_t RetType = Try->getOperand(0).getImm();
+ for (auto B = MachineBasicBlock::iterator(Try),
+ E = std::next(MachineBasicBlock::iterator(EndTry));
+ B != TryBB->begin() && E != Cont->end() &&
+ std::prev(B)->getOpcode() == WebAssembly::BLOCK &&
+ E->getOpcode() == WebAssembly::END_BLOCK &&
+ std::prev(B)->getOperand(0).getImm() == RetType;
+ --B, ++E) {
+ ToDelete.push_back(&*std::prev(B));
+ ToDelete.push_back(&*E);
+ }
+ }
+ }
+ for (auto *MI : ToDelete) {
+ if (MI->getOpcode() == WebAssembly::BLOCK)
+ unregisterScope(MI);
+ MI->eraseFromParent();
+ }
+}
+
static unsigned
getDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
const MachineBasicBlock *MBB) {
@@ -747,6 +833,7 @@ bool WebAssemblyCFGStackify::runOnMachin
LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n"
"********** Function: "
<< MF.getName() << '\n');
+ const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
releaseMemory();
@@ -756,6 +843,11 @@ bool WebAssemblyCFGStackify::runOnMachin
// Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes.
placeMarkers(MF);
+ if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
+ MF.getFunction().hasPersonalityFn())
+ // Remove unnecessary instructions.
+ removeUnnecessaryInstrs(MF);
+
// Convert MBB operands in terminators to relative depth immediates.
rewriteDepthImmediates(MF);
Modified: llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll?rev=354939&r1=354938&r2=354939&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll Tue Feb 26 16:50:53 2019
@@ -18,26 +18,23 @@ target triple = "wasm32-unknown-unknown"
; }
; CHECK-LABEL: test0
-; CHECK: block
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 0 # 0: down to label1
-; CHECK: catch
-; CHECK: block
-; CHECK: br_if 0, {{.*}} # 0: down to label3
-; CHECK: i32.call $drop=, __cxa_begin_catch
-; CHECK: call __cxa_end_catch
-; CHECK: br 1 # 1: down to label1
-; CHECK: end_block # label3:
-; CHECK: block
-; CHECK: br_if 0, {{.*}} # 0: down to label4
-; CHECK: i32.call $drop=, __cxa_begin_catch
-; CHECK: call __cxa_end_catch
-; CHECK: br 1 # 1: down to label1
-; CHECK: end_block # label4:
-; CHECK: call __cxa_rethrow
-; CHECK: end_try # label1:
-; CHECK: end_block
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch
+; CHECK: block
+; CHECK: br_if 0, {{.*}} # 0: down to label2
+; CHECK: i32.call $drop=, __cxa_begin_catch
+; CHECK: call __cxa_end_catch
+; CHECK: br 1 # 1: down to label0
+; CHECK: end_block # label2:
+; CHECK: block
+; CHECK: br_if 0, {{.*}} # 0: down to label3
+; CHECK: i32.call $drop=, __cxa_begin_catch
+; CHECK: call __cxa_end_catch
+; CHECK: br 1 # 1: down to label0
+; CHECK: end_block # label3:
+; CHECK: call __cxa_rethrow
+; CHECK: end_try # label0:
define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:
invoke void @foo()
@@ -177,39 +174,33 @@ unreachable:
; }
; CHECK-LABEL: test2
-; CHECK: block
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 0 # 0: down to label17
-; CHECK: catch
-; CHECK: i32.call $drop=, __cxa_begin_catch
-; CHECK: loop # label19:
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch
+; CHECK: i32.call $drop=, __cxa_begin_catch
+; CHECK: loop # label15:
+; CHECK: block
; CHECK: block
-; CHECK: block
-; CHECK: br_if 0, {{.*}} # 0: down to label21
+; CHECK: br_if 0, {{.*}} # 0: down to label17
+; CHECK: try
+; CHECK: call foo
+; CHECK: br 2 # 2: down to label16
+; CHECK: catch
; CHECK: try
-; CHECK: call foo
-; CHECK: br 2 # 2: down to label20
+; CHECK: call __cxa_end_catch
; CHECK: catch
-; CHECK: block
-; CHECK: try
-; CHECK: call __cxa_end_catch
-; CHECK: br 0 # 0: down to label24
-; CHECK: catch
-; CHECK: call __clang_call_terminate
-; CHECK: unreachable
-; CHECK: end_try # label24:
-; CHECK: end_block
-; CHECK: rethrow # to caller
+; CHECK: call __clang_call_terminate
+; CHECK: unreachable
; CHECK: end_try
-; CHECK: end_block # label21:
-; CHECK: call __cxa_end_catch
-; CHECK: br 2 # 2: down to label17
-; CHECK: end_block # label20:
-; CHECK: br 0 # 0: up to label19
-; CHECK: end_loop
-; CHECK: end_try # label17:
-; CHECK: end_block
+; CHECK: rethrow # to caller
+; CHECK: end_try
+; CHECK: end_block # label17:
+; CHECK: call __cxa_end_catch
+; CHECK: br 2 # 2: down to label13
+; CHECK: end_block # label16:
+; CHECK: br 0 # 0: up to label15
+; CHECK: end_loop
+; CHECK: end_try # label13:
define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:
invoke void @foo()
Modified: llvm/trunk/test/CodeGen/WebAssembly/exception.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/exception.ll?rev=354939&r1=354938&r2=354939&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/exception.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/exception.ll Tue Feb 26 16:50:53 2019
@@ -37,29 +37,26 @@ define void @test_rethrow(i8* %p) {
; CHECK-LABEL: test_catch:
; CHECK: global.get ${{.+}}=, __stack_pointer
-; CHECK: block
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 0
-; CHECK: catch $[[EXCEPT_REF:[0-9]+]]=
-; CHECK: global.set __stack_pointer
-; CHECK: block i32
-; CHECK: br_on_exn 0, __cpp_exception, $[[EXCEPT_REF]]
-; CHECK: rethrow
-; CHECK: end_block
-; CHECK: extract_exception $[[EXN:[0-9]+]]=
-; CHECK-DAG: i32.store __wasm_lpad_context
-; CHECK-DAG: i32.store __wasm_lpad_context+4
-; CHECK: i32.call $drop=, _Unwind_CallPersonality, $[[EXN]]
-; CHECK: block
-; CHECK: br_if 0
-; CHECK: i32.call $drop=, __cxa_begin_catch
-; CHECK: call __cxa_end_catch
-; CHECK: br 1
-; CHECK: end_block
-; CHECK: call __cxa_rethrow
-; CHECK: end_try
-; CHECK: end_block
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch $[[EXCEPT_REF:[0-9]+]]=
+; CHECK: global.set __stack_pointer
+; CHECK: block i32
+; CHECK: br_on_exn 0, __cpp_exception, $[[EXCEPT_REF]]
+; CHECK: rethrow
+; CHECK: end_block
+; CHECK: extract_exception $[[EXN:[0-9]+]]=
+; CHECK-DAG: i32.store __wasm_lpad_context
+; CHECK-DAG: i32.store __wasm_lpad_context+4
+; CHECK: i32.call $drop=, _Unwind_CallPersonality, $[[EXN]]
+; CHECK: block
+; CHECK: br_if 0
+; CHECK: i32.call $drop=, __cxa_begin_catch
+; CHECK: call __cxa_end_catch
+; CHECK: br 1
+; CHECK: end_block
+; CHECK: call __cxa_rethrow
+; CHECK: end_try
define void @test_catch() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:
invoke void @foo()
@@ -101,16 +98,13 @@ try.cont:
; }
; CHECK-LABEL: test_cleanup:
-; CHECK: block
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 0
-; CHECK: catch
-; CHECK: global.set __stack_pointer
-; CHECK: i32.call $drop=, _ZN4TempD2Ev
-; CHECK: rethrow
-; CHECK: end_try
-; CHECK: end_block
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch
+; CHECK: global.set __stack_pointer
+; CHECK: i32.call $drop=, _ZN4TempD2Ev
+; CHECK: rethrow
+; CHECK: end_try
define void @test_cleanup() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:
%t = alloca %struct.Temp, align 1
@@ -140,37 +134,28 @@ ehcleanup:
; }
; CHECK-LABEL: test_terminatepad
-; CHECK: block
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch
+; CHECK: i32.call $drop=, __cxa_begin_catch
; CHECK: try
; CHECK: call foo
-; CHECK: br 0
; CHECK: catch
-; CHECK: i32.call $drop=, __cxa_begin_catch
-; CHECK: block
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 0
-; CHECK: catch
-; CHECK: block
-; CHECK: try
-; CHECK: call __cxa_end_catch
-; CHECK: br 0
-; CHECK: catch
-; CHECK: block i32
-; CHECK: br_on_exn 0, __cpp_exception
-; CHECK: call __clang_call_terminate, 0
-; CHECK: unreachable
-; CHECK: end_block
-; CHECK: call __clang_call_terminate
-; CHECK: unreachable
-; CHECK: end_try
-; CHECK: end_block
-; CHECK: rethrow
-; CHECK: end_try
-; CHECK: end_block
-; CHECK: call __cxa_end_catch
+; CHECK: try
+; CHECK: call __cxa_end_catch
+; CHECK: catch
+; CHECK: block i32
+; CHECK: br_on_exn 0, __cpp_exception
+; CHECK: call __clang_call_terminate, 0
+; CHECK: unreachable
+; CHECK: end_block
+; CHECK: call __clang_call_terminate
+; CHECK: unreachable
+; CHECK: end_try
+; CHECK: rethrow
; CHECK: end_try
-; CHECK: end_block
+; CHECK: call __cxa_end_catch
+; CHECK: end_try
define void @test_terminatepad() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:
invoke void @foo()
@@ -227,34 +212,30 @@ terminate:
; }
; CHECK-LABEL: test_no_prolog_epilog_in_ehpad
-; CHECK: block
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 0
-; CHECK: catch
-; CHECK-NOT: global.get $push{{.+}}=, __stack_pointer
-; CHECK: global.set __stack_pointer
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch
+; CHECK-NOT: global.get $push{{.+}}=, __stack_pointer
+; CHECK: global.set __stack_pointer
+; CHECK: block
; CHECK: block
-; CHECK: block
-; CHECK: br_if 0
-; CHECK: i32.call $drop=, __cxa_begin_catch
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 2
-; CHECK: catch
-; CHECK-NOT: global.get $push{{.+}}=, __stack_pointer
-; CHECK: global.set __stack_pointer
-; CHECK: call __cxa_end_catch
-; CHECK: rethrow
-; CHECK-NOT: global.set __stack_pointer, $pop{{.+}}
-; CHECK: end_try
-; CHECK: end_block
-; CHECK: call __cxa_rethrow
+; CHECK: br_if 0
+; CHECK: i32.call $drop=, __cxa_begin_catch
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch
+; CHECK-NOT: global.get $push{{.+}}=, __stack_pointer
+; CHECK: global.set __stack_pointer
+; CHECK: call __cxa_end_catch
+; CHECK: rethrow
+; CHECK-NOT: global.set __stack_pointer, $pop{{.+}}
+; CHECK: end_try
; CHECK: end_block
-; CHECK-NOT: global.set __stack_pointer, $pop{{.+}}
-; CHECK: call __cxa_end_catch
-; CHECK: end_try
-; CHECK: end_block
+; CHECK: call __cxa_rethrow
+; CHECK: end_block
+; CHECK-NOT: global.set __stack_pointer, $pop{{.+}}
+; CHECK: call __cxa_end_catch
+; CHECK: end_try
define void @test_no_prolog_epilog_in_ehpad() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:
%stack_var = alloca i32, align 4
@@ -309,15 +290,12 @@ ehcleanup:
; }
; CHECK-LABEL: test_no_sp_writeback
-; CHECK: block
-; CHECK: try
-; CHECK: call foo
-; CHECK: br 0
-; CHECK: catch
-; CHECK: i32.call $drop=, __cxa_begin_catch
-; CHECK: call __cxa_end_catch
-; CHECK: end_try
-; CHECK: end_block
+; CHECK: try
+; CHECK: call foo
+; CHECK: catch
+; CHECK: i32.call $drop=, __cxa_begin_catch
+; CHECK: call __cxa_end_catch
+; CHECK: end_try
; CHECK-NOT: global.set __stack_pointer
; CHECK: return
define void @test_no_sp_writeback() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
More information about the llvm-commits
mailing list