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 Invokes, + // 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 @@ -17,31 +17,28 @@ ; CHECK-NEXT: .cfi_offset lr, 16 ; CHECK-NEXT: mr 31, 1 ; CHECK-NEXT: .cfi_def_cfa_register r31 -; CHECK-NEXT: .cfi_offset r27, -40 ; CHECK-NEXT: .cfi_offset r28, -32 ; CHECK-NEXT: .cfi_offset r29, -24 ; CHECK-NEXT: .cfi_offset r30, -16 -; CHECK-NEXT: std 29, 152(31) # 8-byte Folded Spill -; CHECK-NEXT: mr 29, 3 -; CHECK-NEXT: rldic 3, 5, 3, 29 -; CHECK-NEXT: std 27, 136(31) # 8-byte Folded Spill ; CHECK-NEXT: std 30, 160(31) # 8-byte Folded Spill ; CHECK-NEXT: mr 30, 4 -; CHECK-NEXT: addi 3, 3, 15 -; CHECK-NEXT: rldicl 3, 3, 60, 4 -; CHECK-NEXT: mr 27, 1 -; CHECK-NEXT: rldicl 3, 3, 4, 28 -; CHECK-NEXT: addi 4, 31, 176 -; CHECK-NEXT: neg 3, 3 +; CHECK-NEXT: rldic 4, 5, 3, 29 +; CHECK-NEXT: std 29, 152(31) # 8-byte Folded Spill +; CHECK-NEXT: mr 29, 3 +; CHECK-NEXT: addi 4, 4, 15 +; CHECK-NEXT: rldicl 4, 4, 60, 4 +; CHECK-NEXT: addi 3, 31, 176 +; CHECK-NEXT: rldicl 4, 4, 4, 28 ; CHECK-NEXT: std 28, 144(31) # 8-byte Folded Spill -; CHECK-NEXT: stdux 4, 1, 3 +; CHECK-NEXT: neg 4, 4 +; CHECK-NEXT: stdux 3, 1, 4 ; CHECK-NEXT: addi 3, 1, 112 ; CHECK-NEXT: .Ltmp0: ; CHECK-NEXT: bl Foo ; CHECK-NEXT: nop ; CHECK-NEXT: .Ltmp1: ; CHECK-NEXT: # %bb.1: # %bb30.preheader -; CHECK-NEXT: addi 28, 31, 120 +; CHECK-NEXT: addi 28, 31, 128 ; CHECK-NEXT: cmpldi 30, 0 ; CHECK-NEXT: beq 0, .LBB0_4 ; CHECK-NEXT: .LBB0_2: # %cond_true @@ -54,7 +51,7 @@ ; CHECK-NEXT: .Ltmp4: ; CHECK-NEXT: # %bb.3: # %invcont23 ; CHECK-NEXT: # -; CHECK-NEXT: ld 3, 128(31) +; CHECK-NEXT: ld 3, 136(31) ; CHECK-NEXT: sub 30, 30, 3 ; CHECK-NEXT: cmpldi 30, 0 ; CHECK-NEXT: bne 0, .LBB0_2 @@ -62,7 +59,6 @@ ; CHECK-NEXT: ld 30, 160(31) # 8-byte Folded Reload ; CHECK-NEXT: ld 29, 152(31) # 8-byte Folded Reload ; CHECK-NEXT: ld 28, 144(31) # 8-byte Folded Reload -; CHECK-NEXT: ld 27, 136(31) # 8-byte Folded Reload ; CHECK-NEXT: ld 1, 0(1) ; CHECK-NEXT: ld 0, 16(1) ; CHECK-NEXT: ld 31, -8(1) @@ -70,13 +66,8 @@ ; CHECK-NEXT: blr ; CHECK-NEXT: .LBB0_5: # %unwind.loopexit.split-lp ; CHECK-NEXT: .Ltmp2: -; CHECK-NEXT: b .LBB0_7 ; CHECK-NEXT: .LBB0_6: # %unwind.loopexit ; CHECK-NEXT: .Ltmp5: -; CHECK-NEXT: .LBB0_7: # %unwind -; CHECK-NEXT: ld 3, 0(1) -; CHECK-NEXT: mr 1, 27 -; CHECK-NEXT: std 3, 0(1) entry: %effectiveRange = alloca %struct.Range, align 8 ; <%struct.Range*> [#uses=2] %tmp4 = call i8* @llvm.stacksave() ; [#uses=1] 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: