@@ -935,6 +935,68 @@ static bool addNonNullAttrs(const SCCNodeSet &SCCNodes,
935
935
return MadeChange;
936
936
}
937
937
938
+ // / Removes convergent attributes where we can prove that none of the SCC's
939
+ // / callees are themselves convergent. Returns true if successful at removing
940
+ // / the attribute.
941
+ static bool removeConvergentAttrs (const CallGraphSCC &SCC,
942
+ const SCCNodeSet &SCCNodes) {
943
+ // Determines whether a function can be made non-convergent, ignoring all
944
+ // other functions in SCC. (A function can *actually* be made non-convergent
945
+ // only if all functions in its SCC can be made convergent.)
946
+ auto CanRemoveConvergent = [&] (CallGraphNode *CGN) {
947
+ Function *F = CGN->getFunction ();
948
+ if (!F) return false ;
949
+
950
+ if (!F->isConvergent ()) return true ;
951
+
952
+ // Can't remove convergent from declarations.
953
+ if (F->isDeclaration ()) return false ;
954
+
955
+ // Don't remove convergent from optnone functions.
956
+ if (F->hasFnAttribute (Attribute::OptimizeNone))
957
+ return false ;
958
+
959
+ // Can't remove convergent if any of F's callees -- ignoring functions in the
960
+ // SCC itself -- are convergent.
961
+ if (llvm::any_of (*CGN, [&](const CallGraphNode::CallRecord &CR) {
962
+ Function *F = CR.second ->getFunction ();
963
+ return SCCNodes.count (F) == 0 && (!F || F->isConvergent ());
964
+ }))
965
+ return false ;
966
+
967
+ // CGN doesn't contain calls to intrinsics, so iterate over all of F's
968
+ // callsites, looking for any calls to convergent intrinsics. If we find one,
969
+ // F must remain marked as convergent.
970
+ auto IsConvergentIntrinsicCall = [](Instruction &I) {
971
+ CallSite CS (cast<Value>(&I));
972
+ if (!CS)
973
+ return false ;
974
+ Function *Callee = CS.getCalledFunction ();
975
+ return Callee && Callee->isIntrinsic () && Callee->isConvergent ();
976
+ };
977
+ return !llvm::any_of (*F, [=](BasicBlock &BB) {
978
+ return llvm::any_of (BB, IsConvergentIntrinsicCall);
979
+ });
980
+ };
981
+
982
+ // We can remove the convergent attr from functions in the SCC if they all can
983
+ // be made non-convergent (because they call only non-convergent functions,
984
+ // other than each other).
985
+ if (!llvm::all_of (SCC, CanRemoveConvergent)) return false ;
986
+
987
+ // If we got here, all of the SCC's callees are non-convergent, and none of
988
+ // the optnone functions in the SCC are marked as convergent. Therefore all
989
+ // of the SCC's functions can be marked as non-convergent.
990
+ for (CallGraphNode *CGN : SCC)
991
+ if (Function *F = CGN->getFunction ()) {
992
+ if (F->isConvergent ())
993
+ DEBUG (dbgs () << " Removing convergent attr from " << F->getName ()
994
+ << " \n " );
995
+ F->setNotConvergent ();
996
+ }
997
+ return true ;
998
+ }
999
+
938
1000
static bool setDoesNotRecurse (Function &F) {
939
1001
if (F.doesNotRecurse ())
940
1002
return false ;
@@ -1011,6 +1073,7 @@ bool PostOrderFunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
1011
1073
if (!ExternalNode) {
1012
1074
Changed |= addNoAliasAttrs (SCCNodes);
1013
1075
Changed |= addNonNullAttrs (SCCNodes, *TLI);
1076
+ Changed |= removeConvergentAttrs (SCC, SCCNodes);
1014
1077
}
1015
1078
1016
1079
Changed |= addNoRecurseAttrs (SCC);
0 commit comments