[PM][FunctionAttrs] add NoUnwind attribute inference to PostOrderFunctionAttrs pass
Summary:
This was motivated by absence of PrunEH functionality in new PM.
It was decided that a proper way to do PruneEH is to add NoUnwind inference
into PostOrderFunctionAttrs and then perform normal SimplifyCFG on top.
This change generalizes attribute handling implemented for (a removal of)
Convergent attribute, by introducing a generic builder-like class
AttributeInferer
It registers all the attribute inference requests, storing per-attribute
predicates into a vector, and then goes through an SCC Node, scanning all
the instructions for not breaking attribute assumptions.
The main idea is that as soon all the instructions from all the functions
of SCC Node conform to attribute assumptions then we are free to infer
the attribute as set for all the functions of SCC Node.
It handles two distinct cases of attributes:
- those that might break due to derefinement of the function code
for these attributes we are allowed to apply inference only if all the
functions are "exact definitions". Example - NoUnwind.
- those that do not care about derefinement
for these attributes we are allowed to apply inference as soon as we see
any function definition. Example - removal of Convergent attribute.
Also in this commit:
* Converted all the FunctionAttrs tests to use FileCheck and added new-PM
invocations to them
* FunctionAttrs/convergent.ll test demonstrates a difference in behavior between
new and old PM implementations. Marked with FIXME.
* PruneEH tests were converted to new-PM as well, using function-attrs+simplify-cfg
combo as intended
* some of "other" tests were updated since function-attrs now infers 'nounwind'
even for old PM pipeline
* -disable-nounwind-inference hidden option added as a possible workaround for a supposedly
rare case when nounwind being inferred by default presents a problem
Reviewers: chandlerc, jlebar
Reviewed By: jlebar
Subscribers: eraman, llvm-commits
Differential Revision: https://reviews.llvm.org/D44415
llvm-svn: 328377
diff --git a/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll b/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
index b0aecfa..6bbd999 100644
--- a/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
+++ b/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
@@ -1,10 +1,17 @@
-; RUN: opt < %s -functionattrs -S | grep readnone
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @a
define i32 @a() {
%tmp = call i32 @b( ) ; <i32> [#uses=1]
ret i32 %tmp
}
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @b
define i32 @b() {
%tmp = call i32 @a( ) ; <i32> [#uses=1]
ret i32 %tmp
diff --git a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
index b62698a..d747fe7 100644
--- a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
+++ b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
@@ -1,25 +1,32 @@
; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
+
@x = global i32 0
-; CHECK: declare i32 @e() #0
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: declare i32 @e
declare i32 @e() readnone
-; CHECK: define i32 @f() #0
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @f
define i32 @f() {
%tmp = call i32 @e( ) ; <i32> [#uses=1]
ret i32 %tmp
}
-; CHECK: define i32 @g() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @g
define i32 @g() readonly {
ret i32 0
}
-; CHECK: define i32 @h() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @h
define i32 @h() readnone {
%tmp = load i32, i32* @x ; <i32> [#uses=1]
ret i32 %tmp
}
-
-; CHECK: attributes #0 = { readnone }
-; CHECK: attributes #1 = { norecurse readnone }
diff --git a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
index d8256ae..35cb534 100644
--- a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
+++ b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
; CHECK: define i32 @f() #0
define i32 @f() {
diff --git a/llvm/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll b/llvm/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
index fef872c..8212e89 100644
--- a/llvm/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
+++ b/llvm/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
@@ -1,4 +1,5 @@
-; RUN: opt < %s -functionattrs -S | not grep read
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
; PR2792
@g = global i32 0 ; <i32*> [#uses=1]
@@ -7,3 +8,5 @@
%t = load volatile i32, i32* @g ; <i32> [#uses=1]
ret i32 %t
}
+
+; CHECK-NOT: attributes #{{.*}} read
diff --git a/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll b/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
index e3a8f01..ee1a8ca 100644
--- a/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
+++ b/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
@@ -1,8 +1,12 @@
-; RUN: opt < %s -basicaa -functionattrs -S | grep readnone
+; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
@s = external constant i8 ; <i8*> [#uses=1]
+; CHECK: define i8 @f() #0
define i8 @f() {
%tmp = load i8, i8* @s ; <i8> [#uses=1]
ret i8 %tmp
}
+
+; CHECK: attributes #0 = { {{.*}} readnone
diff --git a/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll b/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
index 0d0231b..ce72c41 100644
--- a/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
+++ b/llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
; CHECK: define i32* @a(i32** nocapture readonly %p)
define i32* @a(i32** %p) {
diff --git a/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll b/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
index 23bb18e9..b9536dc 100644
--- a/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
+++ b/llvm/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
@@ -1,12 +1,14 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
; PR8279
@g = constant i32 1
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse
+; CHECK-NOT: readonly
+; CHECK-NEXT: void @foo()
define void @foo() {
-; CHECK: void @foo() #0 {
%tmp = load volatile i32, i32* @g
ret void
}
-
-; CHECK: attributes #0 = { norecurse }
diff --git a/llvm/test/Transforms/FunctionAttrs/assume.ll b/llvm/test/Transforms/FunctionAttrs/assume.ll
index 5820062..d629662 100644
--- a/llvm/test/Transforms/FunctionAttrs/assume.ll
+++ b/llvm/test/Transforms/FunctionAttrs/assume.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -o - -functionattrs %s | FileCheck %s
+; RUN: opt -S -o - -passes=function-attrs %s | FileCheck %s
; CHECK-NOT: readnone
declare void @llvm.assume(i1)
diff --git a/llvm/test/Transforms/FunctionAttrs/atomic.ll b/llvm/test/Transforms/FunctionAttrs/atomic.ll
index dd915a6..af87a28 100644
--- a/llvm/test/Transforms/FunctionAttrs/atomic.ll
+++ b/llvm/test/Transforms/FunctionAttrs/atomic.ll
@@ -1,4 +1,5 @@
; RUN: opt -basicaa -functionattrs -S < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes=function-attrs -S < %s | FileCheck %s
; Atomic load/store to local doesn't affect whether a function is
; readnone/readonly.
@@ -19,5 +20,5 @@
ret i32 %r
}
-; CHECK: attributes #0 = { norecurse readnone ssp uwtable }
-; CHECK: attributes #1 = { norecurse ssp uwtable }
+; CHECK: attributes #0 = { norecurse nounwind readnone ssp uwtable }
+; CHECK: attributes #1 = { norecurse nounwind ssp uwtable }
diff --git a/llvm/test/Transforms/FunctionAttrs/comdat-ipo.ll b/llvm/test/Transforms/FunctionAttrs/comdat-ipo.ll
index e82d2fb..2a149e4 100644
--- a/llvm/test/Transforms/FunctionAttrs/comdat-ipo.ll
+++ b/llvm/test/Transforms/FunctionAttrs/comdat-ipo.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
; See PR26774
diff --git a/llvm/test/Transforms/FunctionAttrs/convergent.ll b/llvm/test/Transforms/FunctionAttrs/convergent.ll
index 37886b8..0e4b751 100644
--- a/llvm/test/Transforms/FunctionAttrs/convergent.ll
+++ b/llvm/test/Transforms/FunctionAttrs/convergent.ll
@@ -1,4 +1,8 @@
-; RUN: opt -functionattrs -S < %s | FileCheck %s
+; FIXME: convert CHECK-INDIRECT into CHECK (and remove -check-prefixes) as soon
+; FIXME: as new-pass-manager's handling of indirect_non_convergent_call is fixed
+;
+; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-INDIRECT
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
; CHECK: Function Attrs
; CHECK-NOT: convergent
@@ -50,8 +54,8 @@
; "Function Attrs" comment in the output.
;
; CHECK: Function Attrs
-; CHECK-NOT: convergent
-; CHECK-NEXT: define i32 @indirect_non_convergent_call(
+; CHECK-INDIRECT-NOT: convergent
+; CHECK-INDIRECT-NEXT: define i32 @indirect_non_convergent_call(
define i32 @indirect_non_convergent_call(i32 ()* %f) convergent norecurse {
%a = call i32 %f()
ret i32 %a
diff --git a/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll b/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll
index 13091e3..24a1459 100644
--- a/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll
+++ b/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll
@@ -1,17 +1,25 @@
; RUN: opt -S < %s -functionattrs | FileCheck %s
+; RUN: opt -S < %s -passes=function-attrs | FileCheck %s
+; CHECK: Function Attrs
+; CHECK-SAME: inaccessiblememonly
+; CHECK-NEXT: declare void @llvm.sideeffect()
declare void @llvm.sideeffect()
; Don't add readnone or similar attributes when an @llvm.sideeffect() intrinsic
; is present.
-; CHECK: define void @test() {
+; CHECK: Function Attrs
+; CHECK-NOT: readnone
+; CHECK: define void @test()
define void @test() {
call void @llvm.sideeffect()
ret void
}
-; CHECK: define void @loop() {
+; CHECK: Function Attrs
+; CHECK-NOT: readnone
+; CHECK: define void @loop()
define void @loop() {
br label %loop
diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
index e137a38..931072e 100644
--- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -1,4 +1,6 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
@g = global i32* null ; <i32**> [#uses=1]
; CHECK: define i32* @c1(i32* readnone returned %q)
diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull-global.ll b/llvm/test/Transforms/FunctionAttrs/nonnull-global.ll
index 43353e8..d79a7ae 100644
--- a/llvm/test/Transforms/FunctionAttrs/nonnull-global.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nonnull-global.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -functionattrs %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs %s | FileCheck %s
@a = external global i8, !absolute_symbol !0
diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
index 191e678..7de65d8 100644
--- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
@@ -1,4 +1,6 @@
; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s
+
declare nonnull i8* @ret_nonnull()
; Return a pointer trivially nonnull (call return attribute)
diff --git a/llvm/test/Transforms/FunctionAttrs/norecurse.ll b/llvm/test/Transforms/FunctionAttrs/norecurse.ll
index cd9044d..0293938 100644
--- a/llvm/test/Transforms/FunctionAttrs/norecurse.ll
+++ b/llvm/test/Transforms/FunctionAttrs/norecurse.ll
@@ -1,53 +1,82 @@
; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-functionattrs' -S | FileCheck %s
-; CHECK: define i32 @leaf() #0
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse nounwind readnone
+; CHECK-NEXT: define i32 @leaf()
define i32 @leaf() {
ret i32 1
}
-; CHECK: define i32 @self_rec() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @self_rec()
define i32 @self_rec() {
%a = call i32 @self_rec()
ret i32 4
}
-; CHECK: define i32 @indirect_rec() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec()
define i32 @indirect_rec() {
%a = call i32 @indirect_rec2()
ret i32 %a
}
-; CHECK: define i32 @indirect_rec2() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec2()
define i32 @indirect_rec2() {
%a = call i32 @indirect_rec()
ret i32 %a
}
-; CHECK: define i32 @extern() #1
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @extern()
define i32 @extern() {
%a = call i32 @k()
ret i32 %a
}
+
+; CHECK: Function Attrs
+; CHECK-NEXT: declare i32 @k()
declare i32 @k() readnone
-; CHECK: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len) {
+; CHECK: Function Attrs
+; CHECK-SAME: nounwind
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len)
define void @intrinsic(i8* %dest, i8* %src, i32 %len) {
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false)
ret void
}
+
+; CHECK: Function Attrs
+; CHECK-NEXT: declare void @llvm.memcpy.p0i8.p0i8.i32
declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
-; CHECK: define internal i32 @called_by_norecurse() #0
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse readnone
+; CHECK-NEXT: define internal i32 @called_by_norecurse()
define internal i32 @called_by_norecurse() {
%a = call i32 @k()
ret i32 %a
}
+; CHECK: Function Attrs
+; CHECK-NEXT: define void @m()
define void @m() norecurse {
%a = call i32 @called_by_norecurse()
ret void
}
-; CHECK: define internal i32 @called_by_norecurse_indirectly() #0
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse readnone
+; CHECK-NEXT: define internal i32 @called_by_norecurse_indirectly()
define internal i32 @called_by_norecurse_indirectly() {
%a = call i32 @k()
ret i32 %a
@@ -60,6 +89,3 @@
call void @o()
ret void
}
-
-; CHECK: attributes #0 = { norecurse readnone }
-; CHECK: attributes #1 = { readnone }
diff --git a/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll b/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
index 2502ea7..69808a8 100644
--- a/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
+++ b/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
@@ -1,13 +1,17 @@
; RUN: opt -S -functionattrs < %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs < %s | FileCheck %s
define void @f() {
-; CHECK-LABEL: define void @f() {
+; CHECK-LABEL: define void @f() #0 {
call void @g() [ "unknown"() ]
ret void
}
define void @g() {
-; CHECK-LABEL: define void @g() {
+; CHECK-LABEL: define void @g() #0 {
call void @f()
ret void
}
+
+
+; CHECK: attributes #0 = { nounwind }
diff --git a/llvm/test/Transforms/FunctionAttrs/optnone.ll b/llvm/test/Transforms/FunctionAttrs/optnone.ll
index cd08c75..586a6d4 100644
--- a/llvm/test/Transforms/FunctionAttrs/optnone.ll
+++ b/llvm/test/Transforms/FunctionAttrs/optnone.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
@x = global i32 0
@@ -19,6 +20,6 @@
; CHECK: (i8*) #1
; CHECK-LABEL: attributes #0
-; CHECK: = { norecurse readnone }
+; CHECK: = { norecurse nounwind readnone }
; CHECK-LABEL: attributes #1
; CHECK: = { noinline optnone }
diff --git a/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll b/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
index db9a895..f2294fe 100644
--- a/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
+++ b/llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
@@ -1,4 +1,5 @@
; RUN: opt -functionattrs -S < %s | FileCheck %s
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
; This checks for an iterator wraparound bug in FunctionAttrs. The previous
; "incorrect" behavior was inferring readonly for the %x argument in @caller.
diff --git a/llvm/test/Transforms/FunctionAttrs/readnone.ll b/llvm/test/Transforms/FunctionAttrs/readnone.ll
index eddcdd2..b5a5b30 100644
--- a/llvm/test/Transforms/FunctionAttrs/readnone.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readnone.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
; CHECK: define void @bar(i8* nocapture readnone)
define void @bar(i8* readonly) {
diff --git a/llvm/test/Transforms/FunctionAttrs/returned.ll b/llvm/test/Transforms/FunctionAttrs/returned.ll
index ede9481..04ddb7b 100644
--- a/llvm/test/Transforms/FunctionAttrs/returned.ll
+++ b/llvm/test/Transforms/FunctionAttrs/returned.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
; CHECK: define i32 @test1(i32 %p, i32 %q)
define i32 @test1(i32 %p, i32 %q) {
diff --git a/llvm/test/Transforms/Inline/cgscc-update.ll b/llvm/test/Transforms/Inline/cgscc-update.ll
index 77666c3..b251a5d 100644
--- a/llvm/test/Transforms/Inline/cgscc-update.ll
+++ b/llvm/test/Transforms/Inline/cgscc-update.ll
@@ -10,9 +10,9 @@
declare void @unknown()
; Sanity check: this should get annotated as readnone.
-; CHECK: Function Attrs: readnone
+; CHECK: Function Attrs: nounwind readnone
; CHECK-NEXT: declare void @readnone()
-declare void @readnone() readnone
+declare void @readnone() readnone nounwind
; The 'test1_' prefixed functions are designed to trigger forming a new direct
; call in the inlined body of the function. After that, we form a new SCC and
@@ -27,7 +27,7 @@
}
; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
; CHECK-NEXT: define void @test1_g()
define void @test1_g() noinline {
entry:
@@ -36,7 +36,7 @@
}
; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
; CHECK-NEXT: define void @test1_h()
define void @test1_h() noinline {
entry:
@@ -59,7 +59,7 @@
}
; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
; CHECK-NEXT: define void @test2_g()
define void @test2_g() noinline {
entry:
@@ -69,7 +69,7 @@
}
; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
; CHECK-NEXT: define void @test2_h()
define void @test2_h() noinline {
entry:
@@ -152,7 +152,7 @@
; form a new SCC and should use that can deduce precise function attrs.
; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
; CHECK-NEXT: define void @test4_f1()
define void @test4_f1() noinline {
entry:
@@ -175,7 +175,7 @@
}
; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline readnone
+; CHECK: Function Attrs: noinline nounwind readnone
; CHECK-NEXT: define void @test4_h()
define void @test4_h() noinline {
entry:
diff --git a/llvm/test/Transforms/PruneEH/2008-06-02-Weak.ll b/llvm/test/Transforms/PruneEH/2008-06-02-Weak.ll
index fb97ae8..6743606 100644
--- a/llvm/test/Transforms/PruneEH/2008-06-02-Weak.ll
+++ b/llvm/test/Transforms/PruneEH/2008-06-02-Weak.ll
@@ -1,12 +1,20 @@
-; RUN: opt < %s -prune-eh -S | not grep nounwind
+; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
+; We should not infer 'nounwind' for/from a weak function,
+; since it can be overriden by throwing implementation.
+;
+; CHECK-LABEL: define weak void @f()
define weak void @f() {
entry:
ret void
}
+; CHECK-LABEL: define void @g()
define void @g() {
entry:
call void @f()
ret void
}
+
+; CHECK-NOT: {{^}}attributes #{{[0-9].*}} nounwind
diff --git a/llvm/test/Transforms/PruneEH/ipo-nounwind.ll b/llvm/test/Transforms/PruneEH/ipo-nounwind.ll
index ba3fab1..251bc08 100644
--- a/llvm/test/Transforms/PruneEH/ipo-nounwind.ll
+++ b/llvm/test/Transforms/PruneEH/ipo-nounwind.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -prune-eh < %s | FileCheck %s
+; RUN: opt -S -passes='function-attrs,function(simplify-cfg)' < %s | FileCheck %s
declare void @may_throw()
diff --git a/llvm/test/Transforms/PruneEH/operand-bundles.ll b/llvm/test/Transforms/PruneEH/operand-bundles.ll
index efe8f62..112f471 100644
--- a/llvm/test/Transforms/PruneEH/operand-bundles.ll
+++ b/llvm/test/Transforms/PruneEH/operand-bundles.ll
@@ -1,4 +1,5 @@
; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
declare void @nounwind() nounwind
diff --git a/llvm/test/Transforms/PruneEH/pr23971.ll b/llvm/test/Transforms/PruneEH/pr23971.ll
index 8a8a591..e23e8cb 100644
--- a/llvm/test/Transforms/PruneEH/pr23971.ll
+++ b/llvm/test/Transforms/PruneEH/pr23971.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -prune-eh < %s | FileCheck %s
+; RUN: opt -S -passes='function-attrs,function(simplify-cfg)' < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/Transforms/PruneEH/pr26263.ll b/llvm/test/Transforms/PruneEH/pr26263.ll
index 17fafeb..d1232ab 100644
--- a/llvm/test/Transforms/PruneEH/pr26263.ll
+++ b/llvm/test/Transforms/PruneEH/pr26263.ll
@@ -1,4 +1,10 @@
-; RUN: opt -prune-eh -S < %s | FileCheck %s
+; PruneEH is less powerful than simplify-cfg in terms of cfg simplification,
+; so it leaves some of the unreachable stuff hanging around.
+; Checking it with CHECK-OLD.
+;
+; RUN: opt -prune-eh -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OLD
+; RUN: opt -passes='function-attrs,function(simplify-cfg)' -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NEW
+
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i386-pc-windows-msvc"
@@ -20,12 +26,15 @@
}
; CHECK-LABEL: define void @test1(
-; CHECK: call void @neverthrows()
+; CHECK: call void @neverthrows()
+; CHECK-NEW-NEXT: ret void
+; CHECK-NEW-NEXT: }
+; CHECK-OLD: ret void
-; CHECK: %[[cp:.*]] = cleanuppad within none []
-; CHECK-NEXT: unreachable
+; CHECK-OLD: %[[cp:.*]] = cleanuppad within none []
+; CHECK-OLD-NEXT: unreachable
-; CHECK: cleanupret from %[[cp]] unwind to caller
+; CHECK-OLD: cleanupret from %[[cp]] unwind to caller
define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
invoke void @neverthrows()
@@ -46,11 +55,16 @@
}
; CHECK-LABEL: define void @test2(
-; CHECK: call void @neverthrows()
+; CHECK: call void @neverthrows()
+; CHECK-NEW-NEXT: ret void
+; CHECK-NEW-NEXT: }
+; CHECK-OLD: ret void
-; CHECK: %[[cs:.*]] = catchswitch within none [label
+; CHECK-OLD: %[[cs:.*]] = catchswitch within none [label
-; CHECK: catchpad within %[[cs]] []
-; CHECK-NEXT: unreachable
+; CHECK-OLD: catchpad within %[[cs]] []
+; CHECK-OLD-NEXT: unreachable
+
+; CHECK-OLD:ret void
declare i32 @__CxxFrameHandler3(...)
diff --git a/llvm/test/Transforms/PruneEH/recursivetest.ll b/llvm/test/Transforms/PruneEH/recursivetest.ll
index 0b2399a..755f251 100644
--- a/llvm/test/Transforms/PruneEH/recursivetest.ll
+++ b/llvm/test/Transforms/PruneEH/recursivetest.ll
@@ -1,6 +1,9 @@
-; RUN: opt < %s -prune-eh -S | not grep invoke
+; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
+; CHECK-LABEL: define internal i32 @foo()
define internal i32 @foo() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-NOT: invoke i32 @foo()
invoke i32 @foo( )
to label %Normal unwind label %Except ; <i32>:1 [#uses=0]
Normal: ; preds = %0
@@ -11,7 +14,9 @@
ret i32 123
}
+; CHECK-LABEL: define i32 @caller()
define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-NOT: invoke i32 @foo()
invoke i32 @foo( )
to label %Normal unwind label %Except ; <i32>:1 [#uses=0]
Normal: ; preds = %0
diff --git a/llvm/test/Transforms/PruneEH/seh-nounwind.ll b/llvm/test/Transforms/PruneEH/seh-nounwind.ll
index 043a792..7bc8f80 100644
--- a/llvm/test/Transforms/PruneEH/seh-nounwind.ll
+++ b/llvm/test/Transforms/PruneEH/seh-nounwind.ll
@@ -1,4 +1,5 @@
; RUN: opt -S -prune-eh < %s | FileCheck %s
+; RUN: opt -S -passes='function-attrs,function(simplify-cfg)' < %s | FileCheck %s
; Don't remove invokes of nounwind functions if the personality handles async
; exceptions. The @div function in this test can fault, even though it can't
diff --git a/llvm/test/Transforms/PruneEH/simpletest.ll b/llvm/test/Transforms/PruneEH/simpletest.ll
index cbc5592..720a85a 100644
--- a/llvm/test/Transforms/PruneEH/simpletest.ll
+++ b/llvm/test/Transforms/PruneEH/simpletest.ll
@@ -1,4 +1,5 @@
-; RUN: opt < %s -prune-eh -S | not grep invoke
+; RUN: opt < %s -prune-eh -S | FileCheck %s
+; RUN: opt < %s -passes='function-attrs,function(simplify-cfg)' -S | FileCheck %s
declare void @nounwind() nounwind
@@ -7,7 +8,9 @@
ret void
}
+; CHECK-LABEL: define i32 @caller()
define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-NOT: invoke void @foo
invoke void @foo( )
to label %Normal unwind label %Except