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:
parent
c1001d823d
commit
93b123f786
@ -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(
|
||||||
|
@ -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))
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
@ -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 )
|
||||||
|
@ -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 }
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user