@@ -47,6 +47,7 @@ STATISTIC(
4747 NumWriteArgumentMemOrErrnoMemOnly,
4848 " Number of functions inferred as memory(argmem: write, errnomem: write)" );
4949STATISTIC (NumNoUnwind, " Number of functions inferred as nounwind" );
50+ STATISTIC (NumNoCallback, " Number of functions inferred as nocallback" );
5051STATISTIC (NumNoCapture, " Number of arguments inferred as nocapture" );
5152STATISTIC (NumWriteOnlyArg, " Number of arguments inferred as writeonly" );
5253STATISTIC (NumReadOnlyArg, " Number of arguments inferred as readonly" );
@@ -148,6 +149,14 @@ static bool setDoesNotThrow(Function &F) {
148149 return true ;
149150}
150151
152+ static bool setDoesNotCallback (Function &F) {
153+ if (F.hasFnAttribute (Attribute::NoCallback))
154+ return false ;
155+ F.addFnAttr (Attribute::NoCallback);
156+ ++NumNoCallback;
157+ return true ;
158+ }
159+
151160static bool setRetDoesNotAlias (Function &F) {
152161 if (F.hasRetAttribute (Attribute::NoAlias))
153162 return false ;
@@ -322,6 +331,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
322331 case LibFunc_wcslen:
323332 Changed |= setOnlyReadsMemory (F);
324333 Changed |= setDoesNotThrow (F);
334+ Changed |= setDoesNotCallback (F);
325335 Changed |= setOnlyAccessesArgMemory (F);
326336 Changed |= setWillReturn (F);
327337 Changed |= setDoesNotCapture (F, 0 );
@@ -331,6 +341,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
331341 Changed |= setOnlyAccessesArgMemory (F);
332342 Changed |= setOnlyReadsMemory (F);
333343 Changed |= setDoesNotThrow (F);
344+ Changed |= setDoesNotCallback (F);
334345 Changed |= setWillReturn (F);
335346 break ;
336347 case LibFunc_strtol:
@@ -341,6 +352,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
341352 case LibFunc_strtold:
342353 case LibFunc_strtoull:
343354 Changed |= setDoesNotThrow (F);
355+ Changed |= setDoesNotCallback (F);
344356 Changed |= setWillReturn (F);
345357 Changed |= setDoesNotCapture (F, 1 );
346358 Changed |= setOnlyReadsMemory (F, 0 );
@@ -349,6 +361,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
349361 case LibFunc_strncat:
350362 Changed |= setOnlyAccessesArgMemory (F);
351363 Changed |= setDoesNotThrow (F);
364+ Changed |= setDoesNotCallback (F);
352365 Changed |= setWillReturn (F);
353366 Changed |= setReturnedArg (F, 0 );
354367 Changed |= setDoesNotCapture (F, 1 );
@@ -364,6 +377,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
364377 case LibFunc_stpncpy:
365378 Changed |= setOnlyAccessesArgMemory (F);
366379 Changed |= setDoesNotThrow (F);
380+ Changed |= setDoesNotCallback (F);
367381 Changed |= setWillReturn (F);
368382 Changed |= setDoesNotCapture (F, 1 );
369383 Changed |= setOnlyWritesMemory (F, 0 );
@@ -373,6 +387,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
373387 break ;
374388 case LibFunc_strxfrm:
375389 Changed |= setDoesNotThrow (F);
390+ Changed |= setDoesNotCallback (F);
376391 Changed |= setWillReturn (F);
377392 Changed |= setDoesNotCapture (F, 0 );
378393 Changed |= setDoesNotCapture (F, 1 );
@@ -383,6 +398,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
383398 case LibFunc_strncmp: // 0,1
384399 case LibFunc_strcspn: // 0,1
385400 Changed |= setDoesNotThrow (F);
401+ Changed |= setDoesNotCallback (F);
386402 Changed |= setOnlyAccessesArgMemory (F);
387403 Changed |= setWillReturn (F);
388404 Changed |= setOnlyReadsMemory (F);
@@ -396,6 +412,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
396412 // global memory.
397413 Changed |= setOnlyReadsMemory (F);
398414 Changed |= setDoesNotThrow (F);
415+ Changed |= setDoesNotCallback (F);
399416 Changed |= setWillReturn (F);
400417 Changed |= setDoesNotCapture (F, 0 );
401418 Changed |= setDoesNotCapture (F, 1 );
@@ -405,12 +422,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
405422 Changed |= setOnlyAccessesArgMemory (F);
406423 Changed |= setOnlyReadsMemory (F);
407424 Changed |= setDoesNotThrow (F);
425+ Changed |= setDoesNotCallback (F);
408426 Changed |= setWillReturn (F);
409427 Changed |= setDoesNotCapture (F, 1 );
410428 break ;
411429 case LibFunc_strtok:
412430 case LibFunc_strtok_r:
413431 Changed |= setDoesNotThrow (F);
432+ Changed |= setDoesNotCallback (F);
414433 Changed |= setWillReturn (F);
415434 Changed |= setDoesNotCapture (F, 1 );
416435 Changed |= setOnlyReadsMemory (F, 1 );
@@ -509,13 +528,15 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
509528 Changed |= setOnlyAccessesArgMemory (F);
510529 Changed |= setOnlyReadsMemory (F);
511530 Changed |= setDoesNotThrow (F);
531+ Changed |= setDoesNotCallback (F);
512532 Changed |= setWillReturn (F);
513533 Changed |= setDoesNotCapture (F, 0 );
514534 Changed |= setDoesNotCapture (F, 1 );
515535 break ;
516536 case LibFunc_memchr:
517537 case LibFunc_memrchr:
518538 Changed |= setDoesNotThrow (F);
539+ Changed |= setDoesNotCallback (F);
519540 Changed |= setOnlyAccessesArgMemory (F);
520541 Changed |= setOnlyReadsMemory (F);
521542 Changed |= setWillReturn (F);
@@ -524,13 +545,15 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
524545 case LibFunc_modff:
525546 case LibFunc_modfl:
526547 Changed |= setDoesNotThrow (F);
548+ Changed |= setDoesNotCallback (F);
527549 Changed |= setWillReturn (F);
528550 Changed |= setOnlyAccessesArgMemory (F);
529551 Changed |= setOnlyWritesMemory (F);
530552 Changed |= setDoesNotCapture (F, 1 );
531553 break ;
532554 case LibFunc_memcpy:
533555 Changed |= setDoesNotThrow (F);
556+ Changed |= setDoesNotCallback (F);
534557 Changed |= setOnlyAccessesArgMemory (F);
535558 Changed |= setWillReturn (F);
536559 Changed |= setDoesNotAlias (F, 0 );
@@ -542,6 +565,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
542565 break ;
543566 case LibFunc_memmove:
544567 Changed |= setDoesNotThrow (F);
568+ Changed |= setDoesNotCallback (F);
545569 Changed |= setOnlyAccessesArgMemory (F);
546570 Changed |= setWillReturn (F);
547571 Changed |= setReturnedArg (F, 0 );
@@ -555,6 +579,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
555579 [[fallthrough]];
556580 case LibFunc_memcpy_chk:
557581 Changed |= setDoesNotThrow (F);
582+ Changed |= setDoesNotCallback (F);
558583 Changed |= setOnlyAccessesArgMemory (F);
559584 Changed |= setDoesNotAlias (F, 0 );
560585 Changed |= setOnlyWritesMemory (F, 0 );
@@ -657,6 +682,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
657682 break ;
658683 case LibFunc_bcopy:
659684 Changed |= setDoesNotThrow (F);
685+ Changed |= setDoesNotCallback (F);
660686 Changed |= setOnlyAccessesArgMemory (F);
661687 Changed |= setWillReturn (F);
662688 Changed |= setDoesNotCapture (F, 0 );
@@ -666,6 +692,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
666692 break ;
667693 case LibFunc_bcmp:
668694 Changed |= setDoesNotThrow (F);
695+ Changed |= setDoesNotCallback (F);
669696 Changed |= setOnlyAccessesArgMemory (F);
670697 Changed |= setOnlyReadsMemory (F);
671698 Changed |= setWillReturn (F);
@@ -674,6 +701,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
674701 break ;
675702 case LibFunc_bzero:
676703 Changed |= setDoesNotThrow (F);
704+ Changed |= setDoesNotCallback (F);
677705 Changed |= setOnlyAccessesArgMemory (F);
678706 Changed |= setWillReturn (F);
679707 Changed |= setDoesNotCapture (F, 0 );
@@ -710,6 +738,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
710738 case LibFunc_atof:
711739 case LibFunc_atoll:
712740 Changed |= setDoesNotThrow (F);
741+ Changed |= setDoesNotCallback (F);
713742 Changed |= setOnlyReadsMemory (F);
714743 Changed |= setWillReturn (F);
715744 Changed |= setDoesNotCapture (F, 0 );
@@ -787,6 +816,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
787816 case LibFunc_frexpf:
788817 case LibFunc_frexpl:
789818 Changed |= setDoesNotThrow (F);
819+ Changed |= setDoesNotCallback (F);
790820 Changed |= setWillReturn (F);
791821 Changed |= setOnlyAccessesArgMemory (F);
792822 Changed |= setOnlyWritesMemory (F);
@@ -1025,6 +1055,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
10251055 case LibFunc_ntohl:
10261056 case LibFunc_ntohs:
10271057 Changed |= setDoesNotThrow (F);
1058+ Changed |= setDoesNotCallback (F);
10281059 Changed |= setDoesNotAccessMemory (F);
10291060 break ;
10301061 case LibFunc_lstat:
@@ -1041,7 +1072,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
10411072 Changed |= setOnlyReadsMemory (F, 0 );
10421073 break ;
10431074 case LibFunc_qsort:
1044- // May throw; places call through function pointer.
1075+ // May throw/callback ; places call through function pointer.
10451076 // Cannot give undef pointer/size
10461077 Changed |= setRetAndArgsNoUndef (F);
10471078 Changed |= setDoesNotCapture (F, 3 );
@@ -1058,6 +1089,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
10581089 break ;
10591090 case LibFunc_dunder_strtok_r:
10601091 Changed |= setDoesNotThrow (F);
1092+ Changed |= setDoesNotCallback (F);
10611093 Changed |= setDoesNotCapture (F, 1 );
10621094 Changed |= setOnlyReadsMemory (F, 1 );
10631095 break ;
@@ -1149,13 +1181,15 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
11491181 Changed |= setOnlyAccessesArgMemory (F);
11501182 Changed |= setOnlyWritesMemory (F, 0 );
11511183 Changed |= setDoesNotThrow (F);
1184+ Changed |= setDoesNotCallback (F);
11521185 break ;
11531186 case LibFunc_abort:
11541187 Changed |= setIsCold (F);
11551188 Changed |= setNoReturn (F);
11561189 Changed |= setDoesNotThrow (F);
11571190 break ;
11581191 case LibFunc_terminate:
1192+ // May callback; terminate_handler may be called
11591193 Changed |= setIsCold (F);
11601194 Changed |= setNoReturn (F);
11611195 break ;
@@ -1284,6 +1318,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
12841318 case LibFunc_tanhl:
12851319 case LibFunc_tanl:
12861320 Changed |= setDoesNotThrow (F);
1321+ Changed |= setDoesNotCallback (F);
12871322 Changed |= setDoesNotFreeMemory (F);
12881323 Changed |= setWillReturn (F);
12891324 Changed |= setOnlyWritesErrnoMemory (F);
@@ -1327,6 +1362,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
13271362 case LibFunc_isascii:
13281363 case LibFunc_isdigit:
13291364 Changed |= setDoesNotThrow (F);
1365+ Changed |= setDoesNotCallback (F);
13301366 Changed |= setDoesNotFreeMemory (F);
13311367 Changed |= setWillReturn (F);
13321368 break ;
@@ -1340,6 +1376,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
13401376 case LibFunc_remquof:
13411377 case LibFunc_remquol:
13421378 Changed |= setDoesNotThrow (F);
1379+ Changed |= setDoesNotCallback (F);
13431380 Changed |= setDoesNotFreeMemory (F);
13441381 Changed |= setOnlyWritesMemory (F, 2 );
13451382 Changed |= setDoesNotCapture (F, 2 );
0 commit comments