llvm.org GIT mirror llvm / 2c37b35
[attrs] Move the norecurse deduction to operate on the node set rather than the SCC object, and have it scan the instruction stream directly rather than relying on call records. This makes the behavior of this routine consistent between libc routines and LLVM intrinsics for libc routines. We can go and start teaching it about those being norecurse, but we should behave the same for the intrinsic and the libc routine rather than differently. I chatted with James Molloy and the inconsistency doesn't seem intentional and likely is due to intrinsic calls not being modelled in the call graph analyses. This also fixes a bug where we would deduce norecurse on optnone functions, when generally we try to handle optnone functions as-if they were replaceable and thus unanalyzable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260813 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 4 years ago
4 changed file(s) with 30 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
990990 return true;
991991 }
992992
993 static bool addNoRecurseAttrs(const CallGraphSCC &SCC) {
993 static bool addNoRecurseAttrs(const SCCNodeSet &SCCNodes) {
994994 // Try and identify functions that do not recurse.
995995
996996 // If the SCC contains multiple nodes we know for sure there is recursion.
997 if (!SCC.isSingular())
997 if (SCCNodes.size() != 1)
998998 return false;
999999
1000 const CallGraphNode *CGN = *SCC.begin();
1001 Function *F = CGN->getFunction();
1000 Function *F = *SCCNodes.begin();
10021001 if (!F || F->isDeclaration() || F->doesNotRecurse())
10031002 return false;
10041003
10051004 // If all of the calls in F are identifiable and are to norecurse functions, F
10061005 // is norecurse. This check also detects self-recursion as F is not currently
10071006 // marked norecurse, so any called from F to F will not be marked norecurse.
1008 if (std::all_of(CGN->begin(), CGN->end(),
1009 [](const CallGraphNode::CallRecord &CR) {
1010 Function *F = CR.second->getFunction();
1011 return F && F->doesNotRecurse();
1012 }))
1013 // Function calls a potentially recursive function.
1014 return setDoesNotRecurse(*F);
1015
1016 // Nothing else we can deduce usefully during the postorder traversal.
1017 return false;
1007 for (Instruction &I : instructions(*F))
1008 if (auto CS = CallSite(&I)) {
1009 Function *Callee = CS.getCalledFunction();
1010 if (!Callee || Callee == F || !Callee->doesNotRecurse())
1011 // Function calls a potentially recursive function.
1012 return false;
1013 }
1014
1015 // Every call was to a non-recursive function other than this function, and
1016 // we have no indirect recursion as the SCC size is one. This function cannot
1017 // recurse.
1018 return setDoesNotRecurse(*F);
10181019 }
10191020
10201021 bool PostOrderFunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
10591060 Changed |= addNoAliasAttrs(SCCNodes);
10601061 Changed |= addNonNullAttrs(SCCNodes, *TLI);
10611062 Changed |= removeConvergentAttrs(SCCNodes);
1062 }
1063
1064 Changed |= addNoRecurseAttrs(SCC);
1063 Changed |= addNoRecurseAttrs(SCCNodes);
1064 }
1065
10651066 return Changed;
10661067 }
10671068
4242 ; This is unusual, since the function is memcpy, but as above, this
4343 ; isn't necessarily invalid.
4444
45 ; CHECK: define void @test2_yes(i8* nocapture %p, i8* nocapture %q, i64 %n) #0 {
45 ; CHECK: define void @test2_yes(i8* nocapture %p, i8* nocapture %q, i64 %n) #4 {
4646 define void @test2_yes(i8* %p, i8* %q, i64 %n) nounwind {
4747 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i32 1, i1 false), !tbaa !1
4848 ret void
4949 }
5050
51 ; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #1 {
51 ; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #3 {
5252 define void @test2_no(i8* %p, i8* %q, i64 %n) nounwind {
5353 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i32 1, i1 false), !tbaa !2
5454 ret void
7575 ; CHECK: attributes #1 = { norecurse nounwind }
7676 ; CHECK: attributes #2 = { nounwind readonly }
7777 ; CHECK: attributes #3 = { nounwind }
78 ; CHECK: attributes #4 = { argmemonly nounwind }
78 ; CHECK: attributes #4 = { nounwind readnone }
79 ; CHECK: attributes #5 = { argmemonly nounwind }
7980
8081 ; Root note.
8182 !0 = !{ }
2828 }
2929 declare i32 @k() readnone
3030
31 ; CHECK: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len) {
32 define void @intrinsic(i8* %dest, i8* %src, i32 %len) {
33 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i32 1, i1 false)
34 ret void
35 }
36 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
37
3138 ; CHECK: define internal i32 @called_by_norecurse() #0
3239 define internal i32 @called_by_norecurse() {
3340 %a = call i32 @k()
1515
1616 declare i8 @strlen(i8*) noinline optnone
1717 ; CHECK-LABEL: @strlen
18 ; CHECK: (i8*) #2
18 ; CHECK: (i8*) #1
1919
2020 ; CHECK-LABEL: attributes #0
2121 ; CHECK: = { norecurse readnone }
2222 ; CHECK-LABEL: attributes #1
23 ; CHECK: = { noinline norecurse optnone }
24 ; CHECK-LABEL: attributes #2
2523 ; CHECK: = { noinline optnone }