diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -26,6 +26,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumeBundleQueries.h" #include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/GuardUtils.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/Loads.h" @@ -5273,6 +5274,18 @@ if (isa(I)) return false; + if (isa(I)) { + switch (classifyEHPersonality(I->getFunction()->getPersonalityFn())) { + default: + // A catchpad may invoke exception object constructors and such, which + // in some languages can be arbitrary code, so be conservative by default. + return false; + case EHPersonality::CoreCLR: + // For CoreCLR, it just involves a type test. + return true; + } + } + // An instruction that returns without throwing must transfer control flow // to a successor. return !I->mayThrow() && I->willReturn(); diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2870,6 +2870,7 @@ return nullptr; } +// WARNING: keep in sync with SimplifyCFGOpt::simplifyUnreachable()! Instruction *InstCombinerImpl::visitUnreachableInst(UnreachableInst &I) { // Try to remove the previous instruction if it must lead to unreachable. // This includes instructions like stores and "llvm.assume" that may not get diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4655,6 +4655,7 @@ return false; } +// WARNING: keep in sync with InstCombinerImpl::visitUnreachableInst()! bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { BasicBlock *BB = UI->getParent(); @@ -4665,39 +4666,24 @@ while (UI->getIterator() != BB->begin()) { BasicBlock::iterator BBI = UI->getIterator(); --BBI; - // Do not delete instructions that can have side effects which might cause - // the unreachable to not be reachable; specifically, calls and volatile - // operations may have this effect. - if (isa(BBI) && !isa(BBI)) - break; - if (BBI->mayHaveSideEffects()) { - if (auto *SI = dyn_cast(BBI)) { - // Temporarily disable removal of volatile stores preceding unreachable, - // pending a potential LangRef change permitting volatile stores to - // trap. - // TODO: Either remove this code, or properly integrate the check into - // isGuaranteedToTransferExecutionToSuccessor(). - if (SI->isVolatile()) - break; - } else if (isa(BBI)) { - // A catchpad may invoke exception object constructors and such, which - // in some languages can be arbitrary code, so be conservative by - // default. - // For CoreCLR, it just involves a type test, so can be removed. - if (classifyEHPersonality(BB->getParent()->getPersonalityFn()) != - EHPersonality::CoreCLR) - break; - } else if (!isa(BBI) && !isa(BBI) && - !isa(BBI) && !isa(BBI) && - !isa(BBI) && !isa(BBI)) { - break; - } - // Note that deleting LandingPad's here is in fact okay, although it - // involves a bit of subtle reasoning. If this inst is a LandingPad, - // all the predecessors of this block will be the unwind edges of Invokes, - // and we can therefore guarantee this block will be erased. - } + if (!isGuaranteedToTransferExecutionToSuccessor(&*BBI)) + break; // Can not drop any more instructions. We're done here. + // Otherwise, this instruction can be freely erased, + // even if it is not side-effect free. + + // Temporarily disable removal of volatile stores preceding unreachable, + // pending a potential LangRef change permitting volatile stores to trap. + // TODO: Either remove this code, or properly integrate the check into + // isGuaranteedToTransferExecutionToSuccessor(). + if (auto *SI = dyn_cast(&*BBI)) + if (SI->isVolatile()) + break; // Can not drop this instruction. We're done here. + + // Note that deleting EH's here is in fact okay, although it involves a bit + // of subtle reasoning. If this inst is an EH, all the predecessors of this + // block will be the unwind edges of Invoke/CatchSwitch/CleanupReturn, + // and we can therefore guarantee this block will be erased. // Delete this instruction (any uses are guaranteed to be dead) BBI->replaceAllUsesWith(PoisonValue::get(BBI->getType())); diff --git a/llvm/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll b/llvm/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll --- a/llvm/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll +++ b/llvm/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll @@ -74,9 +74,11 @@ ; CHECK-NEXT: .LBB0_6: # %unwind.loopexit ; CHECK-NEXT: .Ltmp5: ; CHECK-NEXT: .LBB0_7: # %unwind -; CHECK-NEXT: ld 3, 0(1) +; CHECK-NEXT: ld 4, 0(1) ; CHECK-NEXT: mr 1, 27 -; CHECK-NEXT: std 3, 0(1) +; CHECK-NEXT: std 4, 0(1) +; CHECK-NEXT: bl _Unwind_Resume +; CHECK-NEXT: nop entry: %effectiveRange = alloca %struct.Range, align 8 ; <%struct.Range*> [#uses=2] %tmp4 = call i8* @llvm.stacksave() ; [#uses=1] @@ -91,7 +93,7 @@ unwind: ; preds = %cond_true, %entry %exn = landingpad {i8*, i32} - catch i8* null + cleanup call void @llvm.stackrestore(i8* %tmp4) resume { i8*, i32 } %exn diff --git a/llvm/test/Transforms/SimplifyCFG/simplifyUnreachable-degenerate-conditional-branch-with-matching-destinations.ll b/llvm/test/Transforms/SimplifyCFG/simplifyUnreachable-degenerate-conditional-branch-with-matching-destinations.ll --- a/llvm/test/Transforms/SimplifyCFG/simplifyUnreachable-degenerate-conditional-branch-with-matching-destinations.ll +++ b/llvm/test/Transforms/SimplifyCFG/simplifyUnreachable-degenerate-conditional-branch-with-matching-destinations.ll @@ -8,9 +8,6 @@ define void @widget() { ; CHECK-LABEL: @widget( ; CHECK-NEXT: bb: -; CHECK-NEXT: [[I:%.*]] = load i16, i16* @global, align 1 -; CHECK-NEXT: [[I13:%.*]] = icmp ne i16 [[I]], 0 -; CHECK-NEXT: call void @llvm.assume(i1 [[I13]]) ; CHECK-NEXT: unreachable ; bb: diff --git a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll --- a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll @@ -116,8 +116,6 @@ define void @PR42737(i32* %a, i1 %c) { ; CHECK-LABEL: @PR42737( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: unreachable ; entry: