diff options
author | Philip Reames <listmail@philipreames.com> | 2015-08-31 19:44:38 +0000 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2015-08-31 19:44:38 +0000 |
commit | a88caeab6c20db6325b5fa4d80cc79830e7a278f (patch) | |
tree | a769fe0b89103b330b2b9357c49b442c9b222b37 /llvm/test/Transforms/FunctionAttrs | |
parent | 35eebe13fc81dc7e6e9b543b0e4e46eb9ab57595 (diff) | |
download | bcm5719-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.ll | 74 |
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 +} + + |