@@ -37,6 +37,7 @@ STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
37
37
STATISTIC (NumNoCapture, " Number of arguments inferred as nocapture" );
38
38
STATISTIC (NumReadOnlyArg, " Number of arguments inferred as readonly" );
39
39
STATISTIC (NumNoAlias, " Number of function returns inferred as noalias" );
40
+ STATISTIC (NumNoUndef, " Number of function returns inferred as noundef returns" );
40
41
STATISTIC (NumNonNull, " Number of function returns inferred as nonnull returns" );
41
42
STATISTIC (NumReturnedArg, " Number of arguments inferred as returned" );
42
43
@@ -104,6 +105,24 @@ static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) {
104
105
return true ;
105
106
}
106
107
108
+ static bool setRetAndArgsNoUndef (Function &F) {
109
+ bool Changed = false ;
110
+ if (!F.getReturnType ()->isVoidTy () &&
111
+ !F.hasAttribute (AttributeList::ReturnIndex, Attribute::NoUndef)) {
112
+ F.addAttribute (AttributeList::ReturnIndex, Attribute::NoUndef);
113
+ ++NumNoUndef;
114
+ Changed = true ;
115
+ }
116
+ for (unsigned ArgNo = 0 ; ArgNo < F.arg_size (); ++ArgNo) {
117
+ if (!F.hasParamAttribute (ArgNo, Attribute::NoUndef)) {
118
+ F.addParamAttr (ArgNo, Attribute::NoUndef);
119
+ ++NumNoUndef;
120
+ Changed = true ;
121
+ }
122
+ }
123
+ return Changed;
124
+ }
125
+
107
126
static bool setRetNonNull (Function &F) {
108
127
assert (F.getReturnType ()->isPointerTy () &&
109
128
" nonnull applies only to pointers" );
@@ -227,6 +246,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
227
246
Changed |= setOnlyReadsMemory (F, 1 );
228
247
return Changed;
229
248
case LibFunc_scanf:
249
+ Changed |= setRetAndArgsNoUndef (F);
230
250
Changed |= setDoesNotThrow (F);
231
251
Changed |= setDoesNotCapture (F, 0 );
232
252
Changed |= setOnlyReadsMemory (F, 0 );
@@ -251,20 +271,23 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
251
271
Changed |= setOnlyReadsMemory (F, 0 );
252
272
return Changed;
253
273
case LibFunc_sscanf:
274
+ Changed |= setRetAndArgsNoUndef (F);
254
275
Changed |= setDoesNotThrow (F);
255
276
Changed |= setDoesNotCapture (F, 0 );
256
277
Changed |= setDoesNotCapture (F, 1 );
257
278
Changed |= setOnlyReadsMemory (F, 0 );
258
279
Changed |= setOnlyReadsMemory (F, 1 );
259
280
return Changed;
260
281
case LibFunc_sprintf:
282
+ Changed |= setRetAndArgsNoUndef (F);
261
283
Changed |= setDoesNotThrow (F);
262
284
Changed |= setDoesNotCapture (F, 0 );
263
285
Changed |= setDoesNotAlias (F, 0 );
264
286
Changed |= setDoesNotCapture (F, 1 );
265
287
Changed |= setOnlyReadsMemory (F, 1 );
266
288
return Changed;
267
289
case LibFunc_snprintf:
290
+ Changed |= setRetAndArgsNoUndef (F);
268
291
Changed |= setDoesNotThrow (F);
269
292
Changed |= setDoesNotCapture (F, 0 );
270
293
Changed |= setDoesNotAlias (F, 0 );
@@ -347,9 +370,11 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
347
370
return Changed;
348
371
case LibFunc_read:
349
372
// May throw; "read" is a valid pthread cancellation point.
373
+ Changed |= setRetAndArgsNoUndef (F);
350
374
Changed |= setDoesNotCapture (F, 1 );
351
375
return Changed;
352
376
case LibFunc_rewind:
377
+ Changed |= setRetAndArgsNoUndef (F);
353
378
Changed |= setDoesNotThrow (F);
354
379
Changed |= setDoesNotCapture (F, 0 );
355
380
return Changed;
@@ -375,6 +400,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
375
400
return Changed;
376
401
case LibFunc_write:
377
402
// May throw; "write" is a valid pthread cancellation point.
403
+ Changed |= setRetAndArgsNoUndef (F);
378
404
Changed |= setDoesNotCapture (F, 1 );
379
405
Changed |= setOnlyReadsMemory (F, 1 );
380
406
return Changed;
@@ -428,6 +454,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
428
454
Changed |= setOnlyReadsMemory (F, 0 );
429
455
return Changed;
430
456
case LibFunc_fopen:
457
+ Changed |= setRetAndArgsNoUndef (F);
431
458
Changed |= setDoesNotThrow (F);
432
459
Changed |= setRetDoesNotAlias (F);
433
460
Changed |= setDoesNotCapture (F, 0 );
@@ -436,13 +463,21 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
436
463
Changed |= setOnlyReadsMemory (F, 1 );
437
464
return Changed;
438
465
case LibFunc_fdopen:
466
+ Changed |= setRetAndArgsNoUndef (F);
439
467
Changed |= setDoesNotThrow (F);
440
468
Changed |= setRetDoesNotAlias (F);
441
469
Changed |= setDoesNotCapture (F, 1 );
442
470
Changed |= setOnlyReadsMemory (F, 1 );
443
471
return Changed;
444
472
case LibFunc_feof:
473
+ Changed |= setRetAndArgsNoUndef (F);
474
+ Changed |= setDoesNotThrow (F);
475
+ Changed |= setDoesNotCapture (F, 0 );
476
+ return Changed;
445
477
case LibFunc_free:
478
+ Changed |= setDoesNotThrow (F);
479
+ Changed |= setDoesNotCapture (F, 0 );
480
+ return Changed;
446
481
case LibFunc_fseek:
447
482
case LibFunc_ftell:
448
483
case LibFunc_fgetc:
@@ -456,64 +491,88 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
456
491
case LibFunc_flockfile:
457
492
case LibFunc_funlockfile:
458
493
case LibFunc_ftrylockfile:
494
+ Changed |= setRetAndArgsNoUndef (F);
459
495
Changed |= setDoesNotThrow (F);
460
496
Changed |= setDoesNotCapture (F, 0 );
461
497
return Changed;
462
498
case LibFunc_ferror:
499
+ Changed |= setRetAndArgsNoUndef (F);
463
500
Changed |= setDoesNotThrow (F);
464
501
Changed |= setDoesNotCapture (F, 0 );
465
502
Changed |= setOnlyReadsMemory (F);
466
503
return Changed;
467
504
case LibFunc_fputc:
468
505
case LibFunc_fputc_unlocked:
469
506
case LibFunc_fstat:
507
+ Changed |= setRetAndArgsNoUndef (F);
508
+ Changed |= setDoesNotThrow (F);
509
+ Changed |= setDoesNotCapture (F, 1 );
510
+ return Changed;
470
511
case LibFunc_frexp:
471
512
case LibFunc_frexpf:
472
513
case LibFunc_frexpl:
514
+ Changed |= setDoesNotThrow (F);
515
+ Changed |= setDoesNotCapture (F, 1 );
516
+ return Changed;
473
517
case LibFunc_fstatvfs:
518
+ Changed |= setRetAndArgsNoUndef (F);
474
519
Changed |= setDoesNotThrow (F);
475
520
Changed |= setDoesNotCapture (F, 1 );
476
521
return Changed;
477
522
case LibFunc_fgets:
478
523
case LibFunc_fgets_unlocked:
524
+ Changed |= setRetAndArgsNoUndef (F);
479
525
Changed |= setDoesNotThrow (F);
480
526
Changed |= setDoesNotCapture (F, 2 );
481
527
return Changed;
482
528
case LibFunc_fread:
483
529
case LibFunc_fread_unlocked:
530
+ Changed |= setRetAndArgsNoUndef (F);
484
531
Changed |= setDoesNotThrow (F);
485
532
Changed |= setDoesNotCapture (F, 0 );
486
533
Changed |= setDoesNotCapture (F, 3 );
487
534
return Changed;
488
535
case LibFunc_fwrite:
489
536
case LibFunc_fwrite_unlocked:
537
+ Changed |= setRetAndArgsNoUndef (F);
490
538
Changed |= setDoesNotThrow (F);
491
539
Changed |= setDoesNotCapture (F, 0 );
492
540
Changed |= setDoesNotCapture (F, 3 );
493
541
// FIXME: readonly #1?
494
542
return Changed;
495
543
case LibFunc_fputs:
496
544
case LibFunc_fputs_unlocked:
545
+ Changed |= setRetAndArgsNoUndef (F);
497
546
Changed |= setDoesNotThrow (F);
498
547
Changed |= setDoesNotCapture (F, 0 );
499
548
Changed |= setDoesNotCapture (F, 1 );
500
549
Changed |= setOnlyReadsMemory (F, 0 );
501
550
return Changed;
502
551
case LibFunc_fscanf:
503
552
case LibFunc_fprintf:
553
+ Changed |= setRetAndArgsNoUndef (F);
504
554
Changed |= setDoesNotThrow (F);
505
555
Changed |= setDoesNotCapture (F, 0 );
506
556
Changed |= setDoesNotCapture (F, 1 );
507
557
Changed |= setOnlyReadsMemory (F, 1 );
508
558
return Changed;
509
559
case LibFunc_fgetpos:
560
+ Changed |= setRetAndArgsNoUndef (F);
510
561
Changed |= setDoesNotThrow (F);
511
562
Changed |= setDoesNotCapture (F, 0 );
512
563
Changed |= setDoesNotCapture (F, 1 );
513
564
return Changed;
514
565
case LibFunc_getc:
566
+ Changed |= setRetAndArgsNoUndef (F);
567
+ Changed |= setDoesNotThrow (F);
568
+ Changed |= setDoesNotCapture (F, 0 );
569
+ return Changed;
515
570
case LibFunc_getlogin_r:
571
+ Changed |= setDoesNotThrow (F);
572
+ Changed |= setDoesNotCapture (F, 0 );
573
+ return Changed;
516
574
case LibFunc_getc_unlocked:
575
+ Changed |= setRetAndArgsNoUndef (F);
517
576
Changed |= setDoesNotThrow (F);
518
577
Changed |= setDoesNotCapture (F, 0 );
519
578
return Changed;
@@ -525,6 +584,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
525
584
case LibFunc_gets:
526
585
case LibFunc_getchar:
527
586
case LibFunc_getchar_unlocked:
587
+ Changed |= setRetAndArgsNoUndef (F);
528
588
Changed |= setDoesNotThrow (F);
529
589
return Changed;
530
590
case LibFunc_getitimer:
@@ -537,6 +597,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
537
597
Changed |= setOnlyReadsMemory (F, 0 );
538
598
return Changed;
539
599
case LibFunc_ungetc:
600
+ Changed |= setRetAndArgsNoUndef (F);
540
601
Changed |= setDoesNotThrow (F);
541
602
Changed |= setDoesNotCapture (F, 1 );
542
603
return Changed;
@@ -564,27 +625,32 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
564
625
return Changed;
565
626
case LibFunc_putc:
566
627
case LibFunc_putc_unlocked:
628
+ Changed |= setRetAndArgsNoUndef (F);
567
629
Changed |= setDoesNotThrow (F);
568
630
Changed |= setDoesNotCapture (F, 1 );
569
631
return Changed;
570
632
case LibFunc_puts:
571
633
case LibFunc_printf:
572
634
case LibFunc_perror:
635
+ Changed |= setRetAndArgsNoUndef (F);
573
636
Changed |= setDoesNotThrow (F);
574
637
Changed |= setDoesNotCapture (F, 0 );
575
638
Changed |= setOnlyReadsMemory (F, 0 );
576
639
return Changed;
577
640
case LibFunc_pread:
578
641
// May throw; "pread" is a valid pthread cancellation point.
642
+ Changed |= setRetAndArgsNoUndef (F);
579
643
Changed |= setDoesNotCapture (F, 1 );
580
644
return Changed;
581
645
case LibFunc_pwrite:
582
646
// May throw; "pwrite" is a valid pthread cancellation point.
647
+ Changed |= setRetAndArgsNoUndef (F);
583
648
Changed |= setDoesNotCapture (F, 1 );
584
649
Changed |= setOnlyReadsMemory (F, 1 );
585
650
return Changed;
586
651
case LibFunc_putchar:
587
652
case LibFunc_putchar_unlocked:
653
+ Changed |= setRetAndArgsNoUndef (F);
588
654
Changed |= setDoesNotThrow (F);
589
655
return Changed;
590
656
case LibFunc_popen:
@@ -600,18 +666,21 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
600
666
Changed |= setDoesNotCapture (F, 0 );
601
667
return Changed;
602
668
case LibFunc_vscanf:
669
+ Changed |= setRetAndArgsNoUndef (F);
603
670
Changed |= setDoesNotThrow (F);
604
671
Changed |= setDoesNotCapture (F, 0 );
605
672
Changed |= setOnlyReadsMemory (F, 0 );
606
673
return Changed;
607
674
case LibFunc_vsscanf:
675
+ Changed |= setRetAndArgsNoUndef (F);
608
676
Changed |= setDoesNotThrow (F);
609
677
Changed |= setDoesNotCapture (F, 0 );
610
678
Changed |= setDoesNotCapture (F, 1 );
611
679
Changed |= setOnlyReadsMemory (F, 0 );
612
680
Changed |= setOnlyReadsMemory (F, 1 );
613
681
return Changed;
614
682
case LibFunc_vfscanf:
683
+ Changed |= setRetAndArgsNoUndef (F);
615
684
Changed |= setDoesNotThrow (F);
616
685
Changed |= setDoesNotCapture (F, 0 );
617
686
Changed |= setDoesNotCapture (F, 1 );
@@ -622,25 +691,29 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
622
691
Changed |= setRetDoesNotAlias (F);
623
692
return Changed;
624
693
case LibFunc_vprintf:
694
+ Changed |= setRetAndArgsNoUndef (F);
625
695
Changed |= setDoesNotThrow (F);
626
696
Changed |= setDoesNotCapture (F, 0 );
627
697
Changed |= setOnlyReadsMemory (F, 0 );
628
698
return Changed;
629
699
case LibFunc_vfprintf:
630
700
case LibFunc_vsprintf:
701
+ Changed |= setRetAndArgsNoUndef (F);
631
702
Changed |= setDoesNotThrow (F);
632
703
Changed |= setDoesNotCapture (F, 0 );
633
704
Changed |= setDoesNotCapture (F, 1 );
634
705
Changed |= setOnlyReadsMemory (F, 1 );
635
706
return Changed;
636
707
case LibFunc_vsnprintf:
708
+ Changed |= setRetAndArgsNoUndef (F);
637
709
Changed |= setDoesNotThrow (F);
638
710
Changed |= setDoesNotCapture (F, 0 );
639
711
Changed |= setDoesNotCapture (F, 2 );
640
712
Changed |= setOnlyReadsMemory (F, 2 );
641
713
return Changed;
642
714
case LibFunc_open:
643
715
// May throw; "open" is a valid pthread cancellation point.
716
+ Changed |= setRetAndArgsNoUndef (F);
644
717
Changed |= setDoesNotCapture (F, 0 );
645
718
Changed |= setOnlyReadsMemory (F, 0 );
646
719
return Changed;
@@ -693,14 +766,17 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
693
766
Changed |= setOnlyReadsMemory (F, 1 );
694
767
return Changed;
695
768
case LibFunc_under_IO_getc:
769
+ Changed |= setRetAndArgsNoUndef (F);
696
770
Changed |= setDoesNotThrow (F);
697
771
Changed |= setDoesNotCapture (F, 0 );
698
772
return Changed;
699
773
case LibFunc_under_IO_putc:
774
+ Changed |= setRetAndArgsNoUndef (F);
700
775
Changed |= setDoesNotThrow (F);
701
776
Changed |= setDoesNotCapture (F, 1 );
702
777
return Changed;
703
778
case LibFunc_dunder_isoc99_scanf:
779
+ Changed |= setRetAndArgsNoUndef (F);
704
780
Changed |= setDoesNotThrow (F);
705
781
Changed |= setDoesNotCapture (F, 0 );
706
782
Changed |= setOnlyReadsMemory (F, 0 );
@@ -714,13 +790,15 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
714
790
Changed |= setOnlyReadsMemory (F, 0 );
715
791
return Changed;
716
792
case LibFunc_dunder_isoc99_sscanf:
793
+ Changed |= setRetAndArgsNoUndef (F);
717
794
Changed |= setDoesNotThrow (F);
718
795
Changed |= setDoesNotCapture (F, 0 );
719
796
Changed |= setDoesNotCapture (F, 1 );
720
797
Changed |= setOnlyReadsMemory (F, 0 );
721
798
Changed |= setOnlyReadsMemory (F, 1 );
722
799
return Changed;
723
800
case LibFunc_fopen64:
801
+ Changed |= setRetAndArgsNoUndef (F);
724
802
Changed |= setDoesNotThrow (F);
725
803
Changed |= setRetDoesNotAlias (F);
726
804
Changed |= setDoesNotCapture (F, 0 );
@@ -730,6 +808,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
730
808
return Changed;
731
809
case LibFunc_fseeko64:
732
810
case LibFunc_ftello64:
811
+ Changed |= setRetAndArgsNoUndef (F);
733
812
Changed |= setDoesNotThrow (F);
734
813
Changed |= setDoesNotCapture (F, 0 );
735
814
return Changed;
@@ -739,11 +818,13 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
739
818
return Changed;
740
819
case LibFunc_fstat64:
741
820
case LibFunc_fstatvfs64:
821
+ Changed |= setRetAndArgsNoUndef (F);
742
822
Changed |= setDoesNotThrow (F);
743
823
Changed |= setDoesNotCapture (F, 1 );
744
824
return Changed;
745
825
case LibFunc_open64:
746
826
// May throw; "open" is a valid pthread cancellation point.
827
+ Changed |= setRetAndArgsNoUndef (F);
747
828
Changed |= setDoesNotCapture (F, 0 );
748
829
Changed |= setOnlyReadsMemory (F, 0 );
749
830
return Changed;
0 commit comments