@@ -2068,7 +2068,9 @@ static void inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes,
2068
2068
}
2069
2069
2070
2070
static void addNoRecurseAttrs (const SCCNodeSet &SCCNodes,
2071
- SmallPtrSet<Function *, 8 > &Changed) {
2071
+ SmallPtrSet<Function *, 8 > &Changed,
2072
+ bool AnyFunctionsAddressIsTaken,
2073
+ bool IsLTOPostLink) {
2072
2074
// Try and identify functions that do not recurse.
2073
2075
2074
2076
// If the SCC contains multiple nodes we know for sure there is recursion.
@@ -2081,6 +2083,10 @@ static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
2081
2083
2082
2084
if (F->hasAddressTaken ())
2083
2085
return ;
2086
+
2087
+ Module *M = F->getParent ();
2088
+ llvm::TargetLibraryInfoImpl TLII (llvm::Triple (M->getTargetTriple ()));
2089
+ llvm::TargetLibraryInfo TLI (TLII);
2084
2090
// If all of the calls in F are identifiable and can be proven to not
2085
2091
// callback F, F is norecurse. This check also detects self-recursion
2086
2092
// as F is not currently marked norecurse, so any call from F to F
@@ -2096,11 +2102,21 @@ static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
2096
2102
if (Callee->doesNotRecurse ())
2097
2103
continue ;
2098
2104
2099
- // External call with NoCallback attribute.
2105
+ LibFunc LF;
2100
2106
if (Callee->isDeclaration ()) {
2107
+ // External call with NoCallback attribute.
2101
2108
if (Callee->hasFnAttribute (Attribute::NoCallback))
2102
2109
continue ;
2103
- return ;
2110
+ // We rely on this only in post link stage when all functions in the
2111
+ // program are known.
2112
+ if (IsLTOPostLink && !AnyFunctionsAddressIsTaken &&
2113
+ TLI.getLibFunc (Callee->getName (), LF))
2114
+ continue ;
2115
+ // Do not consider external functions safe unless we are in LTO
2116
+ // post-link stage and have information about all functions in the
2117
+ // program.
2118
+ if (!IsLTOPostLink)
2119
+ return ;
2104
2120
}
2105
2121
}
2106
2122
}
@@ -2252,7 +2268,8 @@ static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
2252
2268
template <typename AARGetterT>
2253
2269
static SmallPtrSet<Function *, 8 >
2254
2270
deriveAttrsInPostOrder (ArrayRef<Function *> Functions, AARGetterT &&AARGetter,
2255
- bool ArgAttrsOnly) {
2271
+ bool ArgAttrsOnly, bool AnyFunctionAddressTaken = false ,
2272
+ bool IsLTOPostLink = false ) {
2256
2273
SCCNodesResult Nodes = createSCCNodeSet (Functions);
2257
2274
2258
2275
// Bail if the SCC only contains optnone functions.
@@ -2282,7 +2299,8 @@ deriveAttrsInPostOrder(ArrayRef<Function *> Functions, AARGetterT &&AARGetter,
2282
2299
addNoAliasAttrs (Nodes.SCCNodes , Changed);
2283
2300
addNonNullAttrs (Nodes.SCCNodes , Changed);
2284
2301
inferAttrsFromFunctionBodies (Nodes.SCCNodes , Changed);
2285
- addNoRecurseAttrs (Nodes.SCCNodes , Changed);
2302
+ addNoRecurseAttrs (Nodes.SCCNodes , Changed, AnyFunctionAddressTaken,
2303
+ IsLTOPostLink);
2286
2304
2287
2305
// Finally, infer the maximal set of attributes from the ones we've inferred
2288
2306
// above. This is handling the cases where one attribute on a signature
@@ -2324,8 +2342,29 @@ PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
2324
2342
Functions.push_back (&N.getFunction ());
2325
2343
}
2326
2344
2345
+ bool AnyFunctionsAddressIsTaken = false ;
2346
+ // Check if any function in the whole program has its address taken.
2347
+ // We use this information when inferring norecurse attribute: If there is
2348
+ // no function whose address is taken, we conclude that any external function
2349
+ // cannot callback into any user function.
2350
+ if (IsLTOPostLink) {
2351
+ // Get the parent Module of the Function
2352
+ Module &M = *C.begin ()->getFunction ().getParent ();
2353
+ for (Function &F : M) {
2354
+ // We only care about functions defined in user program whose addresses
2355
+ // escape, making them potential callback targets.
2356
+ if (F.isDeclaration ())
2357
+ continue ;
2358
+
2359
+ if (F.hasAddressTaken ()) {
2360
+ AnyFunctionsAddressIsTaken = true ;
2361
+ break ; // break if we found one
2362
+ }
2363
+ }
2364
+ }
2327
2365
auto ChangedFunctions =
2328
- deriveAttrsInPostOrder (Functions, AARGetter, ArgAttrsOnly);
2366
+ deriveAttrsInPostOrder (Functions, AARGetter, ArgAttrsOnly,
2367
+ AnyFunctionsAddressIsTaken, IsLTOPostLink);
2329
2368
if (ChangedFunctions.empty ())
2330
2369
return PreservedAnalyses::all ();
2331
2370
0 commit comments