From: Nikita Popov Date: Thu, 18 Feb 2021 21:29:19 +0000 (+0100) Subject: [DCE] Don't remove non-willreturn calls X-Git-Tag: llvmorg-14-init~14624 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2f17ed294fcd8cde505b93c9c5bbab06ba59051c;p=platform%2Fupstream%2Fllvm.git [DCE] Don't remove non-willreturn calls In both ADCE and BDCE (via DemandedBits) we should not remove instructions that are not guaranteed to return. This issue was pointed out by fhahn in the recent llvm-dev thread. Differential Revision: https://reviews.llvm.org/D96993 --- diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp index 461fd72..dd11b0b 100644 --- a/llvm/lib/Analysis/DemandedBits.cpp +++ b/llvm/lib/Analysis/DemandedBits.cpp @@ -80,7 +80,7 @@ void DemandedBitsWrapperPass::print(raw_ostream &OS, const Module *M) const { static bool isAlwaysLive(Instruction *I) { return I->isTerminator() || isa(I) || I->isEHPad() || - I->mayHaveSideEffects(); + I->mayHaveSideEffects() || !I->willReturn(); } void DemandedBits::determineLiveOperandBits( diff --git a/llvm/lib/Transforms/Scalar/ADCE.cpp b/llvm/lib/Transforms/Scalar/ADCE.cpp index 2b64973..ce4e5e5 100644 --- a/llvm/lib/Transforms/Scalar/ADCE.cpp +++ b/llvm/lib/Transforms/Scalar/ADCE.cpp @@ -325,7 +325,7 @@ void AggressiveDeadCodeElimination::initialize() { bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &I) { // TODO -- use llvm::isInstructionTriviallyDead - if (I.isEHPad() || I.mayHaveSideEffects()) { + if (I.isEHPad() || I.mayHaveSideEffects() || !I.willReturn()) { // Skip any value profile instrumentation calls if they are // instrumenting constants. if (isInstrumentsConstant(I)) diff --git a/llvm/test/Feature/OperandBundles/adce.ll b/llvm/test/Feature/OperandBundles/adce.ll index a729ba7..fa4e045 100644 --- a/llvm/test/Feature/OperandBundles/adce.ll +++ b/llvm/test/Feature/OperandBundles/adce.ll @@ -5,8 +5,8 @@ ; bundles since the presence of unknown operand bundles implies ; arbitrary memory effects. -declare void @readonly_function() readonly nounwind -declare void @readnone_function() readnone nounwind +declare void @readonly_function() readonly nounwind willreturn +declare void @readnone_function() readnone nounwind willreturn define void @test0() { ; CHECK-LABEL: @test0( diff --git a/llvm/test/LTO/X86/parallel.ll b/llvm/test/LTO/X86/parallel.ll index b3c1281..34235ec 100644 --- a/llvm/test/LTO/X86/parallel.ll +++ b/llvm/test/LTO/X86/parallel.ll @@ -11,7 +11,7 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK0-NOT: bar ; CHECK0: T foo ; CHECK0-NOT: bar -define void @foo() { +define void @foo() mustprogress { call void @bar() ret void } @@ -19,7 +19,7 @@ define void @foo() { ; CHECK1-NOT: foo ; CHECK1: T bar ; CHECK1-NOT: foo -define void @bar() { +define void @bar() mustprogress { call void @foo() ret void } diff --git a/llvm/test/Transforms/ADCE/dce_pure_call.ll b/llvm/test/Transforms/ADCE/dce_pure_call.ll index 66483ab..88e92bf 100644 --- a/llvm/test/Transforms/ADCE/dce_pure_call.ll +++ b/llvm/test/Transforms/ADCE/dce_pure_call.ll @@ -1,6 +1,6 @@ ; RUN: opt -adce -S < %s | not grep call -declare i32 @strlen(i8*) readonly nounwind +declare i32 @strlen(i8*) readonly nounwind willreturn define void @test() { call i32 @strlen( i8* null ) ; :1 [#uses=0] diff --git a/llvm/test/Transforms/ADCE/willreturn.ll b/llvm/test/Transforms/ADCE/willreturn.ll index c3482a4..61bbbe0 100644 --- a/llvm/test/Transforms/ADCE/willreturn.ll +++ b/llvm/test/Transforms/ADCE/willreturn.ll @@ -4,9 +4,10 @@ declare void @may_not_return(i32) nounwind readnone declare void @will_return(i32) nounwind readnone willreturn -; FIXME: This is a miscompile. define void @test(i32 %a) { ; CHECK-LABEL: @test( +; CHECK-NEXT: [[B:%.*]] = add i32 [[A:%.*]], 1 +; CHECK-NEXT: call void @may_not_return(i32 [[B]]) ; CHECK-NEXT: ret void ; %b = add i32 %a, 1 diff --git a/llvm/test/Transforms/BDCE/dce-pure.ll b/llvm/test/Transforms/BDCE/dce-pure.ll index a487a04..e00121d 100644 --- a/llvm/test/Transforms/BDCE/dce-pure.ll +++ b/llvm/test/Transforms/BDCE/dce-pure.ll @@ -1,7 +1,7 @@ ; RUN: opt -bdce -S < %s | FileCheck %s ; RUN: opt -passes=bdce -S < %s | FileCheck %s -declare i32 @strlen(i8*) readonly nounwind +declare i32 @strlen(i8*) readonly nounwind willreturn define void @test1() { call i32 @strlen( i8* null ) diff --git a/llvm/test/Transforms/BDCE/dead-void-ro.ll b/llvm/test/Transforms/BDCE/dead-void-ro.ll index 36f0951..77f4e09 100644 --- a/llvm/test/Transforms/BDCE/dead-void-ro.ll +++ b/llvm/test/Transforms/BDCE/dead-void-ro.ll @@ -14,5 +14,5 @@ define void @PR34211(i16* %p) { declare void @no_side_effects_so_dead(i16) #0 -attributes #0 = { nounwind readnone } +attributes #0 = { nounwind readnone willreturn } diff --git a/llvm/test/Transforms/BDCE/willreturn.ll b/llvm/test/Transforms/BDCE/willreturn.ll index b87ab00..5efd6ad 100644 --- a/llvm/test/Transforms/BDCE/willreturn.ll +++ b/llvm/test/Transforms/BDCE/willreturn.ll @@ -4,9 +4,10 @@ declare void @may_not_return(i32) nounwind readnone declare void @will_return(i32) nounwind readnone willreturn -; FIXME: This is a miscompile. define void @test(i32 %a) { ; CHECK-LABEL: @test( +; CHECK-NEXT: [[B:%.*]] = add i32 [[A:%.*]], 1 +; CHECK-NEXT: call void @may_not_return(i32 [[B]]) ; CHECK-NEXT: ret void ; %b = add i32 %a, 1 diff --git a/llvm/test/tools/gold/X86/parallel.ll b/llvm/test/tools/gold/X86/parallel.ll index 6972efc..b8072f0 100644 --- a/llvm/test/tools/gold/X86/parallel.ll +++ b/llvm/test/tools/gold/X86/parallel.ll @@ -14,7 +14,7 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK0-NOT: bar ; CHECK0: T foo ; CHECK0-NOT: bar -define void @foo() { +define void @foo() mustprogress { call void @bar() ret void } @@ -24,7 +24,7 @@ define void @foo() { ; CHECK1-NOT: foo ; CHECK1: T bar ; CHECK1-NOT: foo -define void @bar() { +define void @bar() mustprogress { call void @foo() ret void }