[llvm] ff256c1 - [Attributor] Derive `willreturn` based on `mustprogress`

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 11 21:31:50 PST 2021


Author: Johannes Doerfert
Date: 2021-03-11T23:31:44-06:00
New Revision: ff256c1376fea83272c2d0ba7b33fdea44459495

URL: https://github.com/llvm/llvm-project/commit/ff256c1376fea83272c2d0ba7b33fdea44459495
DIFF: https://github.com/llvm/llvm-project/commit/ff256c1376fea83272c2d0ba7b33fdea44459495.diff

LOG: [Attributor] Derive `willreturn` based on `mustprogress`

Since D86233 we have `mustprogress` which, in combination with
`readonly`, implies `willreturn`. The idea is that every side-effect
has to be modeled as a "write". Consequently, `readonly` means there
is no side-effect, and `mustprogress` guarantees that we cannot "loop"
forever without side-effect.

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D94125

Added: 
    

Modified: 
    llvm/lib/Transforms/IPO/AttributorAttributes.cpp
    llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll
    llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
    llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
    llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll
    llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll
    llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll
    llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
    llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll
    llvm/test/Transforms/Attributor/cb_range_disabled.ll
    llvm/test/Transforms/Attributor/cb_range_enabled.ll
    llvm/test/Transforms/Attributor/internal-noalias.ll
    llvm/test/Transforms/Attributor/noalias.ll
    llvm/test/Transforms/Attributor/nocapture-1.ll
    llvm/test/Transforms/Attributor/nofree.ll
    llvm/test/Transforms/Attributor/nosync.ll
    llvm/test/Transforms/Attributor/potential.ll
    llvm/test/Transforms/Attributor/range.ll
    llvm/test/Transforms/Attributor/readattrs.ll
    llvm/test/Transforms/Attributor/returned.ll
    llvm/test/Transforms/Attributor/value-simplify.ll
    llvm/test/Transforms/Attributor/willreturn.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 5dd3cc09ef7d..21fa11aadea8 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -2333,13 +2333,37 @@ struct AAWillReturnImpl : public AAWillReturn {
   void initialize(Attributor &A) override {
     AAWillReturn::initialize(A);
 
-    Function *F = getAnchorScope();
-    if (!F || F->isDeclaration() || mayContainUnboundedCycle(*F, A))
-      indicatePessimisticFixpoint();
+    if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ true)) {
+      indicateOptimisticFixpoint();
+      return;
+    }
+  }
+
+  /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
+  bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
+    // Check for `mustprogress` in the scope and the associated function which
+    // might be 
diff erent if this is a call site.
+    if ((!getAnchorScope() || !getAnchorScope()->mustProgress()) &&
+        (!getAssociatedFunction() || !getAssociatedFunction()->mustProgress()))
+      return false;
+
+    const auto &MemAA = A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(),
+                                                      DepClassTy::NONE);
+    if (!MemAA.isAssumedReadOnly())
+      return false;
+    if (KnownOnly && !MemAA.isKnownReadOnly())
+      return false;
+    if (!MemAA.isKnownReadOnly())
+      A.recordDependence(MemAA, *this, DepClassTy::OPTIONAL);
+
+    return true;
   }
 
   /// See AbstractAttribute::updateImpl(...).
   ChangeStatus updateImpl(Attributor &A) override {
+    if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
+      return ChangeStatus::UNCHANGED;
+
     auto CheckForWillReturn = [&](Instruction &I) {
       IRPosition IPos = IRPosition::callsite_function(cast<CallBase>(I));
       const auto &WillReturnAA =
@@ -2369,6 +2393,15 @@ struct AAWillReturnFunction final : AAWillReturnImpl {
   AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
       : AAWillReturnImpl(IRP, A) {}
 
+  /// See AbstractAttribute::initialize(...).
+  void initialize(Attributor &A) override {
+    AAWillReturnImpl::initialize(A);
+
+    Function *F = getAnchorScope();
+    if (!F || F->isDeclaration() || mayContainUnboundedCycle(*F, A))
+      indicatePessimisticFixpoint();
+  }
+
   /// See AbstractAttribute::trackStatistics()
   void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
 };
@@ -2380,7 +2413,7 @@ struct AAWillReturnCallSite final : AAWillReturnImpl {
 
   /// See AbstractAttribute::initialize(...).
   void initialize(Attributor &A) override {
-    AAWillReturn::initialize(A);
+    AAWillReturnImpl::initialize(A);
     Function *F = getAssociatedFunction();
     if (!F || !A.isFunctionIPOAmendable(*F))
       indicatePessimisticFixpoint();
@@ -2388,6 +2421,9 @@ struct AAWillReturnCallSite final : AAWillReturnImpl {
 
   /// See AbstractAttribute::updateImpl(...).
   ChangeStatus updateImpl(Attributor &A) override {
+    if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
+      return ChangeStatus::UNCHANGED;
+
     // TODO: Once we have call site specific value information we can provide
     //       call site specific liveness information and then it makes
     //       sense to specialize attributes for call sites arguments instead of
@@ -5603,9 +5639,9 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
       const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
       for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
         Type *PointeeTy = PrivStructType->getElementType(u)->getPointerTo();
-        Value *Ptr = constructPointer(
-            PointeeTy, PrivType, &Base, PrivStructLayout->getElementOffset(u),
-            IRB, DL);
+        Value *Ptr =
+            constructPointer(PointeeTy, PrivType, &Base,
+                             PrivStructLayout->getElementOffset(u), IRB, DL);
         new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
       }
     } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
@@ -5613,8 +5649,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
       Type *PointeePtrTy = PointeeTy->getPointerTo();
       uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
       for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
-        Value *Ptr = constructPointer(
-            PointeePtrTy, PrivType, &Base, u * PointeeTySize, IRB, DL);
+        Value *Ptr = constructPointer(PointeePtrTy, PrivType, &Base,
+                                      u * PointeeTySize, IRB, DL);
         new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
       }
     } else {
@@ -5655,8 +5691,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
       uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
       Type *PointeePtrTy = PointeeTy->getPointerTo();
       for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
-        Value *Ptr = constructPointer(
-            PointeePtrTy, PrivType, Base, u * PointeeTySize, IRB, DL);
+        Value *Ptr = constructPointer(PointeePtrTy, PrivType, Base,
+                                      u * PointeeTySize, IRB, DL);
         LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
         L->setAlignment(Alignment);
         ReplacementValues.push_back(L);

diff  --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll
index 7c8eea655d77..fa98ef74d5ae 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll
@@ -65,5 +65,5 @@ entry:
 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR1]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
index 2125e3ee6e2d..7382ea8d345e 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
@@ -164,9 +164,9 @@ entry:
 ; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { nofree nosync nounwind readnone willreturn }
 ;.
 ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC_OPM: attributes #[[ATTR1]] = { willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR1]] = { readnone willreturn }
 ;.
 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR2]] = { willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR2]] = { readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
index 0dfa1d5d0385..93f093efeff4 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
@@ -218,5 +218,5 @@ entry:
 ; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { nofree nosync nounwind readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn }
+; IS__CGSCC____: attributes #[[ATTR1:[0-9]+]] = { nounwind readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll
index a604b1da4410..c2baf04e74a4 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll
@@ -65,12 +65,12 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
 ;.
 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
 ; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
-; IS__TUNIT____: attributes #[[ATTR2]] = { willreturn }
+; IS__TUNIT____: attributes #[[ATTR2]] = { readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
-; IS__CGSCC____: attributes #[[ATTR3]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR3]] = { readnone willreturn }
 ;.
 ; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug)
 ; CHECK: [[META1:![0-9]+]] = !DIFile(filename: "test.c", directory: "")

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll
index 11728bff8ec7..b6a9cfd639e0 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll
@@ -265,5 +265,5 @@ entry:
 ; IS__CGSCC____: attributes #[[ATTR0:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readonly willreturn }
 ; IS__CGSCC____: attributes #[[ATTR2]] = { nounwind readonly willreturn }
-; IS__CGSCC____: attributes #[[ATTR3:[0-9]+]] = { nounwind willreturn }
+; IS__CGSCC____: attributes #[[ATTR3:[0-9]+]] = { nounwind readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll
index 90f4436f14be..e41262281ad7 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll
@@ -110,7 +110,7 @@ entry:
 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR1]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
 ;.
 ; CHECK: [[META0:![0-9]+]] = !{i64 -8, i64 43}
 ;.

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
index 541540d724de..30dbdd109753 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
@@ -147,6 +147,6 @@ declare i32 @__gxx_personality_v0(...)
 ; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn }
 ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR2]] = { nounwind willreturn }
-; IS__CGSCC____: attributes #[[ATTR3]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR3]] = { readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR4]] = { nounwind readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll
index ca07d2818a83..584ec97b6c55 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll
@@ -155,5 +155,5 @@ define i32 @caller2(i1 %Q) {
 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR1]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/cb_range_disabled.ll b/llvm/test/Transforms/Attributor/cb_range_disabled.ll
index 6df12493d45a..effc39b7607b 100644
--- a/llvm/test/Transforms/Attributor/cb_range_disabled.ll
+++ b/llvm/test/Transforms/Attributor/cb_range_disabled.ll
@@ -134,7 +134,7 @@ define i32 @test2_ncheck(i32 %unknown) {
 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR1]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
 ;.
 ; NOT_CGSCC_NPM: [[META0:![0-9]+]] = !{i32 0, i32 101}
 ;.

diff  --git a/llvm/test/Transforms/Attributor/cb_range_enabled.ll b/llvm/test/Transforms/Attributor/cb_range_enabled.ll
index c7e966c3e847..52fd1e1ee0ac 100644
--- a/llvm/test/Transforms/Attributor/cb_range_enabled.ll
+++ b/llvm/test/Transforms/Attributor/cb_range_enabled.ll
@@ -128,7 +128,7 @@ define i32 @test2_ncheck(i32 %unknown) {
 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR1]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
 ;.
 ; CHECK: [[META0:![0-9]+]] = !{i32 0, i32 101}
 ; CHECK: [[META1:![0-9]+]] = !{i32 -20, i32 81}

diff  --git a/llvm/test/Transforms/Attributor/internal-noalias.ll b/llvm/test/Transforms/Attributor/internal-noalias.ll
index 7ad94c187677..484aa14cc4e3 100644
--- a/llvm/test/Transforms/Attributor/internal-noalias.ll
+++ b/llvm/test/Transforms/Attributor/internal-noalias.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
-; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
-; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
+; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
+; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
 ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
 

diff  --git a/llvm/test/Transforms/Attributor/noalias.ll b/llvm/test/Transforms/Attributor/noalias.ll
index 21743acd6265..10e3218036e4 100644
--- a/llvm/test/Transforms/Attributor/noalias.ll
+++ b/llvm/test/Transforms/Attributor/noalias.ll
@@ -576,17 +576,29 @@ define internal i32 @ret(i32* %arg) {
 
 ; Function Attrs: nounwind optsize
 define internal fastcc double @strtox(i8* %s, i8** %p, i32 %prec) unnamed_addr {
-; CHECK-LABEL: define {{[^@]+}}@strtox
-; CHECK-SAME: (i8* [[S:%.*]]) unnamed_addr {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8
-; CHECK-NEXT:    [[TMP0:%.*]] = bitcast %struct._IO_FILE* [[F]] to i8*
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 144, i8* nocapture nofree noundef nonnull align 8 dereferenceable(240) [[TMP0]]) #[[ATTR10:[0-9]+]]
-; CHECK-NEXT:    [[CALL:%.*]] = call i32 bitcast (i32 (...)* @sh_fromstring to i32 (%struct._IO_FILE*, i8*)*)(%struct._IO_FILE* nonnull align 8 dereferenceable(240) [[F]], i8* [[S]])
-; CHECK-NEXT:    call void @__shlim(%struct._IO_FILE* noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0)
-; CHECK-NEXT:    [[CALL1:%.*]] = call double @__floatscan(%struct._IO_FILE* noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1)
-; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 noundef 144, i8* nocapture nofree noundef nonnull align 8 dereferenceable(240) [[TMP0]])
-; CHECK-NEXT:    ret double [[CALL1]]
+; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@strtox
+; NOT_CGSCC_NPM-SAME: (i8* [[S:%.*]]) unnamed_addr {
+; NOT_CGSCC_NPM-NEXT:  entry:
+; NOT_CGSCC_NPM-NEXT:    [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8
+; NOT_CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast %struct._IO_FILE* [[F]] to i8*
+; NOT_CGSCC_NPM-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 144, i8* nocapture nofree noundef nonnull align 8 dereferenceable(240) [[TMP0]]) #[[ATTR10:[0-9]+]]
+; NOT_CGSCC_NPM-NEXT:    [[CALL:%.*]] = call i32 bitcast (i32 (...)* @sh_fromstring to i32 (%struct._IO_FILE*, i8*)*)(%struct._IO_FILE* nonnull align 8 dereferenceable(240) [[F]], i8* [[S]])
+; NOT_CGSCC_NPM-NEXT:    call void @__shlim(%struct._IO_FILE* noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0)
+; NOT_CGSCC_NPM-NEXT:    [[CALL1:%.*]] = call double @__floatscan(%struct._IO_FILE* noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1)
+; NOT_CGSCC_NPM-NEXT:    call void @llvm.lifetime.end.p0i8(i64 noundef 144, i8* nocapture nofree noundef nonnull align 8 dereferenceable(240) [[TMP0]])
+; NOT_CGSCC_NPM-NEXT:    ret double [[CALL1]]
+;
+; IS__CGSCC____-LABEL: define {{[^@]+}}@strtox
+; IS__CGSCC____-SAME: (i8* [[S:%.*]]) unnamed_addr {
+; IS__CGSCC____-NEXT:  entry:
+; IS__CGSCC____-NEXT:    [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8
+; IS__CGSCC____-NEXT:    [[TMP0:%.*]] = bitcast %struct._IO_FILE* [[F]] to i8*
+; IS__CGSCC____-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 144, i8* nocapture nofree noundef nonnull align 8 dereferenceable(240) [[TMP0]]) #[[ATTR12:[0-9]+]]
+; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i32 bitcast (i32 (...)* @sh_fromstring to i32 (%struct._IO_FILE*, i8*)*)(%struct._IO_FILE* nonnull align 8 dereferenceable(240) [[F]], i8* [[S]])
+; IS__CGSCC____-NEXT:    call void @__shlim(%struct._IO_FILE* noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0)
+; IS__CGSCC____-NEXT:    [[CALL1:%.*]] = call double @__floatscan(%struct._IO_FILE* noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1)
+; IS__CGSCC____-NEXT:    call void @llvm.lifetime.end.p0i8(i64 noundef 144, i8* nocapture nofree noundef nonnull align 8 dereferenceable(240) [[TMP0]])
+; IS__CGSCC____-NEXT:    ret double [[CALL1]]
 ;
 entry:
   %f = alloca %struct._IO_FILE, align 8
@@ -686,10 +698,10 @@ define void @test15_caller(i32* noalias %p, i32 %c) {
 ; IS__CGSCC____-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
 ; IS__CGSCC____-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
 ; IS__CGSCC____:       if.then:
-; IS__CGSCC____-NEXT:    tail call void @only_store(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR12:[0-9]+]]
+; IS__CGSCC____-NEXT:    tail call void @only_store(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR13:[0-9]+]]
 ; IS__CGSCC____-NEXT:    br label [[IF_END]]
 ; IS__CGSCC____:       if.end:
-; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree writeonly [[P]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree writeonly [[P]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    ret void
 ;
   %tobool = icmp eq i32 %c, 0
@@ -749,14 +761,14 @@ define internal void @test16_sub(i32* noalias %p, i32 %c1, i32 %c2) {
 ; IS__CGSCC____-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0
 ; IS__CGSCC____-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
 ; IS__CGSCC____:       if.then:
-; IS__CGSCC____-NEXT:    tail call void @only_store(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR12]]
-; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @only_store(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR13]]
+; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    br label [[IF_END]]
 ; IS__CGSCC____:       if.end:
 ; IS__CGSCC____-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C2]], 0
 ; IS__CGSCC____-NEXT:    br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]]
 ; IS__CGSCC____:       if.then2:
-; IS__CGSCC____-NEXT:    tail call void @only_store(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @only_store(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    br label [[IF_END3]]
 ; IS__CGSCC____:       if.end3:
 ; IS__CGSCC____-NEXT:    ret void
@@ -791,7 +803,7 @@ define void @test16_caller(i32* %p, i32 %c) {
 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@test16_caller
 ; IS__CGSCC____-SAME: (i32* nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR7]] {
-; IS__CGSCC____-NEXT:    tail call void @test16_sub(i32* noalias nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @test16_sub(i32* noalias nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    ret void
 ;
   tail call void @test16_sub(i32* %p, i32 %c, i32 %c)
@@ -840,10 +852,10 @@ define void @test17_caller(i32* noalias %p, i32 %c) {
 ; IS__CGSCC____-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
 ; IS__CGSCC____-NEXT:    br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]]
 ; IS__CGSCC____:       l1:
-; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree writeonly [[P]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree writeonly [[P]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    br label [[L3:%.*]]
 ; IS__CGSCC____:       l2:
-; IS__CGSCC____-NEXT:    tail call void @only_store(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @only_store(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    br label [[L3]]
 ; IS__CGSCC____:       l3:
 ; IS__CGSCC____-NEXT:    ret void
@@ -911,10 +923,10 @@ define void @test18_caller(i32* noalias %p, i32 %c) {
 ; IS__CGSCC____-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
 ; IS__CGSCC____-NEXT:    br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]]
 ; IS__CGSCC____:       l1:
-; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @make_alias(i32* nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    unreachable
 ; IS__CGSCC____:       l2:
-; IS__CGSCC____-NEXT:    tail call void @only_store(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR12]]
+; IS__CGSCC____-NEXT:    tail call void @only_store(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR13]]
 ; IS__CGSCC____-NEXT:    ret void
 ;
 entry:
@@ -953,7 +965,8 @@ l2:
 ; IS__CGSCC____: attributes #[[ATTR7]] = { nofree norecurse nosync nounwind willreturn writeonly }
 ; IS__CGSCC____: attributes #[[ATTR8]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
 ; IS__CGSCC____: attributes #[[ATTR9]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR10]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR10]] = { readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR11]] = { readonly willreturn }
-; IS__CGSCC____: attributes #[[ATTR12]] = { nounwind willreturn writeonly }
+; IS__CGSCC____: attributes #[[ATTR12]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR13]] = { nounwind willreturn writeonly }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll
index 20014b73fc8d..9d2c6208c6f2 100644
--- a/llvm/test/Transforms/Attributor/nocapture-1.ll
+++ b/llvm/test/Transforms/Attributor/nocapture-1.ll
@@ -623,7 +623,7 @@ define void @nocaptureLaunder(i8* %p) {
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureLaunder
 ; IS__CGSCC____-SAME: (i8* nocapture nofree [[P:%.*]]) #[[ATTR10:[0-9]+]] {
 ; IS__CGSCC____-NEXT:  entry:
-; IS__CGSCC____-NEXT:    [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR18]]
+; IS__CGSCC____-NEXT:    [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR20:[0-9]+]]
 ; IS__CGSCC____-NEXT:    store i8 42, i8* [[B]], align 1
 ; IS__CGSCC____-NEXT:    ret void
 ;
@@ -645,7 +645,7 @@ define void @captureLaunder(i8* %p) {
 ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@captureLaunder
 ; IS__CGSCC____-SAME: (i8* nofree [[P:%.*]]) #[[ATTR10]] {
-; IS__CGSCC____-NEXT:    [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR18]]
+; IS__CGSCC____-NEXT:    [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR20]]
 ; IS__CGSCC____-NEXT:    store i8* [[B]], i8** @g2, align 8
 ; IS__CGSCC____-NEXT:    ret void
 ;
@@ -659,7 +659,7 @@ define void @nocaptureStrip(i8* %p) {
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureStrip
 ; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR1]] {
 ; IS__TUNIT____-NEXT:  entry:
-; IS__TUNIT____-NEXT:    [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR17]]
+; IS__TUNIT____-NEXT:    [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR18:[0-9]+]]
 ; IS__TUNIT____-NEXT:    store i8 42, i8* [[B]], align 1
 ; IS__TUNIT____-NEXT:    ret void
 ;
@@ -682,7 +682,7 @@ define void @captureStrip(i8* %p) {
 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@captureStrip
 ; IS__TUNIT____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR1]] {
-; IS__TUNIT____-NEXT:    [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR17]]
+; IS__TUNIT____-NEXT:    [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR18]]
 ; IS__TUNIT____-NEXT:    store i8* [[B]], i8** @g3, align 8
 ; IS__TUNIT____-NEXT:    ret void
 ;
@@ -892,6 +892,7 @@ declare i8* @llvm.strip.invariant.group.p0i8(i8*)
 ; IS__TUNIT____: attributes #[[ATTR15]] = { nofree nounwind readnone willreturn }
 ; IS__TUNIT____: attributes #[[ATTR16]] = { nounwind }
 ; IS__TUNIT____: attributes #[[ATTR17]] = { willreturn }
+; IS__TUNIT____: attributes #[[ATTR18]] = { readnone willreturn }
 ;.
 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind willreturn writeonly }
@@ -911,6 +912,7 @@ declare i8* @llvm.strip.invariant.group.p0i8(i8*)
 ; IS__CGSCC____: attributes #[[ATTR15:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn }
 ; IS__CGSCC____: attributes #[[ATTR16:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
 ; IS__CGSCC____: attributes #[[ATTR17]] = { nounwind willreturn writeonly }
-; IS__CGSCC____: attributes #[[ATTR18]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR18]] = { readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR19]] = { nounwind }
+; IS__CGSCC____: attributes #[[ATTR20]] = { willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/nofree.ll b/llvm/test/Transforms/Attributor/nofree.ll
index ff345b81b25b..4273c69e7eaf 100644
--- a/llvm/test/Transforms/Attributor/nofree.ll
+++ b/llvm/test/Transforms/Attributor/nofree.ll
@@ -383,13 +383,13 @@ define void @nonnull_assume_pos(i8* %arg1, i8* %arg2, i8* %arg3, i8* %arg4) {
 ;
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@nonnull_assume_pos
 ; IS__TUNIT____-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]]) {
-; IS__TUNIT____-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR11]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
+; IS__TUNIT____-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR12:[0-9]+]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
 ; IS__TUNIT____-NEXT:    call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]])
 ; IS__TUNIT____-NEXT:    ret void
 ;
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@nonnull_assume_pos
 ; IS__CGSCC____-SAME: (i8* nofree [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* nofree [[ARG3:%.*]], i8* [[ARG4:%.*]]) {
-; IS__CGSCC____-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR12]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
+; IS__CGSCC____-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR13:[0-9]+]] [ "nofree"(i8* [[ARG1]]), "nofree"(i8* [[ARG3]]) ]
 ; IS__CGSCC____-NEXT:    call void @unknown(i8* nofree [[ARG1]], i8* [[ARG2]], i8* nofree [[ARG3]], i8* [[ARG4]])
 ; IS__CGSCC____-NEXT:    ret void
 ;
@@ -480,7 +480,8 @@ attributes #2 = { nobuiltin nounwind }
 ; IS__TUNIT____: attributes #[[ATTR8:[0-9]+]] = { nobuiltin nofree nounwind }
 ; IS__TUNIT____: attributes #[[ATTR9:[0-9]+]] = { nofree nosync nounwind willreturn }
 ; IS__TUNIT____: attributes #[[ATTR10:[0-9]+]] = { nounwind willreturn }
-; IS__TUNIT____: attributes #[[ATTR11]] = { willreturn }
+; IS__TUNIT____: attributes #[[ATTR11]] = { readnone willreturn }
+; IS__TUNIT____: attributes #[[ATTR12]] = { willreturn }
 ;.
 ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nounwind }
 ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { noinline nounwind uwtable }
@@ -494,7 +495,8 @@ attributes #2 = { nobuiltin nounwind }
 ; IS__CGSCC_OPM: attributes #[[ATTR9:[0-9]+]] = { nobuiltin nofree nounwind }
 ; IS__CGSCC_OPM: attributes #[[ATTR10:[0-9]+]] = { nofree nosync nounwind willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR11:[0-9]+]] = { nounwind willreturn }
-; IS__CGSCC_OPM: attributes #[[ATTR12]] = { willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR12]] = { readnone willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR13]] = { willreturn }
 ;.
 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nounwind }
 ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { noinline nounwind uwtable }
@@ -508,5 +510,6 @@ attributes #2 = { nobuiltin nounwind }
 ; IS__CGSCC_NPM: attributes #[[ATTR9:[0-9]+]] = { nobuiltin nofree nounwind }
 ; IS__CGSCC_NPM: attributes #[[ATTR10:[0-9]+]] = { nofree nosync nounwind willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR11:[0-9]+]] = { nounwind willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR12]] = { willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR12]] = { readnone willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR13]] = { willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/nosync.ll b/llvm/test/Transforms/Attributor/nosync.ll
index 1a287e0f1528..31128cc3342f 100644
--- a/llvm/test/Transforms/Attributor/nosync.ll
+++ b/llvm/test/Transforms/Attributor/nosync.ll
@@ -508,13 +508,13 @@ define float @cos_test2(float %x) {
 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@cos_test2
 ; IS__TUNIT____-SAME: (float [[X:%.*]]) #[[ATTR15]] {
-; IS__TUNIT____-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR17]]
+; IS__TUNIT____-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR19:[0-9]+]]
 ; IS__TUNIT____-NEXT:    ret float [[C]]
 ;
 ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@cos_test2
 ; IS__CGSCC____-SAME: (float [[X:%.*]]) #[[ATTR16:[0-9]+]] {
-; IS__CGSCC____-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR18]]
+; IS__CGSCC____-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR20:[0-9]+]]
 ; IS__CGSCC____-NEXT:    ret float [[C]]
 ;
   %c = call float @llvm.cos(float %x)
@@ -540,6 +540,7 @@ define float @cos_test2(float %x) {
 ; IS__TUNIT____: attributes #[[ATTR16:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
 ; IS__TUNIT____: attributes #[[ATTR17]] = { willreturn }
 ; IS__TUNIT____: attributes #[[ATTR18]] = { willreturn writeonly }
+; IS__TUNIT____: attributes #[[ATTR19]] = { readnone willreturn }
 ;.
 ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp uwtable willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind uwtable willreturn }
@@ -561,6 +562,7 @@ define float @cos_test2(float %x) {
 ; IS__CGSCC_OPM: attributes #[[ATTR17:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR18]] = { willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR19]] = { willreturn writeonly }
+; IS__CGSCC_OPM: attributes #[[ATTR20]] = { readnone willreturn }
 ;.
 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp uwtable willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind uwtable willreturn }
@@ -582,4 +584,5 @@ define float @cos_test2(float %x) {
 ; IS__CGSCC_NPM: attributes #[[ATTR17:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR18]] = { willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR19]] = { willreturn writeonly }
+; IS__CGSCC_NPM: attributes #[[ATTR20]] = { readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/potential.ll b/llvm/test/Transforms/Attributor/potential.ll
index 503a6b0eb281..e79501037418 100644
--- a/llvm/test/Transforms/Attributor/potential.ll
+++ b/llvm/test/Transforms/Attributor/potential.ll
@@ -923,10 +923,10 @@ define i1 @potential_test16(i1 %c0, i1 %c1) {
 ;.
 ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone }
-; IS__CGSCC_OPM: attributes #[[ATTR2]] = { willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR2]] = { readnone willreturn }
 ;.
 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR1]] = { willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR1]] = { readnone willreturn }
 ;.
 ; IS__TUNIT_OPM: [[RNG0]] = !{i32 1, i32 4}
 ; IS__TUNIT_OPM: [[RNG1]] = !{i32 3, i32 5}

diff  --git a/llvm/test/Transforms/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll
index 7228f5089a04..e7e7bfd869f5 100644
--- a/llvm/test/Transforms/Attributor/range.ll
+++ b/llvm/test/Transforms/Attributor/range.ll
@@ -2496,12 +2496,12 @@ declare void @barney(i32 signext, i32 signext)
 ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { readonly willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nounwind readnone }
-; IS__CGSCC_OPM: attributes #[[ATTR5]] = { willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR5]] = { readnone willreturn }
 ;.
 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR2]] = { readonly willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR3]] = { willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR3]] = { readnone willreturn }
 ;.
 ; IS__TUNIT_OPM: [[RNG0]] = !{i32 0, i32 10}
 ; IS__TUNIT_OPM: [[RNG1]] = !{i32 10, i32 100}

diff  --git a/llvm/test/Transforms/Attributor/readattrs.ll b/llvm/test/Transforms/Attributor/readattrs.ll
index 19f0ca5bf24c..9f28407c76c4 100644
--- a/llvm/test/Transforms/Attributor/readattrs.ll
+++ b/llvm/test/Transforms/Attributor/readattrs.ll
@@ -518,7 +518,7 @@ define i32 @read_only_constant_mem() {
 ; IS__CGSCC____: attributes #[[ATTR8]] = { argmemonly nofree norecurse nounwind willreturn }
 ; IS__CGSCC____: attributes #[[ATTR9]] = { readnone }
 ; IS__CGSCC____: attributes #[[ATTR10]] = { nounwind readonly }
-; IS__CGSCC____: attributes #[[ATTR11]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR11]] = { readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR12]] = { willreturn writeonly }
 ; IS__CGSCC____: attributes #[[ATTR13]] = { readonly willreturn }
 ; IS__CGSCC____: attributes #[[ATTR14]] = { nounwind }

diff  --git a/llvm/test/Transforms/Attributor/returned.ll b/llvm/test/Transforms/Attributor/returned.ll
index 575313008664..4b9f90850ae2 100644
--- a/llvm/test/Transforms/Attributor/returned.ll
+++ b/llvm/test/Transforms/Attributor/returned.ll
@@ -1617,7 +1617,7 @@ attributes #0 = { noinline nounwind uwtable }
 ; IS__CGSCC____: attributes #[[ATTR3]] = { noinline nounwind uwtable }
 ; IS__CGSCC____: attributes #[[ATTR4]] = { noreturn }
 ; IS__CGSCC____: attributes #[[ATTR5:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC____: attributes #[[ATTR6]] = { willreturn }
+; IS__CGSCC____: attributes #[[ATTR6]] = { readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind readnone }
 ; IS__CGSCC____: attributes #[[ATTR8]] = { nounwind readnone }
 ; IS__CGSCC____: attributes #[[ATTR9]] = { nounwind }

diff  --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll
index c2ae25887ccc..41fa16c0284a 100644
--- a/llvm/test/Transforms/Attributor/value-simplify.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify.ll
@@ -399,15 +399,15 @@ define i32* @complicated_args_preallocated() {
 ; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind willreturn
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_preallocated
 ; IS__CGSCC_OPM-SAME: () #[[ATTR0:[0-9]+]] {
-; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR5]]
-; IS__CGSCC_OPM-NEXT:    [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR6:[0-9]+]] [ "preallocated"(token [[C]]) ]
+; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR6:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR7:[0-9]+]] [ "preallocated"(token [[C]]) ]
 ; IS__CGSCC_OPM-NEXT:    ret i32* [[CALL]]
 ;
 ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_preallocated
 ; IS__CGSCC_NPM-SAME: () #[[ATTR0:[0-9]+]] {
-; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR4]]
-; IS__CGSCC_NPM-NEXT:    [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR5:[0-9]+]] [ "preallocated"(token [[C]]) ]
+; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR5:[0-9]+]]
+; IS__CGSCC_NPM-NEXT:    [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR6:[0-9]+]] [ "preallocated"(token [[C]]) ]
 ; IS__CGSCC_NPM-NEXT:    ret i32* [[CALL]]
 ;
   %c = call token @llvm.call.preallocated.setup(i32 1)
@@ -564,13 +564,13 @@ define i8* @complicated_args_byval2() {
 ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_byval2
 ; IS__CGSCC_OPM-SAME: () #[[ATTR3]] {
-; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = call i8* @test_byval2() #[[ATTR7:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = call i8* @test_byval2() #[[ATTR8:[0-9]+]]
 ; IS__CGSCC_OPM-NEXT:    ret i8* [[C]]
 ;
 ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_byval2
 ; IS__CGSCC_NPM-SAME: () #[[ATTR3]] {
-; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = call i8* @test_byval2() #[[ATTR6:[0-9]+]]
+; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = call i8* @test_byval2() #[[ATTR7:[0-9]+]]
 ; IS__CGSCC_NPM-NEXT:    ret i8* [[C]]
 ;
   %c = call i8* @test_byval2(%struct.X* @S)
@@ -827,15 +827,17 @@ define i1 @icmp() {
 ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
 ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind readonly willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind writeonly }
-; IS__CGSCC_OPM: attributes #[[ATTR5]] = { willreturn }
-; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nounwind readnone willreturn }
-; IS__CGSCC_OPM: attributes #[[ATTR7]] = { readonly willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR5]] = { readnone willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR6]] = { willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nounwind readnone willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR8]] = { readonly willreturn }
 ;.
 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
 ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind readonly willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR4]] = { willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR5]] = { nounwind readnone willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR6]] = { readonly willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR4]] = { readnone willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR5]] = { willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nounwind readnone willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR7]] = { readonly willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/willreturn.ll b/llvm/test/Transforms/Attributor/willreturn.ll
index e6b2f2060b7f..658726c61156 100644
--- a/llvm/test/Transforms/Attributor/willreturn.ll
+++ b/llvm/test/Transforms/Attributor/willreturn.ll
@@ -72,9 +72,9 @@ define i32 @fib(i32 %0) local_unnamed_addr #0 {
 ; IS__CGSCC_OPM-NEXT:    br i1 [[TMP2]], label [[TMP9:%.*]], label [[TMP3:%.*]]
 ; IS__CGSCC_OPM:       3:
 ; IS__CGSCC_OPM-NEXT:    [[TMP4:%.*]] = add nsw i32 [[TMP0]], -1
-; IS__CGSCC_OPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR19:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR26:[0-9]+]]
 ; IS__CGSCC_OPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], -2
-; IS__CGSCC_OPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR19]]
+; IS__CGSCC_OPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR26]]
 ; IS__CGSCC_OPM-NEXT:    [[TMP8:%.*]] = add nsw i32 [[TMP7]], [[TMP5]]
 ; IS__CGSCC_OPM-NEXT:    ret i32 [[TMP8]]
 ; IS__CGSCC_OPM:       9:
@@ -87,9 +87,9 @@ define i32 @fib(i32 %0) local_unnamed_addr #0 {
 ; IS__CGSCC_NPM-NEXT:    br i1 [[TMP2]], label [[TMP9:%.*]], label [[TMP3:%.*]]
 ; IS__CGSCC_NPM:       3:
 ; IS__CGSCC_NPM-NEXT:    [[TMP4:%.*]] = add nsw i32 [[TMP0]], -1
-; IS__CGSCC_NPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR21:[0-9]+]]
+; IS__CGSCC_NPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR28:[0-9]+]]
 ; IS__CGSCC_NPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], -2
-; IS__CGSCC_NPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR21]]
+; IS__CGSCC_NPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR28]]
 ; IS__CGSCC_NPM-NEXT:    [[TMP8:%.*]] = add nsw i32 [[TMP7]], [[TMP5]]
 ; IS__CGSCC_NPM-NEXT:    ret i32 [[TMP8]]
 ; IS__CGSCC_NPM:       9:
@@ -285,7 +285,7 @@ define void @mutual_recursion1(i1 %c) #0 {
 ; IS__TUNIT_OPM-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
 ; IS__TUNIT_OPM:       rec:
 ; IS__TUNIT_OPM-NEXT:    call void @sink() #[[ATTR11:[0-9]+]]
-; IS__TUNIT_OPM-NEXT:    call void @mutual_recursion2(i1 [[C]]) #[[ATTR16:[0-9]+]]
+; IS__TUNIT_OPM-NEXT:    call void @mutual_recursion2(i1 [[C]]) #[[ATTR23:[0-9]+]]
 ; IS__TUNIT_OPM-NEXT:    br label [[END]]
 ; IS__TUNIT_OPM:       end:
 ; IS__TUNIT_OPM-NEXT:    ret void
@@ -296,7 +296,7 @@ define void @mutual_recursion1(i1 %c) #0 {
 ; IS__TUNIT_NPM-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
 ; IS__TUNIT_NPM:       rec:
 ; IS__TUNIT_NPM-NEXT:    call void @sink() #[[ATTR11:[0-9]+]]
-; IS__TUNIT_NPM-NEXT:    call void @mutual_recursion2(i1 noundef [[C]]) #[[ATTR18:[0-9]+]]
+; IS__TUNIT_NPM-NEXT:    call void @mutual_recursion2(i1 noundef [[C]]) #[[ATTR25:[0-9]+]]
 ; IS__TUNIT_NPM-NEXT:    br label [[END]]
 ; IS__TUNIT_NPM:       end:
 ; IS__TUNIT_NPM-NEXT:    ret void
@@ -307,7 +307,7 @@ define void @mutual_recursion1(i1 %c) #0 {
 ; IS__CGSCC_OPM-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
 ; IS__CGSCC_OPM:       rec:
 ; IS__CGSCC_OPM-NEXT:    call void @sink() #[[ATTR14:[0-9]+]]
-; IS__CGSCC_OPM-NEXT:    call void @mutual_recursion2(i1 [[C]]) #[[ATTR20:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    call void @mutual_recursion2(i1 [[C]]) #[[ATTR27:[0-9]+]]
 ; IS__CGSCC_OPM-NEXT:    br label [[END]]
 ; IS__CGSCC_OPM:       end:
 ; IS__CGSCC_OPM-NEXT:    ret void
@@ -318,7 +318,7 @@ define void @mutual_recursion1(i1 %c) #0 {
 ; IS__CGSCC_NPM-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
 ; IS__CGSCC_NPM:       rec:
 ; IS__CGSCC_NPM-NEXT:    call void @sink() #[[ATTR14:[0-9]+]]
-; IS__CGSCC_NPM-NEXT:    call void @mutual_recursion2(i1 noundef [[C]]) #[[ATTR22:[0-9]+]]
+; IS__CGSCC_NPM-NEXT:    call void @mutual_recursion2(i1 noundef [[C]]) #[[ATTR29:[0-9]+]]
 ; IS__CGSCC_NPM-NEXT:    br label [[END]]
 ; IS__CGSCC_NPM:       end:
 ; IS__CGSCC_NPM-NEXT:    ret void
@@ -337,25 +337,25 @@ define void @mutual_recursion2(i1 %c) #0 {
 ; IS__TUNIT_OPM: Function Attrs: nofree noinline nosync nounwind uwtable
 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@mutual_recursion2
 ; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
-; IS__TUNIT_OPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR16]]
+; IS__TUNIT_OPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR23]]
 ; IS__TUNIT_OPM-NEXT:    ret void
 ;
 ; IS__TUNIT_NPM: Function Attrs: nofree noinline nosync nounwind uwtable
 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@mutual_recursion2
 ; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
-; IS__TUNIT_NPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR18]]
+; IS__TUNIT_NPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR25]]
 ; IS__TUNIT_NPM-NEXT:    ret void
 ;
 ; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind uwtable
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@mutual_recursion2
 ; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR4]] {
-; IS__CGSCC_OPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR20]]
+; IS__CGSCC_OPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR27]]
 ; IS__CGSCC_OPM-NEXT:    ret void
 ;
 ; IS__CGSCC_NPM: Function Attrs: nofree noinline nosync nounwind uwtable
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion2
 ; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR4]] {
-; IS__CGSCC_NPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR22]]
+; IS__CGSCC_NPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR29]]
 ; IS__CGSCC_NPM-NEXT:    ret void
 ;
   call void @mutual_recursion1(i1 %c)
@@ -478,25 +478,25 @@ define float @call_floor2(float %a) #0 {
 ; IS__TUNIT_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@call_floor2
 ; IS__TUNIT_OPM-SAME: (float [[A:%.*]]) #[[ATTR0]] {
-; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR17:[0-9]+]]
+; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR24:[0-9]+]]
 ; IS__TUNIT_OPM-NEXT:    ret float [[C]]
 ;
 ; IS__TUNIT_NPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@call_floor2
 ; IS__TUNIT_NPM-SAME: (float [[A:%.*]]) #[[ATTR0]] {
-; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR19:[0-9]+]]
+; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR26:[0-9]+]]
 ; IS__TUNIT_NPM-NEXT:    ret float [[C]]
 ;
 ; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@call_floor2
 ; IS__CGSCC_OPM-SAME: (float [[A:%.*]]) #[[ATTR9:[0-9]+]] {
-; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR21:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR28:[0-9]+]]
 ; IS__CGSCC_OPM-NEXT:    ret float [[C]]
 ;
 ; IS__CGSCC_NPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@call_floor2
 ; IS__CGSCC_NPM-SAME: (float [[A:%.*]]) #[[ATTR9:[0-9]+]] {
-; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR23:[0-9]+]]
+; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR30:[0-9]+]]
 ; IS__CGSCC_NPM-NEXT:    ret float [[C]]
 ;
   %c = tail call float @llvm.floor.f32(float %a)
@@ -516,25 +516,25 @@ define void @call_maybe_noreturn() #0 {
 ; IS__TUNIT_OPM: Function Attrs: noinline nounwind uwtable
 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@call_maybe_noreturn
 ; IS__TUNIT_OPM-SAME: () #[[ATTR6]] {
-; IS__TUNIT_OPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR18:[0-9]+]]
+; IS__TUNIT_OPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR25:[0-9]+]]
 ; IS__TUNIT_OPM-NEXT:    ret void
 ;
 ; IS__TUNIT_NPM: Function Attrs: noinline nounwind uwtable
 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@call_maybe_noreturn
 ; IS__TUNIT_NPM-SAME: () #[[ATTR6]] {
-; IS__TUNIT_NPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR20:[0-9]+]]
+; IS__TUNIT_NPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR27:[0-9]+]]
 ; IS__TUNIT_NPM-NEXT:    ret void
 ;
 ; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@call_maybe_noreturn
 ; IS__CGSCC_OPM-SAME: () #[[ATTR7]] {
-; IS__CGSCC_OPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR22:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR29:[0-9]+]]
 ; IS__CGSCC_OPM-NEXT:    ret void
 ;
 ; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@call_maybe_noreturn
 ; IS__CGSCC_NPM-SAME: () #[[ATTR7]] {
-; IS__CGSCC_NPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR24:[0-9]+]]
+; IS__CGSCC_NPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR31:[0-9]+]]
 ; IS__CGSCC_NPM-NEXT:    ret void
 ;
   tail call void @maybe_noreturn()
@@ -553,25 +553,25 @@ define void @f1() #0 {
 ; IS__TUNIT_OPM: Function Attrs: noinline nounwind uwtable willreturn
 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f1
 ; IS__TUNIT_OPM-SAME: () #[[ATTR9:[0-9]+]] {
-; IS__TUNIT_OPM-NEXT:    tail call void @will_return() #[[ATTR17]]
+; IS__TUNIT_OPM-NEXT:    tail call void @will_return() #[[ATTR26:[0-9]+]]
 ; IS__TUNIT_OPM-NEXT:    ret void
 ;
 ; IS__TUNIT_NPM: Function Attrs: noinline nounwind uwtable willreturn
 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f1
 ; IS__TUNIT_NPM-SAME: () #[[ATTR9:[0-9]+]] {
-; IS__TUNIT_NPM-NEXT:    tail call void @will_return() #[[ATTR19]]
+; IS__TUNIT_NPM-NEXT:    tail call void @will_return() #[[ATTR28:[0-9]+]]
 ; IS__TUNIT_NPM-NEXT:    ret void
 ;
 ; IS__CGSCC_OPM: Function Attrs: noinline norecurse nounwind uwtable willreturn
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f1
 ; IS__CGSCC_OPM-SAME: () #[[ATTR11:[0-9]+]] {
-; IS__CGSCC_OPM-NEXT:    tail call void @will_return() #[[ATTR21]]
+; IS__CGSCC_OPM-NEXT:    tail call void @will_return() #[[ATTR30:[0-9]+]]
 ; IS__CGSCC_OPM-NEXT:    ret void
 ;
 ; IS__CGSCC_NPM: Function Attrs: noinline norecurse nounwind uwtable willreturn
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f1
 ; IS__CGSCC_NPM-SAME: () #[[ATTR11:[0-9]+]] {
-; IS__CGSCC_NPM-NEXT:    tail call void @will_return() #[[ATTR23]]
+; IS__CGSCC_NPM-NEXT:    tail call void @will_return() #[[ATTR32:[0-9]+]]
 ; IS__CGSCC_NPM-NEXT:    ret void
 ;
   tail call void @will_return()
@@ -640,7 +640,7 @@ define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
 ; IS__TUNIT_OPM: Function Attrs: nounwind willreturn
 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@invoke_test
 ; IS__TUNIT_OPM-SAME: () #[[ATTR11]] personality i32 (...)* @__gxx_personality_v0 {
-; IS__TUNIT_OPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR17]]
+; IS__TUNIT_OPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR26]]
 ; IS__TUNIT_OPM-NEXT:    to label [[N:%.*]] unwind label [[F:%.*]]
 ; IS__TUNIT_OPM:       N:
 ; IS__TUNIT_OPM-NEXT:    ret void
@@ -652,7 +652,7 @@ define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
 ; IS__TUNIT_NPM: Function Attrs: nounwind willreturn
 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@invoke_test
 ; IS__TUNIT_NPM-SAME: () #[[ATTR11]] personality i32 (...)* @__gxx_personality_v0 {
-; IS__TUNIT_NPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR19]]
+; IS__TUNIT_NPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR28]]
 ; IS__TUNIT_NPM-NEXT:    to label [[N:%.*]] unwind label [[F:%.*]]
 ; IS__TUNIT_NPM:       N:
 ; IS__TUNIT_NPM-NEXT:    ret void
@@ -664,7 +664,7 @@ define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
 ; IS__CGSCC_OPM: Function Attrs: nounwind willreturn
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@invoke_test
 ; IS__CGSCC_OPM-SAME: () #[[ATTR14]] personality i32 (...)* @__gxx_personality_v0 {
-; IS__CGSCC_OPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR21]]
+; IS__CGSCC_OPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR30]]
 ; IS__CGSCC_OPM-NEXT:    to label [[N:%.*]] unwind label [[F:%.*]]
 ; IS__CGSCC_OPM:       N:
 ; IS__CGSCC_OPM-NEXT:    ret void
@@ -676,7 +676,7 @@ define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
 ; IS__CGSCC_NPM: Function Attrs: nounwind willreturn
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@invoke_test
 ; IS__CGSCC_NPM-SAME: () #[[ATTR14]] personality i32 (...)* @__gxx_personality_v0 {
-; IS__CGSCC_NPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR23]]
+; IS__CGSCC_NPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR32]]
 ; IS__CGSCC_NPM-NEXT:    to label [[N:%.*]] unwind label [[F:%.*]]
 ; IS__CGSCC_NPM:       N:
 ; IS__CGSCC_NPM-NEXT:    ret void
@@ -1056,7 +1056,7 @@ define void @unreachable_exit_positive1() #0 {
 ; IS__TUNIT_OPM: Function Attrs: noinline nounwind uwtable willreturn
 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@unreachable_exit_positive1
 ; IS__TUNIT_OPM-SAME: () #[[ATTR9]] {
-; IS__TUNIT_OPM-NEXT:    tail call void @will_return() #[[ATTR17]]
+; IS__TUNIT_OPM-NEXT:    tail call void @will_return() #[[ATTR26]]
 ; IS__TUNIT_OPM-NEXT:    ret void
 ; IS__TUNIT_OPM:       unreachable_label:
 ; IS__TUNIT_OPM-NEXT:    unreachable
@@ -1064,7 +1064,7 @@ define void @unreachable_exit_positive1() #0 {
 ; IS__TUNIT_NPM: Function Attrs: noinline nounwind uwtable willreturn
 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unreachable_exit_positive1
 ; IS__TUNIT_NPM-SAME: () #[[ATTR9]] {
-; IS__TUNIT_NPM-NEXT:    tail call void @will_return() #[[ATTR19]]
+; IS__TUNIT_NPM-NEXT:    tail call void @will_return() #[[ATTR28]]
 ; IS__TUNIT_NPM-NEXT:    ret void
 ; IS__TUNIT_NPM:       unreachable_label:
 ; IS__TUNIT_NPM-NEXT:    unreachable
@@ -1072,7 +1072,7 @@ define void @unreachable_exit_positive1() #0 {
 ; IS__CGSCC_OPM: Function Attrs: noinline norecurse nounwind uwtable willreturn
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@unreachable_exit_positive1
 ; IS__CGSCC_OPM-SAME: () #[[ATTR11]] {
-; IS__CGSCC_OPM-NEXT:    tail call void @will_return() #[[ATTR21]]
+; IS__CGSCC_OPM-NEXT:    tail call void @will_return() #[[ATTR30]]
 ; IS__CGSCC_OPM-NEXT:    ret void
 ; IS__CGSCC_OPM:       unreachable_label:
 ; IS__CGSCC_OPM-NEXT:    unreachable
@@ -1080,7 +1080,7 @@ define void @unreachable_exit_positive1() #0 {
 ; IS__CGSCC_NPM: Function Attrs: noinline norecurse nounwind uwtable willreturn
 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@unreachable_exit_positive1
 ; IS__CGSCC_NPM-SAME: () #[[ATTR11]] {
-; IS__CGSCC_NPM-NEXT:    tail call void @will_return() #[[ATTR23]]
+; IS__CGSCC_NPM-NEXT:    tail call void @will_return() #[[ATTR32]]
 ; IS__CGSCC_NPM-NEXT:    ret void
 ; IS__CGSCC_NPM:       unreachable_label:
 ; IS__CGSCC_NPM-NEXT:    unreachable
@@ -2012,7 +2012,7 @@ define void @non_loop_cycle(i32 %n) {
 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@non_loop_cycle
 ; IS__CGSCC_OPM-SAME: (i32 [[N:%.*]]) #[[ATTR18]] {
 ; IS__CGSCC_OPM-NEXT:  entry:
-; IS__CGSCC_OPM-NEXT:    [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR23:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR31:[0-9]+]]
 ; IS__CGSCC_OPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5
 ; IS__CGSCC_OPM-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
 ; IS__CGSCC_OPM:       if.then:
@@ -2020,7 +2020,7 @@ define void @non_loop_cycle(i32 %n) {
 ; IS__CGSCC_OPM:       if.else:
 ; IS__CGSCC_OPM-NEXT:    br label [[ENTRY2:%.*]]
 ; IS__CGSCC_OPM:       entry1:
-; IS__CGSCC_OPM-NEXT:    [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR23]]
+; IS__CGSCC_OPM-NEXT:    [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR31]]
 ; IS__CGSCC_OPM-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5
 ; IS__CGSCC_OPM-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]]
 ; IS__CGSCC_OPM:       if.then3:
@@ -2028,7 +2028,7 @@ define void @non_loop_cycle(i32 %n) {
 ; IS__CGSCC_OPM:       if.else4:
 ; IS__CGSCC_OPM-NEXT:    br label [[ENTRY2]]
 ; IS__CGSCC_OPM:       entry2:
-; IS__CGSCC_OPM-NEXT:    [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR23]]
+; IS__CGSCC_OPM-NEXT:    [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR31]]
 ; IS__CGSCC_OPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5
 ; IS__CGSCC_OPM-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]]
 ; IS__CGSCC_OPM:       if.then7:
@@ -2105,6 +2105,169 @@ exit:                                             ; preds = %if.then7, %if.then3
   ret void
 }
 
+declare void @unknown()
+declare void @readonly() readonly
+declare void @readnone() readnone
+declare void @unknown_mustprogress() mustprogress
+declare void @readonly_mustprogress() readonly mustprogress
+
+define void @willreturn_mustprogress_caller_1() mustprogress {
+; IS__TUNIT_OPM: Function Attrs: mustprogress
+; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
+; IS__TUNIT_OPM-SAME: () #[[ATTR18:[0-9]+]] {
+; IS__TUNIT_OPM-NEXT:    call void @unknown()
+; IS__TUNIT_OPM-NEXT:    ret void
+;
+; IS__TUNIT_NPM: Function Attrs: mustprogress
+; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
+; IS__TUNIT_NPM-SAME: () #[[ATTR20:[0-9]+]] {
+; IS__TUNIT_NPM-NEXT:    call void @unknown()
+; IS__TUNIT_NPM-NEXT:    ret void
+;
+; IS__CGSCC_OPM: Function Attrs: mustprogress
+; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
+; IS__CGSCC_OPM-SAME: () #[[ATTR21:[0-9]+]] {
+; IS__CGSCC_OPM-NEXT:    call void @unknown()
+; IS__CGSCC_OPM-NEXT:    ret void
+;
+; IS__CGSCC_NPM: Function Attrs: mustprogress
+; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
+; IS__CGSCC_NPM-SAME: () #[[ATTR23:[0-9]+]] {
+; IS__CGSCC_NPM-NEXT:    call void @unknown()
+; IS__CGSCC_NPM-NEXT:    ret void
+;
+  call void @unknown()
+  ret void
+}
+define void @willreturn_mustprogress_caller_2() mustprogress {
+; IS__TUNIT_OPM: Function Attrs: readonly willreturn mustprogress
+; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
+; IS__TUNIT_OPM-SAME: () #[[ATTR20:[0-9]+]] {
+; IS__TUNIT_OPM-NEXT:    call void @readonly() #[[ATTR16:[0-9]+]]
+; IS__TUNIT_OPM-NEXT:    ret void
+;
+; IS__TUNIT_NPM: Function Attrs: readonly willreturn mustprogress
+; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
+; IS__TUNIT_NPM-SAME: () #[[ATTR22:[0-9]+]] {
+; IS__TUNIT_NPM-NEXT:    call void @readonly() #[[ATTR18:[0-9]+]]
+; IS__TUNIT_NPM-NEXT:    ret void
+;
+; IS__CGSCC_OPM: Function Attrs: readonly willreturn mustprogress
+; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
+; IS__CGSCC_OPM-SAME: () #[[ATTR23:[0-9]+]] {
+; IS__CGSCC_OPM-NEXT:    call void @readonly() #[[ATTR19:[0-9]+]]
+; IS__CGSCC_OPM-NEXT:    ret void
+;
+; IS__CGSCC_NPM: Function Attrs: readonly willreturn mustprogress
+; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
+; IS__CGSCC_NPM-SAME: () #[[ATTR25:[0-9]+]] {
+; IS__CGSCC_NPM-NEXT:    call void @readonly() #[[ATTR21:[0-9]+]]
+; IS__CGSCC_NPM-NEXT:    ret void
+;
+  call void @readonly()
+  ret void
+}
+define void @willreturn_mustprogress_caller_3() mustprogress {
+; IS__TUNIT_OPM: Function Attrs: nosync readnone willreturn mustprogress
+; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
+; IS__TUNIT_OPM-SAME: () #[[ATTR21:[0-9]+]] {
+; IS__TUNIT_OPM-NEXT:    call void @readnone()
+; IS__TUNIT_OPM-NEXT:    ret void
+;
+; IS__TUNIT_NPM: Function Attrs: nosync readnone willreturn mustprogress
+; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
+; IS__TUNIT_NPM-SAME: () #[[ATTR23:[0-9]+]] {
+; IS__TUNIT_NPM-NEXT:    call void @readnone()
+; IS__TUNIT_NPM-NEXT:    ret void
+;
+; IS__CGSCC_OPM: Function Attrs: nosync readnone willreturn mustprogress
+; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
+; IS__CGSCC_OPM-SAME: () #[[ATTR24:[0-9]+]] {
+; IS__CGSCC_OPM-NEXT:    call void @readnone()
+; IS__CGSCC_OPM-NEXT:    ret void
+;
+; IS__CGSCC_NPM: Function Attrs: nosync readnone willreturn mustprogress
+; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
+; IS__CGSCC_NPM-SAME: () #[[ATTR26:[0-9]+]] {
+; IS__CGSCC_NPM-NEXT:    call void @readnone()
+; IS__CGSCC_NPM-NEXT:    ret void
+;
+  call void @readnone()
+  ret void
+}
+define void @willreturn_mustprogress_callee_1() {
+; CHECK-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_1() {
+; CHECK-NEXT:    call void @unknown_mustprogress()
+; CHECK-NEXT:    ret void
+;
+  call void @unknown_mustprogress()
+  ret void
+}
+define void @willreturn_mustprogress_callee_2() {
+; IS__TUNIT_OPM: Function Attrs: readonly willreturn
+; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
+; IS__TUNIT_OPM-SAME: () #[[ATTR22:[0-9]+]] {
+; IS__TUNIT_OPM-NEXT:    call void @readonly_mustprogress() #[[ATTR22]]
+; IS__TUNIT_OPM-NEXT:    ret void
+;
+; IS__TUNIT_NPM: Function Attrs: readonly willreturn
+; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
+; IS__TUNIT_NPM-SAME: () #[[ATTR24:[0-9]+]] {
+; IS__TUNIT_NPM-NEXT:    call void @readonly_mustprogress() #[[ATTR24]]
+; IS__TUNIT_NPM-NEXT:    ret void
+;
+; IS__CGSCC_OPM: Function Attrs: readonly willreturn
+; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
+; IS__CGSCC_OPM-SAME: () #[[ATTR25:[0-9]+]] {
+; IS__CGSCC_OPM-NEXT:    call void @readonly_mustprogress() #[[ATTR25]]
+; IS__CGSCC_OPM-NEXT:    ret void
+;
+; IS__CGSCC_NPM: Function Attrs: readonly willreturn
+; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
+; IS__CGSCC_NPM-SAME: () #[[ATTR27:[0-9]+]] {
+; IS__CGSCC_NPM-NEXT:    call void @readonly_mustprogress() #[[ATTR27]]
+; IS__CGSCC_NPM-NEXT:    ret void
+;
+  call void @readonly_mustprogress()
+  ret void
+}
+define void @willreturn_mustprogress_callee_3() {
+; CHECK-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_3() {
+; CHECK-NEXT:    call void @willreturn_mustprogress_callee_1()
+; CHECK-NEXT:    ret void
+;
+  call void @willreturn_mustprogress_callee_1()
+  ret void
+}
+define void @willreturn_mustprogress_callee_4() {
+; IS__TUNIT_OPM: Function Attrs: readonly willreturn
+; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
+; IS__TUNIT_OPM-SAME: () #[[ATTR22]] {
+; IS__TUNIT_OPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR22]]
+; IS__TUNIT_OPM-NEXT:    ret void
+;
+; IS__TUNIT_NPM: Function Attrs: readonly willreturn
+; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
+; IS__TUNIT_NPM-SAME: () #[[ATTR24]] {
+; IS__TUNIT_NPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR24]]
+; IS__TUNIT_NPM-NEXT:    ret void
+;
+; IS__CGSCC_OPM: Function Attrs: readonly willreturn
+; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
+; IS__CGSCC_OPM-SAME: () #[[ATTR25]] {
+; IS__CGSCC_OPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR25]]
+; IS__CGSCC_OPM-NEXT:    ret void
+;
+; IS__CGSCC_NPM: Function Attrs: readonly willreturn
+; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
+; IS__CGSCC_NPM-SAME: () #[[ATTR27]] {
+; IS__CGSCC_NPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR27]]
+; IS__CGSCC_NPM-NEXT:    ret void
+;
+  call void @willreturn_mustprogress_callee_2()
+  ret void
+}
+
 attributes #0 = { nounwind uwtable noinline }
 attributes #1 = { uwtable noinline }
 ;.
@@ -2124,9 +2287,17 @@ attributes #1 = { uwtable noinline }
 ; IS__TUNIT_OPM: attributes #[[ATTR13]] = { nofree noinline noreturn nosync nounwind readnone uwtable }
 ; IS__TUNIT_OPM: attributes #[[ATTR14:[0-9]+]] = { noreturn nounwind }
 ; IS__TUNIT_OPM: attributes #[[ATTR15]] = { nofree nosync nounwind readnone }
-; IS__TUNIT_OPM: attributes #[[ATTR16]] = { nofree nosync nounwind }
-; IS__TUNIT_OPM: attributes #[[ATTR17]] = { willreturn }
-; IS__TUNIT_OPM: attributes #[[ATTR18]] = { nounwind }
+; IS__TUNIT_OPM: attributes #[[ATTR16]] = { readonly }
+; IS__TUNIT_OPM: attributes #[[ATTR17:[0-9]+]] = { readnone }
+; IS__TUNIT_OPM: attributes #[[ATTR18]] = { mustprogress }
+; IS__TUNIT_OPM: attributes #[[ATTR19:[0-9]+]] = { readonly mustprogress }
+; IS__TUNIT_OPM: attributes #[[ATTR20]] = { readonly willreturn mustprogress }
+; IS__TUNIT_OPM: attributes #[[ATTR21]] = { nosync readnone willreturn mustprogress }
+; IS__TUNIT_OPM: attributes #[[ATTR22]] = { readonly willreturn }
+; IS__TUNIT_OPM: attributes #[[ATTR23]] = { nofree nosync nounwind }
+; IS__TUNIT_OPM: attributes #[[ATTR24]] = { readnone willreturn }
+; IS__TUNIT_OPM: attributes #[[ATTR25]] = { nounwind }
+; IS__TUNIT_OPM: attributes #[[ATTR26]] = { willreturn }
 ;.
 ; IS__TUNIT_NPM: attributes #[[ATTR0]] = { nofree noinline nosync nounwind readnone uwtable willreturn }
 ; IS__TUNIT_NPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable }
@@ -2146,9 +2317,17 @@ attributes #1 = { uwtable noinline }
 ; IS__TUNIT_NPM: attributes #[[ATTR15:[0-9]+]] = { noreturn nounwind }
 ; IS__TUNIT_NPM: attributes #[[ATTR16]] = { nofree nosync nounwind readnone }
 ; IS__TUNIT_NPM: attributes #[[ATTR17]] = { nofree nosync nounwind readnone willreturn }
-; IS__TUNIT_NPM: attributes #[[ATTR18]] = { nofree nosync nounwind }
-; IS__TUNIT_NPM: attributes #[[ATTR19]] = { willreturn }
-; IS__TUNIT_NPM: attributes #[[ATTR20]] = { nounwind }
+; IS__TUNIT_NPM: attributes #[[ATTR18]] = { readonly }
+; IS__TUNIT_NPM: attributes #[[ATTR19:[0-9]+]] = { readnone }
+; IS__TUNIT_NPM: attributes #[[ATTR20]] = { mustprogress }
+; IS__TUNIT_NPM: attributes #[[ATTR21:[0-9]+]] = { readonly mustprogress }
+; IS__TUNIT_NPM: attributes #[[ATTR22]] = { readonly willreturn mustprogress }
+; IS__TUNIT_NPM: attributes #[[ATTR23]] = { nosync readnone willreturn mustprogress }
+; IS__TUNIT_NPM: attributes #[[ATTR24]] = { readonly willreturn }
+; IS__TUNIT_NPM: attributes #[[ATTR25]] = { nofree nosync nounwind }
+; IS__TUNIT_NPM: attributes #[[ATTR26]] = { readnone willreturn }
+; IS__TUNIT_NPM: attributes #[[ATTR27]] = { nounwind }
+; IS__TUNIT_NPM: attributes #[[ATTR28]] = { willreturn }
 ;.
 ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn }
 ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable }
@@ -2169,11 +2348,19 @@ attributes #1 = { uwtable noinline }
 ; IS__CGSCC_OPM: attributes #[[ATTR16]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable }
 ; IS__CGSCC_OPM: attributes #[[ATTR17:[0-9]+]] = { noreturn nounwind }
 ; IS__CGSCC_OPM: attributes #[[ATTR18]] = { nofree norecurse nosync nounwind readnone }
-; IS__CGSCC_OPM: attributes #[[ATTR19]] = { nofree nosync nounwind readnone }
-; IS__CGSCC_OPM: attributes #[[ATTR20]] = { nofree nosync nounwind }
-; IS__CGSCC_OPM: attributes #[[ATTR21]] = { willreturn }
-; IS__CGSCC_OPM: attributes #[[ATTR22]] = { nounwind }
-; IS__CGSCC_OPM: attributes #[[ATTR23]] = { nounwind readnone }
+; IS__CGSCC_OPM: attributes #[[ATTR19]] = { readonly }
+; IS__CGSCC_OPM: attributes #[[ATTR20:[0-9]+]] = { readnone }
+; IS__CGSCC_OPM: attributes #[[ATTR21]] = { mustprogress }
+; IS__CGSCC_OPM: attributes #[[ATTR22:[0-9]+]] = { readonly mustprogress }
+; IS__CGSCC_OPM: attributes #[[ATTR23]] = { readonly willreturn mustprogress }
+; IS__CGSCC_OPM: attributes #[[ATTR24]] = { nosync readnone willreturn mustprogress }
+; IS__CGSCC_OPM: attributes #[[ATTR25]] = { readonly willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR26]] = { nofree nosync nounwind readnone }
+; IS__CGSCC_OPM: attributes #[[ATTR27]] = { nofree nosync nounwind }
+; IS__CGSCC_OPM: attributes #[[ATTR28]] = { readnone willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR29]] = { nounwind }
+; IS__CGSCC_OPM: attributes #[[ATTR30]] = { willreturn }
+; IS__CGSCC_OPM: attributes #[[ATTR31]] = { nounwind readnone }
 ;.
 ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn }
 ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable }
@@ -2196,8 +2383,16 @@ attributes #1 = { uwtable noinline }
 ; IS__CGSCC_NPM: attributes #[[ATTR18:[0-9]+]] = { noreturn nounwind }
 ; IS__CGSCC_NPM: attributes #[[ATTR19]] = { nofree norecurse nosync nounwind readnone }
 ; IS__CGSCC_NPM: attributes #[[ATTR20]] = { nofree norecurse nosync nounwind readnone willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR21]] = { nofree nosync nounwind readnone }
-; IS__CGSCC_NPM: attributes #[[ATTR22]] = { nofree nosync nounwind }
-; IS__CGSCC_NPM: attributes #[[ATTR23]] = { willreturn }
-; IS__CGSCC_NPM: attributes #[[ATTR24]] = { nounwind }
+; IS__CGSCC_NPM: attributes #[[ATTR21]] = { readonly }
+; IS__CGSCC_NPM: attributes #[[ATTR22:[0-9]+]] = { readnone }
+; IS__CGSCC_NPM: attributes #[[ATTR23]] = { mustprogress }
+; IS__CGSCC_NPM: attributes #[[ATTR24:[0-9]+]] = { readonly mustprogress }
+; IS__CGSCC_NPM: attributes #[[ATTR25]] = { readonly willreturn mustprogress }
+; IS__CGSCC_NPM: attributes #[[ATTR26]] = { nosync readnone willreturn mustprogress }
+; IS__CGSCC_NPM: attributes #[[ATTR27]] = { readonly willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR28]] = { nofree nosync nounwind readnone }
+; IS__CGSCC_NPM: attributes #[[ATTR29]] = { nofree nosync nounwind }
+; IS__CGSCC_NPM: attributes #[[ATTR30]] = { readnone willreturn }
+; IS__CGSCC_NPM: attributes #[[ATTR31]] = { nounwind }
+; IS__CGSCC_NPM: attributes #[[ATTR32]] = { willreturn }
 ;.


        


More information about the llvm-commits mailing list