Index: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp =================================================================== --- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp +++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp @@ -3085,6 +3085,33 @@ RemapInstruction(&I, VMap, RF_IgnoreMissingEntries); } + // Remove implausible terminators and replace them with UnreachableInst. + for (auto &Funclet : FuncletBlocks) { + BasicBlock *FuncletPadBB = Funclet.first; + std::set &BlocksInFunclet = Funclet.second; + Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI(); + auto *CatchPad = dyn_cast(FirstNonPHI); + auto *CleanupPad = dyn_cast(FirstNonPHI); + + for (BasicBlock *BB : BlocksInFunclet) { + TerminatorInst *TI = BB->getTerminator(); + // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst. + bool IsUnreachableRet = isa(TI) && (CatchPad || CleanupPad); + // The token consumed by a CatchReturnInst must match the funclet token. + bool IsUnreachableCatchret = false; + if (auto *CRI = dyn_cast(TI)) + IsUnreachableCatchret = CRI->getReturnValue() != CatchPad; + // The token consumed by a CleanupPadInst must match the funclet token. + bool IsUnreachableCleanupret = false; + if (auto *CRI = dyn_cast(TI)) + IsUnreachableCleanupret = CRI->getReturnValue() != CleanupPad; + if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) { + new UnreachableInst(BB->getContext(), TI); + TI->eraseFromParent(); + } + } + } + // Clean-up some of the mess we made by removing useles PHI nodes, trivial // branches, etc. for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) { @@ -3094,9 +3121,6 @@ MergeBlockIntoPredecessor(BB); } - // TODO: Do something about cleanupblocks which branch to implausible - // cleanuprets. - // We might have some unreachable blocks after cleaning up some impossible // control flow. removeUnreachableBlocks(F); @@ -3215,6 +3239,12 @@ void WinEHPrepare::demoteNonlocalUses(Value *V, std::set &ColorsForBB, Function &F) { + // Tokens can only be used non-locally due to control flow involving + // unreachable edges. Don't try to demote the token usage, we'll simply + // delete the cloned user later. + if (isa(V) || isa(V)) + return; + DenseMap Loads; AllocaInst *SpillSlot = nullptr; for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;) { Index: llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll =================================================================== --- llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll +++ llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll @@ -36,14 +36,14 @@ ; CHECK: merge: ; CHECK-NOT: = phi %phi = phi i32 [ %x, %left ], [ %y, %right ] - catchpad void [] to label %catch unwind label %catchend + %cp = catchpad token [] to label %catch unwind label %catchend catch: ; CHECK: catch: ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]] ; CHECK-NEXT: call void @h(i32 [[Reload]]) call void @h(i32 %phi) - catchret void to label %exit + catchret token %cp to label %exit catchend: catchendpad unwind to caller @@ -75,9 +75,9 @@ merge.inner: ; CHECK: merge.inner: ; CHECK-NOT: = phi - ; CHECK: catchpad void + ; CHECK: catchpad token %x = phi i32 [ 1, %left ], [ 2, %right ] - catchpad void [] to label %catch.inner unwind label %catchend.inner + %cpinner = catchpad token [] to label %catch.inner unwind label %catchend.inner catch.inner: ; Need just one store here because only %y is affected @@ -89,16 +89,16 @@ to label %catchret.inner unwind label %merge.outer catchret.inner: - catchret void to label %exit + catchret token %cpinner to label %exit catchend.inner: catchendpad unwind label %merge.outer merge.outer: ; CHECK: merge.outer: ; CHECK-NOT: = phi - ; CHECK: catchpad void + ; CHECK: [[CatchPad:%[^ ]+]] = catchpad token %y = phi i32 [ %x, %catchend.inner ], [ %z, %catch.inner ] - catchpad void [] to label %catch.outer unwind label %catchend.outer + %cpouter = catchpad token [] to label %catch.outer unwind label %catchend.outer catchend.outer: catchendpad unwind to caller @@ -109,10 +109,10 @@ ; CHECK: catch.outer: ; CHECK-DAG: load i32, i32* [[Slot1]] ; CHECK-DAG: load i32, i32* [[Slot2]] - ; CHECK: catchret void to label + ; CHECK: catchret token [[CatchPad]] to label call void @h(i32 %x) call void @h(i32 %y) - catchret void to label %exit + catchret token %cpouter to label %exit exit: ret void @@ -131,7 +131,7 @@ to label %exit unwind label %catchpad catchpad: - catchpad void [] to label %catch unwind label %catchend + %cp = catchpad token [] to label %catch unwind label %catchend catch: ; Need to reload %B here @@ -152,7 +152,7 @@ ; CHECK: %phi = phi i32 [ [[ReloadX]], %left ] %phi = phi i32 [ %x, %left ], [ 42, %right ] call void @h(i32 %phi) - catchret void to label %exit + catchret token %cp to label %exit catchend: catchendpad unwind to caller @@ -188,11 +188,11 @@ to label %join unwind label %catchpad.inner catchpad.inner: ; CHECK: catchpad.inner: - ; CHECK-NEXT: catchpad void + ; CHECK-NEXT: catchpad token %phi.inner = phi i32 [ %l, %left ], [ %r, %right ] - catchpad void [] to label %catch.inner unwind label %catchend.inner + %cp1 = catchpad token [] to label %catch.inner unwind label %catchend.inner catch.inner: - catchret void to label %join + catchret token %cp1 to label %join catchend.inner: catchendpad unwind label %catchpad.outer join: @@ -205,15 +205,15 @@ to label %exit unwind label %catchpad.outer catchpad.outer: ; CHECK: catchpad.outer: - ; CHECK-NEXT: catchpad void + ; CHECK-NEXT: catchpad token %phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ] - catchpad void [] to label %catch.outer unwind label %catchend.outer + %cp2 = catchpad token [] to label %catch.outer unwind label %catchend.outer catch.outer: ; CHECK: catch.outer: ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]] ; CHECK: call void @h(i32 [[Reload]]) call void @h(i32 %phi.outer) - catchret void to label %exit + catchret token %cp2 to label %exit catchend.outer: catchendpad unwind to caller exit: @@ -241,10 +241,10 @@ cleanup: ; cleanup phi can be loaded at cleanup entry ; CHECK: cleanup: - ; CHECK-NEXT: cleanuppad void + ; CHECK-NEXT: cleanuppad token ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]] %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ] - cleanuppad void [] + %cp = cleanuppad token [] %b = call i1 @i() br i1 %b, label %left, label %right @@ -264,8 +264,8 @@ ; need store for %phi.catch ; CHECK: merge: ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]] - ; CHECK-NEXT: cleanupret void - cleanupret void unwind label %catchpad + ; CHECK-NEXT: cleanupret token + cleanupret token %cp unwind label %catchpad invoke.cont2: ; need store for %phi.catch @@ -277,16 +277,16 @@ catchpad: ; CHECK: catchpad: - ; CHECK-NEXT: catchpad void + ; CHECK-NEXT: catchpad token %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ] - catchpad void [] to label %catch unwind label %catchend + %cp2 = catchpad token [] to label %catch unwind label %catchend catch: ; CHECK: catch: ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]] ; CHECK: call void @h(i32 [[CatchReload]] call void @h(i32 %phi.catch) - catchret void to label %exit + catchret token %cp2 to label %exit catchend: catchendpad unwind to caller @@ -310,8 +310,8 @@ ; CHECK: store i32 %x, i32* [[SpillSlot:%[^ ]+]] ; CHECK: br label %loop to_caller: - cleanuppad void [] - cleanupret void unwind to caller + %cp1 = cleanuppad token [] + cleanupret token %cp1 unwind to caller loop: invoke void @f() to label %loop unwind label %cleanup @@ -319,9 +319,9 @@ ; CHECK: cleanup: ; CHECK: [[Load:%[^ ]+]] = load i32, i32* [[SpillSlot]] ; CHECK: call void @h(i32 [[Load]]) - cleanuppad void [] + %cp2 = cleanuppad token [] call void @h(i32 %x) - cleanupret void unwind to caller + cleanupret token %cp2 unwind to caller } ; CHECK-LABEL: @test7( @@ -343,9 +343,9 @@ catchpad: ; %x phi should be eliminated ; CHECK: catchpad: - ; CHECK-NEXT: catchpad void + ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad token %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ] - catchpad void [] to label %catch unwind label %catchend + %cp = catchpad token [] to label %catch unwind label %catchend catch: %b = call i1 @i() br i1 %b, label %left, label %right @@ -353,8 +353,8 @@ ; Edge from %left to %join needs to be split so that ; the load of %x can be inserted *after* the catchret ; CHECK: left: - ; CHECK-NEXT: catchret void to label %[[SplitLeft:[^ ]+]] - catchret void to label %join + ; CHECK-NEXT: catchret token %[[CatchPad]] to label %[[SplitLeft:[^ ]+]] + catchret token %cp to label %join ; CHECK: [[SplitLeft]]: ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]] ; CHECK: br label %join @@ -363,9 +363,9 @@ ; the load of %y can be inserted *after* the catchret ; CHECK: right: ; CHECK: store i32 %y, i32* [[SlotY:%[^ ]+]] - ; CHECK: catchret void to label %[[SplitRight:[^ ]+]] + ; CHECK: catchret token %[[CatchPad]] to label %[[SplitRight:[^ ]+]] %y = call i32 @g() - catchret void to label %join + catchret token %cp to label %join ; CHECK: [[SplitRight]]: ; CHECK: [[LoadY:%[^ ]+]] = load i32, i32* [[SlotY]] ; CHECK: br label %join @@ -380,3 +380,32 @@ exit: ret void } + +; CHECK-LABEL: @test8( +define void @test8() personality i32 (...)* @__CxxFrameHandler3 { entry: + invoke void @f() + to label %done unwind label %cleanup1 + invoke void @f() + to label %done unwind label %cleanup2 + +done: + ret void + +cleanup1: + ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad token + ; CHECK-NEXT: call void @f() + ; CHECK-NEXT: cleanupret token [[CleanupPad1]] + %cp0 = cleanuppad token [] + br label %cleanupexit + +cleanup2: + ; CHECK: cleanuppad token + ; CHECK-NEXT: call void @f() + ; CHECK-NEXT: unreachable + %cp1 = cleanuppad token [] + br label %cleanupexit + +cleanupexit: + call void @f() + cleanupret token %cp0 unwind label %cleanup2 +}