[PATCH] D15139: [IR] Reformulate LLVM's EH funclet IR

Andy Kaylor via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 11 15:53:42 PST 2015


andrew.w.kaylor accepted this revision.
andrew.w.kaylor added a comment.
This revision is now accepted and ready to land.

Except for the irreducible loop issue, this looks good to me.  I would be OK with putting off addressing that problem until some later time, as it seems like a fairly unlikely corner case, but I do think we should probably think about it.


================
Comment at: lib/CodeGen/WinEHPrepare.cpp:223-232
@@ -250,13 +222,12 @@
 
-static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
-                                             const BasicBlock &BB,
-                                             int ParentState) {
-  assert(BB.isEHPad());
-  const Instruction *FirstNonPHI = BB.getFirstNonPHI();
-  // All catchpad instructions will be handled when we process their
-  // respective catchendpad instruction.
-  if (isa<CatchPadInst>(FirstNonPHI))
-    return;
+static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo,
+                                     const Instruction *FirstNonPHI,
+                                     int ParentState) {
+  const BasicBlock *BB = FirstNonPHI->getParent();
+  assert(BB->isEHPad() && "not a funclet!");
+
+  if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
+    assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
+           "shouldn't revist catch funclets!");
 
     SmallVector<const CatchPadInst *, 2> Handlers;
----------------
Sounds like a plan.

================
Comment at: lib/CodeGen/WinEHPrepare.cpp:250
@@ +249,3 @@
+    for (const auto *CatchPad : Handlers) {
+      FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow;
+      for (const User *U : CatchPad->users()) {
----------------
OK, if MSVC does this also then I feel a lot better about the long term viability of doing it this way.

================
Comment at: test/CodeGen/WinEH/wineh-cloning.ll:288-289
@@ -370,75 +287,4 @@
     to label %unreachable unwind label %right
 left:
-  cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %unreachable unwind label %inner
-inner:
-  cleanuppad []
-  invoke void @f()
-    to label %unreachable unwind label %inner.child
-inner.child:
-  cleanuppad []
-  %x = call i32 @g()
-  call void @h(i32 %x)
-  unreachable
-unreachable:
-  unreachable
-}
-; %inner is a two-parent child which itself has a child; need
-; to make two copies of both the %inner and %inner.child.
-; CHECK-LABEL: define void @test8(
-; CHECK:     invoke.cont:
-; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
-; CHECK:     left:
-; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:               to label %right.catch unwind label %right.end
-; CHECK:     right.catch:
-; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:               to label %[[UNREACHABLE_INNER_RIGHT:.+]] unwind label %[[INNER_CHILD_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:               to label %[[UNREACHABLE_INNER_LEFT:.+]] unwind label %[[INNER_CHILD_LEFT:.+]]
-; CHECK:     [[INNER_CHILD_RIGHT]]:
-; CHECK:       [[TMP:\%.+]] = cleanuppad []
-; CHECK:       [[X:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X]])
-; CHECK:       unreachable
-; CHECK:     [[INNER_CHILD_LEFT]]:
-; CHECK:       [[TMP:\%.+]] = cleanuppad []
-; CHECK:       [[X:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X]])
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_INNER_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_INNER_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_ENTRY]]:
-; CHECK:       unreachable
-
-
-define void @test9() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %unreachable unwind label %right
-left:
-  cleanuppad []
+  cleanuppad within none []
   call void @h(i32 1)
----------------
The original concern was that some future optimization would innocently transform otherwise reasonable code into this form.  I think the hypothetically dangerous input looked something like this:
```
left:
  cleanuppad within none []
  call void @h(i32 1)
  invoke void @f()
    to label %unreachable unwind label %not_right
not_right:
  cleanuppad within none []
  call void @h(i32 2)
  call void @f()
  unreachable
right:
  cleanuppad within none []
  call void @h(i32 2)
  invoke void @f()
    to label %unreachable unwind label %not_left
not_left:
  cleanuppad within none []
  call void @h(i32 1)
  call void @f()
  unreachable
```
So if we can get that out of the clang front end, then a reasonable optimization could transform it into this test case, and I don't see how the code generator could do anything reasonable with the form shown in this test case.


http://reviews.llvm.org/D15139





More information about the llvm-commits mailing list