aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2020-05-25 01:34:43 -0700
committerHeejin Ahn <aheejin@gmail.com>2020-05-28 19:44:27 -0700
commit3fe6ea4641b20c3406e2ef10c0f3782788585030 (patch)
tree5569f942074ad26264278fbcad84ccedad4d7a6a /llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
parent59ba12994c07d03ac3b628c05c45a834774f9b17 (diff)
downloadllvm-3fe6ea4641b20c3406e2ef10c0f3782788585030.zip
llvm-3fe6ea4641b20c3406e2ef10c0f3782788585030.tar.gz
llvm-3fe6ea4641b20c3406e2ef10c0f3782788585030.tar.bz2
[WebAssembly] Fix a bug in removing unnecessary branches
Summary: One of the things `removeUnnecessaryInstrs()` in CFGStackify does is to remove an unnecessary unconditinal branch before an EH pad. 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 ``` This applies when we have a conditional branch followed by an unconditional one, in which case we should only remove the unconditional branch. For example: ``` bb0: try ... br_if someplace_else br bb2 <- Not necessary bb1: catch ... bb2: end ``` But `TargetInstrInfo::removeBranch` we used removed all existing branches when there are multiple ones. This patch fixes it by only deleting the last (= unconditional) branch manually. Also fixes some `preds` comments in the test file. Reviewers: dschuff Subscribers: sbc100, jgravelle-google, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D80572
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp22
1 files changed, 20 insertions, 2 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 23a5aa6..103fe97 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -670,9 +670,27 @@ void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {
MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode();
MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent();
bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
+ // This condition means either
+ // 1. This BB ends with a single unconditional branch whose destinaion is
+ // Cont.
+ // 2. This BB ends with a conditional branch followed by an unconditional
+ // branch, and the unconditional branch's destination is Cont.
+ // In both cases, we want to remove the last (= unconditional) branch.
if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) ||
- (!Cond.empty() && FBB && FBB == Cont)))
- TII.removeBranch(*EHPadLayoutPred);
+ (!Cond.empty() && FBB && FBB == Cont))) {
+ bool ErasedUncondBr = false;
+ for (auto I = EHPadLayoutPred->end(), E = EHPadLayoutPred->begin();
+ I != E; --I) {
+ auto PrevI = std::prev(I);
+ if (PrevI->isTerminator()) {
+ assert(PrevI->getOpcode() == WebAssembly::BR);
+ PrevI->eraseFromParent();
+ ErasedUncondBr = true;
+ break;
+ }
+ }
+ assert(ErasedUncondBr && "Unconditional branch not erased!");
+ }
}
// When there are block / end_block markers that overlap with try / end_try