summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/FunctionAttrs
diff options
context:
space:
mode:
authorPhilip Reames <listmail@philipreames.com>2015-08-31 19:44:38 +0000
committerPhilip Reames <listmail@philipreames.com>2015-08-31 19:44:38 +0000
commita88caeab6c20db6325b5fa4d80cc79830e7a278f (patch)
treea769fe0b89103b330b2b9357c49b442c9b222b37 /llvm/test/Transforms/FunctionAttrs
parent35eebe13fc81dc7e6e9b543b0e4e46eb9ab57595 (diff)
downloadbcm5719-llvm-a88caeab6c20db6325b5fa4d80cc79830e7a278f.tar.gz
bcm5719-llvm-a88caeab6c20db6325b5fa4d80cc79830e7a278f.zip
[FunctionAttr] Infer nonnull attributes on returns
Teach FunctionAttr to infer the nonnull attribute on return values of functions which never return a potentially null value. This is done both via a conservative local analysis for the function itself and a optimistic per-SCC analysis. If no function in the SCC returns anything which could be null (other than values from other functions in the SCC), we can conclude no function returned a null pointer. Even if some function within the SCC returns a null pointer, we may be able to locally conclude that some don't. Differential Revision: http://reviews.llvm.org/D9688 llvm-svn: 246476
Diffstat (limited to 'llvm/test/Transforms/FunctionAttrs')
-rw-r--r--llvm/test/Transforms/FunctionAttrs/nonnull.ll74
1 files changed, 74 insertions, 0 deletions
diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
new file mode 100644
index 00000000000..1fb64b7434a
--- /dev/null
+++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
@@ -0,0 +1,74 @@
+; RUN: opt -S -functionattrs %s | FileCheck %s
+declare nonnull i8* @ret_nonnull()
+
+; Return a pointer trivially nonnull (call return attribute)
+define i8* @test1() {
+; CHECK: define nonnull i8* @test1
+ %ret = call i8* @ret_nonnull()
+ ret i8* %ret
+}
+
+; Return a pointer trivially nonnull (argument attribute)
+define i8* @test2(i8* nonnull %p) {
+; CHECK: define nonnull i8* @test2
+ ret i8* %p
+}
+
+; Given an SCC where one of the functions can not be marked nonnull,
+; can we still mark the other one which is trivially nonnull
+define i8* @scc_binder() {
+; CHECK: define i8* @scc_binder
+ call i8* @test3()
+ ret i8* null
+}
+
+define i8* @test3() {
+; CHECK: define nonnull i8* @test3
+ call i8* @scc_binder()
+ %ret = call i8* @ret_nonnull()
+ ret i8* %ret
+}
+
+; Given a mutual recursive set of functions, we can mark them
+; nonnull if neither can ever return null. (In this case, they
+; just never return period.)
+define i8* @test4_helper() {
+; CHECK: define noalias nonnull i8* @test4_helper
+ %ret = call i8* @test4()
+ ret i8* %ret
+}
+
+define i8* @test4() {
+; CHECK: define noalias nonnull i8* @test4
+ %ret = call i8* @test4_helper()
+ ret i8* %ret
+}
+
+; Given a mutual recursive set of functions which *can* return null
+; make sure we haven't marked them as nonnull.
+define i8* @test5_helper() {
+; CHECK: define noalias i8* @test5_helper
+ %ret = call i8* @test5()
+ ret i8* null
+}
+
+define i8* @test5() {
+; CHECK: define noalias i8* @test5
+ %ret = call i8* @test5_helper()
+ ret i8* %ret
+}
+
+; Local analysis, but going through a self recursive phi
+define i8* @test6() {
+entry:
+; CHECK: define nonnull i8* @test6
+ %ret = call i8* @ret_nonnull()
+ br label %loop
+loop:
+ %phi = phi i8* [%ret, %entry], [%phi, %loop]
+ br i1 undef, label %loop, label %exit
+exit:
+ ret i8* %phi
+}
+
+
OpenPOWER on IntegriCloud