Skip to content

Commit

Permalink
[WinEH] Ignore lifetime.end PHI nodes in empty cleanuppads
Browse files Browse the repository at this point in the history
This fixes a bug where a PHI node that is only referenced by a lifetime.end intrinsic in an otherwise empty cleanuppad can cause SimplyCFG to create an SSA violation while removing the empty cleanuppad. Theoretically the same problem can occur with debug intrinsics.

Differential Revision: https://reviews.llvm.org/D72540
  • Loading branch information
andykaylor committed Jan 24, 2020
1 parent 580d783 commit c467faf
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 3 deletions.
7 changes: 4 additions & 3 deletions llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Expand Up @@ -4083,9 +4083,10 @@ static bool removeEmptyCleanup(CleanupReturnInst *RI) {
// The iterator must be incremented here because the instructions are
// being moved to another block.
PHINode *PN = cast<PHINode>(I++);
if (PN->use_empty())
// If the PHI node has no uses, just leave it. It will be erased
// when we erase BB below.
if (PN->use_empty() || !PN->isUsedOutsideOfBlock(BB))
// If the PHI node has no uses or all of its uses are in this basic
// block (meaning they are debug or lifetime intrinsics), just leave
// it. It will be erased when we erase BB below.
continue;

// Otherwise, sink this PHI node into UnwindDest.
Expand Down
49 changes: 49 additions & 0 deletions llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll
Expand Up @@ -458,6 +458,55 @@ cleanupret2:
cleanupret from %cp unwind to caller
}

; CHECK-LABEL: define void @f11(
; This case tests the handling of an empty cleanup pad that
; contains a lifetime_end intrinsic and does not dominate its
; successor.
; CHECK: entry:
; CHECK: invoke void @g()
; CHECK: invoke.cont:
; CHECK: invoke void @g()
; CHECK: invoke.cont2:
; CHECK: invoke void @g()
; CHECK-NOT: ehcleanup:
; CHECK-NOT: phi
; CHECK-NOT: cleanuppad
; CHECK-NOT: lifetime.end
; CHECK: catch.dispatch:
; CHECK: catchswitch
; CHECK: catch:
; CHECK: catchret
; CHECK: }
define void @f11() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
invoke void @g()
to label %invoke.cont unwind label %ehcleanup

invoke.cont: ; preds = %entry
invoke void @g()
to label %invoke.cont2 unwind label %ehcleanup

invoke.cont2: ; preds = %invoke.cont
invoke void @g()
to label %return unwind label %catch.dispatch

ehcleanup: ; preds = %invoke.cont, %entry
%x = phi i8* [ undef, %invoke.cont ], [ undef, %entry ]
%0 = cleanuppad within none []
call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %x)
cleanupret from %0 unwind label %catch.dispatch

catch.dispatch: ; preds = %ehcleanup, %invoke.cont
%cs1 = catchswitch within none [label %catch] unwind to caller

catch: ; preds = %catch.dispatch
%1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
catchret from %1 to label %return

return: ; preds = %invoke.cont, %catch.cont
ret void
}

%struct.S = type { i8 }
%struct.S2 = type { i8 }
declare void @"\01??1S2@@QEAA@XZ"(%struct.S2*)
Expand Down

0 comments on commit c467faf

Please sign in to comment.