[llvm-branch-commits] [llvm] 4e4df1e - [WebAssembly] Remove unreachable EH pads

Heejin Ahn via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jan 9 03:47:37 PST 2021


Author: Heejin Ahn
Date: 2021-01-09T03:42:38-08:00
New Revision: 4e4df1e38d6b66083b3badb78e56b8b0f6045fd1

URL: https://github.com/llvm/llvm-project/commit/4e4df1e38d6b66083b3badb78e56b8b0f6045fd1
DIFF: https://github.com/llvm/llvm-project/commit/4e4df1e38d6b66083b3badb78e56b8b0f6045fd1.diff

LOG: [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

Added: 
    llvm/test/CodeGen/WebAssembly/exception.mir

Modified: 
    llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp

Removed: 
    llvm/test/CodeGen/WebAssembly/eh-labels.mir


################################################################################
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
similarity index 64%
rename from llvm/test/CodeGen/WebAssembly/eh-labels.mir
rename to 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
+...


        


More information about the llvm-branch-commits mailing list