diff options
author | Heejin Ahn <aheejin@gmail.com> | 2019-02-27 00:50:53 +0000 |
---|---|---|
committer | Heejin Ahn <aheejin@gmail.com> | 2019-02-27 00:50:53 +0000 |
commit | cf699b4534e6e0285d1a6899b5237c5fd9100ab7 (patch) | |
tree | 3b2da62357bb85f10548932a310ae5a1153bda67 /llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | |
parent | 6d6288ae977bfdb08dc2b731f34d9b1ebfc68748 (diff) | |
download | bcm5719-llvm-cf699b4534e6e0285d1a6899b5237c5fd9100ab7.tar.gz bcm5719-llvm-cf699b4534e6e0285d1a6899b5237c5fd9100ab7.zip |
[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
llvm-svn: 354939
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 1efd34f8319..90017879839 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -64,6 +64,7 @@ class WebAssemblyCFGStackify final : public MachineFunctionPass { 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 : public MachineFunctionPass { // <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::registerTryScope(MachineInstr *Begin, 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::placeTryMarker(MachineBasicBlock &MBB) { 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::runOnMachineFunction(MachineFunction &MF) { LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n" "********** Function: " << MF.getName() << '\n'); + const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo(); releaseMemory(); @@ -756,6 +843,11 @@ bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) { // 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); |