1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[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
This commit is contained in:
Nikita Popov 2021-02-18 22:29:19 +01:00
parent c1001d823d
commit 93b123f786
10 changed files with 15 additions and 13 deletions

View File

@ -80,7 +80,7 @@ void DemandedBitsWrapperPass::print(raw_ostream &OS, const Module *M) const {
static bool isAlwaysLive(Instruction *I) { static bool isAlwaysLive(Instruction *I) {
return I->isTerminator() || isa<DbgInfoIntrinsic>(I) || I->isEHPad() || return I->isTerminator() || isa<DbgInfoIntrinsic>(I) || I->isEHPad() ||
I->mayHaveSideEffects(); I->mayHaveSideEffects() || !I->willReturn();
} }
void DemandedBits::determineLiveOperandBits( void DemandedBits::determineLiveOperandBits(

View File

@ -325,7 +325,7 @@ void AggressiveDeadCodeElimination::initialize() {
bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &I) { bool AggressiveDeadCodeElimination::isAlwaysLive(Instruction &I) {
// TODO -- use llvm::isInstructionTriviallyDead // 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 // Skip any value profile instrumentation calls if they are
// instrumenting constants. // instrumenting constants.
if (isInstrumentsConstant(I)) if (isInstrumentsConstant(I))

View File

@ -5,8 +5,8 @@
; bundles since the presence of unknown operand bundles implies ; bundles since the presence of unknown operand bundles implies
; arbitrary memory effects. ; arbitrary memory effects.
declare void @readonly_function() readonly nounwind declare void @readonly_function() readonly nounwind willreturn
declare void @readnone_function() readnone nounwind declare void @readnone_function() readnone nounwind willreturn
define void @test0() { define void @test0() {
; CHECK-LABEL: @test0( ; CHECK-LABEL: @test0(

View File

@ -11,7 +11,7 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK0-NOT: bar ; CHECK0-NOT: bar
; CHECK0: T foo ; CHECK0: T foo
; CHECK0-NOT: bar ; CHECK0-NOT: bar
define void @foo() { define void @foo() mustprogress {
call void @bar() call void @bar()
ret void ret void
} }
@ -19,7 +19,7 @@ define void @foo() {
; CHECK1-NOT: foo ; CHECK1-NOT: foo
; CHECK1: T bar ; CHECK1: T bar
; CHECK1-NOT: foo ; CHECK1-NOT: foo
define void @bar() { define void @bar() mustprogress {
call void @foo() call void @foo()
ret void ret void
} }

View File

@ -1,6 +1,6 @@
; RUN: opt -adce -S < %s | not grep call ; RUN: opt -adce -S < %s | not grep call
declare i32 @strlen(i8*) readonly nounwind declare i32 @strlen(i8*) readonly nounwind willreturn
define void @test() { define void @test() {
call i32 @strlen( i8* null ) ; <i32>:1 [#uses=0] call i32 @strlen( i8* null ) ; <i32>:1 [#uses=0]

View File

@ -4,9 +4,10 @@
declare void @may_not_return(i32) nounwind readnone declare void @may_not_return(i32) nounwind readnone
declare void @will_return(i32) nounwind readnone willreturn declare void @will_return(i32) nounwind readnone willreturn
; FIXME: This is a miscompile.
define void @test(i32 %a) { define void @test(i32 %a) {
; CHECK-LABEL: @test( ; CHECK-LABEL: @test(
; CHECK-NEXT: [[B:%.*]] = add i32 [[A:%.*]], 1
; CHECK-NEXT: call void @may_not_return(i32 [[B]])
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%b = add i32 %a, 1 %b = add i32 %a, 1

View File

@ -1,7 +1,7 @@
; RUN: opt -bdce -S < %s | FileCheck %s ; RUN: opt -bdce -S < %s | FileCheck %s
; RUN: opt -passes=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() { define void @test1() {
call i32 @strlen( i8* null ) call i32 @strlen( i8* null )

View File

@ -14,5 +14,5 @@ define void @PR34211(i16* %p) {
declare void @no_side_effects_so_dead(i16) #0 declare void @no_side_effects_so_dead(i16) #0
attributes #0 = { nounwind readnone } attributes #0 = { nounwind readnone willreturn }

View File

@ -4,9 +4,10 @@
declare void @may_not_return(i32) nounwind readnone declare void @may_not_return(i32) nounwind readnone
declare void @will_return(i32) nounwind readnone willreturn declare void @will_return(i32) nounwind readnone willreturn
; FIXME: This is a miscompile.
define void @test(i32 %a) { define void @test(i32 %a) {
; CHECK-LABEL: @test( ; CHECK-LABEL: @test(
; CHECK-NEXT: [[B:%.*]] = add i32 [[A:%.*]], 1
; CHECK-NEXT: call void @may_not_return(i32 [[B]])
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; ;
%b = add i32 %a, 1 %b = add i32 %a, 1

View File

@ -14,7 +14,7 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK0-NOT: bar ; CHECK0-NOT: bar
; CHECK0: T foo ; CHECK0: T foo
; CHECK0-NOT: bar ; CHECK0-NOT: bar
define void @foo() { define void @foo() mustprogress {
call void @bar() call void @bar()
ret void ret void
} }
@ -24,7 +24,7 @@ define void @foo() {
; CHECK1-NOT: foo ; CHECK1-NOT: foo
; CHECK1: T bar ; CHECK1: T bar
; CHECK1-NOT: foo ; CHECK1-NOT: foo
define void @bar() { define void @bar() mustprogress {
call void @foo() call void @foo()
ret void ret void
} }