mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[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
This commit is contained in:
parent
cb8596965c
commit
58fd110047
@ -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;
|
||||
|
@ -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
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user