summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2020-12-27 02:52:43 -0800
committerHeejin Ahn <aheejin@gmail.com>2021-01-09 03:42:38 -0800
commit4e4df1e38d6b66083b3badb78e56b8b0f6045fd1 (patch)
treeac44616a117cccb6bd07c713ef492adae55c6ecf
parent2c442629f0bd210fdb76fa409e131c87387e884d (diff)
downloadllvm-4e4df1e38d6b66083b3badb78e56b8b0f6045fd1.tar.gz
[WebAssembly] Remove unreachable EH pads
This removes unreachable EH pads in LateEHPrepare. This is not for optimization but for preparation for CFGStackify. In CFGStackify, we determine where to place `try` marker by computing the nearest common dominator of all predecessors of an EH pad, but when an EH pad does not have a predecessor, it becomes tricky. We can insert an empty dummy BB before the EH pad and place the `try` there, but removing unreachable EH pads is simpler. This moves an existing exception label test from eh-label.mir to exception.mir and adds a new test there. This also adds some comments to existing methods. Reviewed By: dschuff, tlively Differential Revision: https://reviews.llvm.org/D94044
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp32
-rw-r--r--llvm/test/CodeGen/WebAssembly/exception.mir (renamed from llvm/test/CodeGen/WebAssembly/eh-labels.mir)33
2 files changed, 56 insertions, 9 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
index 5501af0b2bbd..a0201b199612 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
@@ -15,7 +15,7 @@
#include "WebAssembly.h"
#include "WebAssemblySubtarget.h"
#include "WebAssemblyUtilities.h"
-#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/WasmEHFuncInfo.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -32,6 +32,7 @@ class WebAssemblyLateEHPrepare final : public MachineFunctionPass {
}
bool runOnMachineFunction(MachineFunction &MF) override;
+ bool removeUnreachableEHPads(MachineFunction &MF);
void recordCatchRetBBs(MachineFunction &MF);
bool hoistCatches(MachineFunction &MF);
bool addCatchAlls(MachineFunction &MF);
@@ -40,7 +41,7 @@ class WebAssemblyLateEHPrepare final : public MachineFunctionPass {
bool restoreStackPointer(MachineFunction &MF);
MachineBasicBlock *getMatchingEHPad(MachineInstr *MI);
- SmallSet<MachineBasicBlock *, 8> CatchRetBBs;
+ SmallPtrSet<MachineBasicBlock *, 8> CatchRetBBs;
public:
static char ID; // Pass identification, replacement for typeid
@@ -94,14 +95,18 @@ WebAssemblyLateEHPrepare::getMatchingEHPad(MachineInstr *MI) {
template <typename Container>
static void eraseDeadBBsAndChildren(const Container &MBBs) {
SmallVector<MachineBasicBlock *, 8> WL(MBBs.begin(), MBBs.end());
+ SmallPtrSet<MachineBasicBlock *, 8> Deleted;
while (!WL.empty()) {
MachineBasicBlock *MBB = WL.pop_back_val();
- if (!MBB->pred_empty())
+ if (Deleted.count(MBB) || !MBB->pred_empty())
continue;
SmallVector<MachineBasicBlock *, 4> Succs(MBB->successors());
WL.append(MBB->succ_begin(), MBB->succ_end());
for (auto *Succ : Succs)
MBB->removeSuccessor(Succ);
+ // To prevent deleting the same BB multiple times, which can happen when
+ // 'MBBs' contain both a parent and a child
+ Deleted.insert(MBB);
MBB->eraseFromParent();
}
}
@@ -117,6 +122,7 @@ bool WebAssemblyLateEHPrepare::runOnMachineFunction(MachineFunction &MF) {
bool Changed = false;
if (MF.getFunction().hasPersonalityFn()) {
+ Changed |= removeUnreachableEHPads(MF);
recordCatchRetBBs(MF);
Changed |= hoistCatches(MF);
Changed |= addCatchAlls(MF);
@@ -128,9 +134,20 @@ bool WebAssemblyLateEHPrepare::runOnMachineFunction(MachineFunction &MF) {
return Changed;
}
-// Record which BB ends with 'CATCHRET' instruction, because this will be
-// replaced with BRs later. This set of 'CATCHRET' BBs is necessary in
-// 'getMatchingEHPad' function.
+// Remove unreachable EH pads and its children. If they remain, CFG
+// stackification can be tricky.
+bool WebAssemblyLateEHPrepare::removeUnreachableEHPads(MachineFunction &MF) {
+ SmallVector<MachineBasicBlock *, 4> ToDelete;
+ for (auto &MBB : MF)
+ if (MBB.isEHPad() && MBB.pred_empty())
+ ToDelete.push_back(&MBB);
+ eraseDeadBBsAndChildren(ToDelete);
+ return !ToDelete.empty();
+}
+
+// Record which BB ends with catchret instruction, because this will be replaced
+// with 'br's later. This set of catchret BBs is necessary in 'getMatchingEHPad'
+// function.
void WebAssemblyLateEHPrepare::recordCatchRetBBs(MachineFunction &MF) {
CatchRetBBs.clear();
for (auto &MBB : MF) {
@@ -204,6 +221,8 @@ bool WebAssemblyLateEHPrepare::addCatchAlls(MachineFunction &MF) {
return Changed;
}
+// Replace pseudo-instructions catchret and cleanupret with br and rethrow
+// respectively.
bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
bool Changed = false;
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
@@ -239,6 +258,7 @@ bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
return Changed;
}
+// Remove unnecessary unreachables after a throw or rethrow.
bool WebAssemblyLateEHPrepare::removeUnnecessaryUnreachables(
MachineFunction &MF) {
bool Changed = false;
diff --git a/llvm/test/CodeGen/WebAssembly/eh-labels.mir b/llvm/test/CodeGen/WebAssembly/exception.mir
index 105b21acc4f7..0548123f315b 100644
--- a/llvm/test/CodeGen/WebAssembly/eh-labels.mir
+++ b/llvm/test/CodeGen/WebAssembly/exception.mir
@@ -1,7 +1,5 @@
# 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"
@@ -11,10 +9,15 @@
define void @eh_label_test() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
ret void
}
+ define void @unreachable_ehpad_test() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
+ ret void
+ }
...
---
-# CHECK-LABEL: eh_label_test
+# This tests 'try' and 'catch' instructions are correctly placed with respect to
+# EH_LABEL instructions.
+# CHECK-LABEL: name: eh_label_test
name: eh_label_test
liveins:
- { reg: '$arguments' }
@@ -44,3 +47,27 @@ body: |
; predecessors: %bb.0, %bb.1
RETURN implicit-def dead $arguments
...
+---
+# Unreachable EH pads should be removed by LateEHPrepare.
+# CHECK-LABEL: name: unreachable_ehpad_test
+name: unreachable_ehpad_test
+liveins:
+ - { reg: '$arguments' }
+body: |
+ ; CHECK: bb.0
+ bb.0:
+ successors: %bb.2
+ BR %bb.2, implicit-def dead $arguments
+
+ ; This EH pad is unreachable, so it should be removed by LateEHPrepare
+ ; CHECK-NOT: bb.1 (landing-pad)
+ bb.1 (landing-pad):
+ successors: %bb.2
+ EH_LABEL <mcsymbol .Ltmp2>
+ CATCHRET %bb.2, %bb.0, implicit-def dead $arguments
+
+ ; CHECK: bb.2
+ bb.2:
+ ; predecessors: %bb.0, %bb.1
+ RETURN implicit-def dead $arguments
+...