Skip to content

Commit a88caea

Browse files
committedAug 31, 2015
[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
1 parent 35eebe1 commit a88caea

File tree

2 files changed

+222
-0
lines changed

2 files changed

+222
-0
lines changed
 

‎llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727
#include "llvm/Analysis/CallGraph.h"
2828
#include "llvm/Analysis/CallGraphSCCPass.h"
2929
#include "llvm/Analysis/CaptureTracking.h"
30+
#include "llvm/Analysis/ValueTracking.h"
3031
#include "llvm/IR/GlobalVariable.h"
3132
#include "llvm/IR/InstIterator.h"
3233
#include "llvm/IR/IntrinsicInst.h"
3334
#include "llvm/IR/LLVMContext.h"
35+
#include "llvm/Support/Debug.h"
3436
#include "llvm/Analysis/TargetLibraryInfo.h"
3537
using namespace llvm;
3638

@@ -42,6 +44,7 @@ STATISTIC(NumNoCapture, "Number of arguments marked nocapture");
4244
STATISTIC(NumReadNoneArg, "Number of arguments marked readnone");
4345
STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly");
4446
STATISTIC(NumNoAlias, "Number of function returns marked noalias");
47+
STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
4548
STATISTIC(NumAnnotated, "Number of attributes added to library functions");
4649

4750
namespace {
@@ -67,6 +70,13 @@ namespace {
6770
// AddNoAliasAttrs - Deduce noalias attributes for the SCC.
6871
bool AddNoAliasAttrs(const CallGraphSCC &SCC);
6972

73+
/// \brief Does this function return null?
74+
bool ReturnsNonNull(Function *F, SmallPtrSet<Function*, 8> &,
75+
bool &Speculative) const;
76+
77+
/// \brief Deduce nonnull attributes for the SCC.
78+
bool AddNonNullAttrs(const CallGraphSCC &SCC);
79+
7080
// Utility methods used by inferPrototypeAttributes to add attributes
7181
// and maintain annotation statistics.
7282

@@ -832,6 +842,143 @@ bool FunctionAttrs::AddNoAliasAttrs(const CallGraphSCC &SCC) {
832842
return MadeChange;
833843
}
834844

845+
bool FunctionAttrs::ReturnsNonNull(Function *F,
846+
SmallPtrSet<Function*, 8> &SCCNodes,
847+
bool &Speculative) const {
848+
assert(F->getReturnType()->isPointerTy() &&
849+
"nonnull only meaningful on pointer types");
850+
Speculative = false;
851+
852+
SmallSetVector<Value *, 8> FlowsToReturn;
853+
for (BasicBlock &BB : *F)
854+
if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
855+
FlowsToReturn.insert(Ret->getReturnValue());
856+
857+
for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
858+
Value *RetVal = FlowsToReturn[i];
859+
860+
// If this value is locally known to be non-null, we're good
861+
if (isKnownNonNull(RetVal, TLI))
862+
continue;
863+
864+
// Otherwise, we need to look upwards since we can't make any local
865+
// conclusions.
866+
Instruction *RVI = dyn_cast<Instruction>(RetVal);
867+
if (!RVI)
868+
return false;
869+
switch (RVI->getOpcode()) {
870+
// Extend the analysis by looking upwards.
871+
case Instruction::BitCast:
872+
case Instruction::GetElementPtr:
873+
case Instruction::AddrSpaceCast:
874+
FlowsToReturn.insert(RVI->getOperand(0));
875+
continue;
876+
case Instruction::Select: {
877+
SelectInst *SI = cast<SelectInst>(RVI);
878+
FlowsToReturn.insert(SI->getTrueValue());
879+
FlowsToReturn.insert(SI->getFalseValue());
880+
continue;
881+
}
882+
case Instruction::PHI: {
883+
PHINode *PN = cast<PHINode>(RVI);
884+
for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
885+
FlowsToReturn.insert(PN->getIncomingValue(i));
886+
continue;
887+
}
888+
case Instruction::Call:
889+
case Instruction::Invoke: {
890+
CallSite CS(RVI);
891+
Function *Callee = CS.getCalledFunction();
892+
// A call to a node within the SCC is assumed to return null until
893+
// proven otherwise
894+
if (Callee && SCCNodes.count(Callee)) {
895+
Speculative = true;
896+
continue;
897+
}
898+
return false;
899+
}
900+
default:
901+
return false; // Unknown source, may be null
902+
};
903+
llvm_unreachable("should have either continued or returned");
904+
}
905+
906+
return true;
907+
}
908+
909+
bool FunctionAttrs::AddNonNullAttrs(const CallGraphSCC &SCC) {
910+
SmallPtrSet<Function*, 8> SCCNodes;
911+
912+
// Fill SCCNodes with the elements of the SCC. Used for quickly
913+
// looking up whether a given CallGraphNode is in this SCC.
914+
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
915+
SCCNodes.insert((*I)->getFunction());
916+
917+
// Speculative that all functions in the SCC return only nonnull
918+
// pointers. We may refute this as we analyze functions.
919+
bool SCCReturnsNonNull = true;
920+
921+
bool MadeChange = false;
922+
923+
// Check each function in turn, determining which functions return nonnull
924+
// pointers.
925+
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
926+
Function *F = (*I)->getFunction();
927+
928+
if (!F || F->hasFnAttribute(Attribute::OptimizeNone))
929+
// External node or node we don't want to optimize - skip it;
930+
return false;
931+
932+
// Already nonnull.
933+
if (F->getAttributes().hasAttribute(AttributeSet::ReturnIndex,
934+
Attribute::NonNull))
935+
continue;
936+
937+
// Definitions with weak linkage may be overridden at linktime, so
938+
// treat them like declarations.
939+
if (F->isDeclaration() || F->mayBeOverridden())
940+
return false;
941+
942+
// We annotate nonnull return values, which are only applicable to
943+
// pointer types.
944+
if (!F->getReturnType()->isPointerTy())
945+
continue;
946+
947+
bool Speculative = false;
948+
if (ReturnsNonNull(F, SCCNodes, Speculative)) {
949+
if (!Speculative) {
950+
// Mark the function eagerly since we may discover a function
951+
// which prevents us from speculating about the entire SCC
952+
DEBUG(dbgs() << "Eagerly marking " << F->getName() << " as nonnull\n");
953+
F->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull);
954+
++NumNonNullReturn;
955+
MadeChange = true;
956+
}
957+
continue;
958+
}
959+
// At least one function returns something which could be null, can't
960+
// speculate any more.
961+
SCCReturnsNonNull = false;
962+
}
963+
964+
if (SCCReturnsNonNull) {
965+
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
966+
Function *F = (*I)->getFunction();
967+
if (F->getAttributes().hasAttribute(AttributeSet::ReturnIndex,
968+
Attribute::NonNull) ||
969+
!F->getReturnType()->isPointerTy())
970+
continue;
971+
972+
DEBUG(dbgs() << "SCC marking " << F->getName() << " as nonnull\n");
973+
F->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull);
974+
++NumNonNullReturn;
975+
MadeChange = true;
976+
}
977+
}
978+
979+
return MadeChange;
980+
}
981+
835982
/// inferPrototypeAttributes - Analyze the name and prototype of the
836983
/// given function and set any applicable attributes. Returns true
837984
/// if any attributes were set and false otherwise.
@@ -1707,5 +1854,6 @@ bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
17071854
Changed |= AddReadAttrs(SCC);
17081855
Changed |= AddArgumentAttrs(SCC);
17091856
Changed |= AddNoAliasAttrs(SCC);
1857+
Changed |= AddNonNullAttrs(SCC);
17101858
return Changed;
17111859
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
; RUN: opt -S -functionattrs %s | FileCheck %s
2+
declare nonnull i8* @ret_nonnull()
3+
4+
; Return a pointer trivially nonnull (call return attribute)
5+
define i8* @test1() {
6+
; CHECK: define nonnull i8* @test1
7+
%ret = call i8* @ret_nonnull()
8+
ret i8* %ret
9+
}
10+
11+
; Return a pointer trivially nonnull (argument attribute)
12+
define i8* @test2(i8* nonnull %p) {
13+
; CHECK: define nonnull i8* @test2
14+
ret i8* %p
15+
}
16+
17+
; Given an SCC where one of the functions can not be marked nonnull,
18+
; can we still mark the other one which is trivially nonnull
19+
define i8* @scc_binder() {
20+
; CHECK: define i8* @scc_binder
21+
call i8* @test3()
22+
ret i8* null
23+
}
24+
25+
define i8* @test3() {
26+
; CHECK: define nonnull i8* @test3
27+
call i8* @scc_binder()
28+
%ret = call i8* @ret_nonnull()
29+
ret i8* %ret
30+
}
31+
32+
; Given a mutual recursive set of functions, we can mark them
33+
; nonnull if neither can ever return null. (In this case, they
34+
; just never return period.)
35+
define i8* @test4_helper() {
36+
; CHECK: define noalias nonnull i8* @test4_helper
37+
%ret = call i8* @test4()
38+
ret i8* %ret
39+
}
40+
41+
define i8* @test4() {
42+
; CHECK: define noalias nonnull i8* @test4
43+
%ret = call i8* @test4_helper()
44+
ret i8* %ret
45+
}
46+
47+
; Given a mutual recursive set of functions which *can* return null
48+
; make sure we haven't marked them as nonnull.
49+
define i8* @test5_helper() {
50+
; CHECK: define noalias i8* @test5_helper
51+
%ret = call i8* @test5()
52+
ret i8* null
53+
}
54+
55+
define i8* @test5() {
56+
; CHECK: define noalias i8* @test5
57+
%ret = call i8* @test5_helper()
58+
ret i8* %ret
59+
}
60+
61+
; Local analysis, but going through a self recursive phi
62+
define i8* @test6() {
63+
entry:
64+
; CHECK: define nonnull i8* @test6
65+
%ret = call i8* @ret_nonnull()
66+
br label %loop
67+
loop:
68+
%phi = phi i8* [%ret, %entry], [%phi, %loop]
69+
br i1 undef, label %loop, label %exit
70+
exit:
71+
ret i8* %phi
72+
}
73+
74+

0 commit comments

Comments
 (0)
Please sign in to comment.