[llvm] [InferAttrs] Mark errnomem-setting libcalls as such (PR #124742)

Antonio Frighetto via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 25 08:19:53 PST 2025


https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/124742

>From c13ebc147b6c1aa5b543306e7736bae6fbb8c369 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Sun, 23 Feb 2025 15:49:51 +0100
Subject: [PATCH 1/4] [InferAttrs] Mark `errnomem`-writing libcalls as such

Mark C standard library functions that set `errno` as such, as
included in the POSIX specification.
---
 llvm/include/llvm/IR/Function.h               |  23 +-
 llvm/include/llvm/Support/ModRef.h            |  56 +++
 llvm/lib/IR/Function.cpp                      |  43 +-
 llvm/lib/Transforms/Utils/BuildLibCalls.cpp   | 201 ++++++--
 .../Transforms/InferFunctionAttrs/annotate.ll | 462 +++++++++---------
 5 files changed, 511 insertions(+), 274 deletions(-)

diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index 29041688124bc..d31bc7db50276 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -571,7 +571,7 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
   bool onlyWritesMemory() const;
   void setOnlyWritesMemory();
 
-  /// Determine if the call can access memmory only using pointers based
+  /// Determine if the call can access memory only using pointers based
   /// on its arguments.
   bool onlyAccessesArgMemory() const;
   void setOnlyAccessesArgMemory();
@@ -581,11 +581,32 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
   bool onlyAccessesInaccessibleMemory() const;
   void setOnlyAccessesInaccessibleMemory();
 
+  /// Determine if the call can access only errno memory.
+  bool onlyAccessesErrnoMemory() const;
+  void setOnlyAccessesErrnoMemory();
+
   /// Determine if the function may only access memory that is
   ///  either inaccessible from the IR or pointed to by its arguments.
   bool onlyAccessesInaccessibleMemOrArgMem() const;
   void setOnlyAccessesInaccessibleMemOrArgMem();
 
+  /// Determine if the function may only access memory that is
+  ///  either pointed to by its arguments or errno memory.
+  bool onlyAccessesArgMemOrErrnoMem() const;
+  void setOnlyAccessesArgMemOrErrnoMem(ModRefInfo ArgMR);
+
+  /// Determine if the function may only access memory that is
+  ///  either inaccessible from the IR or errno memory.
+  bool onlyAccessesInaccessibleMemOrErrnoMem() const;
+  void setOnlyAccessesInaccessibleMemOrErrnoMem();
+
+  /// Determine if the function may only access memory that is
+  ///  either inaccessible from the IR, pointed to by its arguments, or errno
+  ///  memory.
+  bool onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const;
+  void setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem(
+      ModRefInfo InaccessibleMR, ModRefInfo ArgMR, ModRefInfo ErrnoMR);
+
   /// Determine if the function cannot return.
   bool doesNotReturn() const {
     return hasFnAttribute(Attribute::NoReturn);
diff --git a/llvm/include/llvm/Support/ModRef.h b/llvm/include/llvm/Support/ModRef.h
index eb660844b0b3a..4d0dc39a72725 100644
--- a/llvm/include/llvm/Support/ModRef.h
+++ b/llvm/include/llvm/Support/ModRef.h
@@ -161,6 +161,38 @@ template <typename LocationEnum> class MemoryEffectsBase {
     return FRMB;
   }
 
+  /// Create MemoryEffectsBase that can only access argument or errno memory.
+  static MemoryEffectsBase
+  argumentOrErrnoMemOnly(ModRefInfo ArgMR = ModRefInfo::ModRef,
+                         ModRefInfo OtherMR = ModRefInfo::ModRef) {
+    MemoryEffectsBase FRMB = none();
+    FRMB.setModRef(Location::ArgMem, ArgMR);
+    FRMB.setModRef(Location::ErrnoMem, OtherMR);
+    return FRMB;
+  }
+
+  /// Create MemoryEffectsBase that can only access inaccessible or errno
+  /// memory.
+  static MemoryEffectsBase
+  inaccessibleOrErrnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
+    MemoryEffectsBase FRMB = none();
+    FRMB.setModRef(Location::ErrnoMem, MR);
+    FRMB.setModRef(Location::InaccessibleMem, MR);
+    return FRMB;
+  }
+
+  /// Create MemoryEffectsBase that can only access inaccessible, argument or
+  /// errno memory.
+  static MemoryEffectsBase
+  inaccessibleOrArgOrErrnoMemOnly(ModRefInfo InaccessibleMR, ModRefInfo ArgMR,
+                                  ModRefInfo ErrnoMR) {
+    MemoryEffectsBase FRMB = none();
+    FRMB.setModRef(Location::ArgMem, ArgMR);
+    FRMB.setModRef(Location::ErrnoMem, ErrnoMR);
+    FRMB.setModRef(Location::InaccessibleMem, InaccessibleMR);
+    return FRMB;
+  }
+
   /// Create MemoryEffectsBase from an encoded integer value (used by memory
   /// attribute).
   static MemoryEffectsBase createFromIntValue(uint32_t Data) {
@@ -237,6 +269,30 @@ template <typename LocationEnum> class MemoryEffectsBase {
         .doesNotAccessMemory();
   }
 
+  /// Whether this function only (at most) accesses argument and errno memory.
+  bool onlyAccessesArgumentOrErrnoMem() const {
+    return getWithoutLoc(Location::ArgMem)
+        .getWithoutLoc(Location::ErrnoMem)
+        .doesNotAccessMemory();
+  }
+
+  /// Whether this function only (at most) accesses inaccessible and errno
+  /// memory.
+  bool onlyAccessesInaccessibleOrErrnoMem() const {
+    return getWithoutLoc(Location::InaccessibleMem)
+        .getWithoutLoc(Location::ErrnoMem)
+        .doesNotAccessMemory();
+  }
+
+  /// Whether this function only (at most) accesses inaccessible, argument and
+  /// errno memory.
+  bool onlyAccessesInaccessibleOrArgOrErrnoMem() const {
+    return getWithoutLoc(Location::InaccessibleMem)
+        .getWithoutLoc(Location::ArgMem)
+        .getWithoutLoc(Location::ErrnoMem)
+        .doesNotAccessMemory();
+  }
+
   /// Intersect with other MemoryEffectsBase.
   MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
     return MemoryEffectsBase(Data & Other.Data);
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 5666f0a53866f..e182ca6a9bbc8 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -904,7 +904,7 @@ void Function::setOnlyWritesMemory() {
   setMemoryEffects(getMemoryEffects() & MemoryEffects::writeOnly());
 }
 
-/// Determine if the call can access memmory only using pointers based
+/// Determine if the call can access memory only using pointers based
 /// on its arguments.
 bool Function::onlyAccessesArgMemory() const {
   return getMemoryEffects().onlyAccessesArgPointees();
@@ -922,6 +922,14 @@ void Function::setOnlyAccessesInaccessibleMemory() {
   setMemoryEffects(getMemoryEffects() & MemoryEffects::inaccessibleMemOnly());
 }
 
+/// Determine if the call can access only errno memory.
+bool Function::onlyAccessesErrnoMemory() const {
+  return getMemoryEffects().onlyAccessesErrnoMem();
+}
+void Function::setOnlyAccessesErrnoMemory() {
+  setMemoryEffects(getMemoryEffects() & MemoryEffects::errnoMemOnly());
+}
+
 /// Determine if the function may only access memory that is
 ///  either inaccessible from the IR or pointed to by its arguments.
 bool Function::onlyAccessesInaccessibleMemOrArgMem() const {
@@ -932,6 +940,39 @@ void Function::setOnlyAccessesInaccessibleMemOrArgMem() {
                    MemoryEffects::inaccessibleOrArgMemOnly());
 }
 
+/// Determine if the function may only access memory that is
+///  either pointed to by its arguments or errno memory.
+bool Function::onlyAccessesArgMemOrErrnoMem() const {
+  return getMemoryEffects().onlyAccessesArgumentOrErrnoMem();
+}
+void Function::setOnlyAccessesArgMemOrErrnoMem(ModRefInfo ArgMR) {
+  setMemoryEffects(getMemoryEffects() &
+                   MemoryEffects::argumentOrErrnoMemOnly(ArgMR));
+}
+
+/// Determine if the function may only access memory that is
+///  either inaccessible from the IR or errno memory.
+bool Function::onlyAccessesInaccessibleMemOrErrnoMem() const {
+  return getMemoryEffects().onlyAccessesInaccessibleOrErrnoMem();
+}
+void Function::setOnlyAccessesInaccessibleMemOrErrnoMem() {
+  setMemoryEffects(getMemoryEffects() &
+                   MemoryEffects::inaccessibleOrErrnoMemOnly());
+}
+
+/// Determine if the function may only access memory that is
+///  either inaccessible from the IR, pointed to by its arguments or errno
+///  memory.
+bool Function::onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const {
+  return getMemoryEffects().onlyAccessesInaccessibleOrArgOrErrnoMem();
+}
+void Function::setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem(
+    ModRefInfo InaccessibleMR, ModRefInfo ArgMR, ModRefInfo ErrnoMR) {
+  setMemoryEffects(getMemoryEffects() &
+                   MemoryEffects::inaccessibleOrArgOrErrnoMemOnly(
+                       InaccessibleMR, ArgMR, ErrnoMR));
+}
+
 bool Function::isTargetIntrinsic() const {
   return Intrinsic::isTargetIntrinsic(IntID);
 }
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 7a5326c255831..c2bd4b0ec6ff1 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -34,13 +34,19 @@ using namespace llvm;
 //- Infer Attributes ---------------------------------------------------------//
 
 STATISTIC(NumReadNone, "Number of functions inferred as readnone");
-STATISTIC(NumInaccessibleMemOnly,
-          "Number of functions inferred as inaccessiblememonly");
 STATISTIC(NumReadOnly, "Number of functions inferred as readonly");
 STATISTIC(NumWriteOnly, "Number of functions inferred as writeonly");
 STATISTIC(NumArgMemOnly, "Number of functions inferred as argmemonly");
+STATISTIC(NumErrnoMemOnly, "Number of functions inferred as errnomemonly");
 STATISTIC(NumInaccessibleMemOrArgMemOnly,
           "Number of functions inferred as inaccessiblemem_or_argmemonly");
+STATISTIC(NumArgumentMemOrErrnoMemOnly,
+          "Number of functions inferred as argmem_or_errnomemonly");
+STATISTIC(NumInaccessibleMemOrErrnoMemOnly,
+          "Number of functions inferred as inaccessiblemem_or_errnomemonly");
+STATISTIC(NumInaccessibleMemOrArgMemOrErrnoMemOnly,
+          "Number of functions inferred as "
+          "inaccessiblemem_or_argmem_or_errnomemonly");
 STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
 STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
 STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
@@ -76,14 +82,6 @@ static bool setNoReturn(Function &F) {
   return true;
 }
 
-static bool setOnlyAccessesInaccessibleMemory(Function &F) {
-  if (F.onlyAccessesInaccessibleMemory())
-    return false;
-  F.setOnlyAccessesInaccessibleMemory();
-  ++NumInaccessibleMemOnly;
-  return true;
-}
-
 static bool setOnlyReadsMemory(Function &F) {
   if (F.onlyReadsMemory())
     return false;
@@ -108,7 +106,7 @@ static bool setOnlyAccessesArgMemory(Function &F) {
   return true;
 }
 
-static bool setOnlyAccessesInaccessibleMemOrArgMem(Function &F) {
+static bool setOnlyAccessesInaccessibleOrArgMem(Function &F) {
   if (F.onlyAccessesInaccessibleMemOrArgMem())
     return false;
   F.setOnlyAccessesInaccessibleMemOrArgMem();
@@ -116,6 +114,44 @@ static bool setOnlyAccessesInaccessibleMemOrArgMem(Function &F) {
   return true;
 }
 
+static bool setOnlyAccessesErrnoMemory(Function &F) {
+  if (F.onlyAccessesErrnoMemory())
+    return false;
+  F.setOnlyAccessesErrnoMemory();
+  ++NumErrnoMemOnly;
+  return true;
+}
+
+static bool
+setOnlyAccessesArgOrErrnoMem(Function &F,
+                             ModRefInfo ArgMR = ModRefInfo::ModRef) {
+  if (F.onlyAccessesArgMemOrErrnoMem())
+    return false;
+  F.setOnlyAccessesArgMemOrErrnoMem(ArgMR);
+  ++NumArgumentMemOrErrnoMemOnly;
+  return true;
+}
+
+static bool setOnlyAccessesInaccessibleOrErrnoMem(Function &F) {
+  if (F.onlyAccessesInaccessibleMemOrErrnoMem())
+    return false;
+  F.setOnlyAccessesInaccessibleMemOrErrnoMem();
+  ++NumInaccessibleMemOrErrnoMemOnly;
+  return true;
+}
+
+static bool setOnlyAccessesInaccessibleOrArgOrErrnoMem(
+    Function &F, ModRefInfo InaccessibleMR = ModRefInfo::ModRef,
+    ModRefInfo ArgMR = ModRefInfo::ModRef,
+    ModRefInfo ErrnoMR = ModRefInfo::ModRef) {
+  if (F.onlyAccessesInaccessibleMemOrArgMemOrErrnoMem())
+    return false;
+  F.setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem(InaccessibleMR, ArgMR,
+                                                     ErrnoMR);
+  ++NumInaccessibleMemOrArgMemOrErrnoMemOnly;
+  return true;
+}
+
 static bool setDoesNotThrow(Function &F) {
   if (F.doesNotThrow())
     return false;
@@ -280,6 +316,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Module *M, StringRef Name,
 
 bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
                                          const TargetLibraryInfo &TLI) {
+  using MR = ModRefInfo;
   LibFunc TheLibFunc;
   if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc)))
     return false;
@@ -320,6 +357,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setWillReturn(F);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_strcat:
   case LibFunc_strncat:
@@ -353,6 +391,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_strcmp:      // 0,1
   case LibFunc_strspn:      // 0,1
@@ -366,6 +405,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     break;
   case LibFunc_strcoll:
+    Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setDoesNotThrow(F);
+    Changed |= setWillReturn(F);
+    Changed |= setDoesNotCapture(F, 0);
+    Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
+    break;
   case LibFunc_strcasecmp:  // 0,1
   case LibFunc_strncasecmp: //
     // Those functions may depend on the locale, which may be accessed through
@@ -396,6 +443,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_setbuf:
   case LibFunc_setvbuf:
@@ -408,7 +456,8 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     [[fallthrough]];
   case LibFunc_strdup:
     Changed |= setAllocFamily(F, "malloc");
-    Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F);
+    Changed |=
+        setOnlyAccessesInaccessibleOrArgOrErrnoMem(F, MR::ModRef, MR::Ref);
     Changed |= setDoesNotThrow(F);
     Changed |= setRetDoesNotAlias(F);
     Changed |= setWillReturn(F);
@@ -422,6 +471,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_sscanf:
     Changed |= setRetAndArgsNoUndef(F);
@@ -430,6 +480,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_sprintf:
     Changed |= setRetAndArgsNoUndef(F);
@@ -439,6 +490,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyWritesMemory(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_snprintf:
     Changed |= setRetAndArgsNoUndef(F);
@@ -448,6 +500,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyWritesMemory(F, 0);
     Changed |= setDoesNotCapture(F, 2);
     Changed |= setOnlyReadsMemory(F, 2);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_setitimer:
     Changed |= setRetAndArgsNoUndef(F);
@@ -456,12 +509,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setDoesNotCapture(F, 2);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_system:
     // May throw; "system" is a valid pthread cancellation point.
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_aligned_alloc:
     Changed |= setAlignedAllocParam(F, 0);
@@ -475,7 +530,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
                                                                   : "malloc");
     Changed |= setAllocKind(F, AllocFnKind::Alloc | AllocFnKind::Uninitialized);
     Changed |= setAllocSize(F, 0, std::nullopt);
-    Changed |= setOnlyAccessesInaccessibleMemory(F);
+    Changed |= setOnlyAccessesInaccessibleOrErrnoMem(F);
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setRetDoesNotAlias(F);
@@ -544,7 +599,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
                                    AllocFnKind::Uninitialized);
     Changed |= setAllocSize(F, 1, std::nullopt);
     Changed |= setAlignedAllocParam(F, 0);
-    Changed |= setOnlyAccessesInaccessibleMemory(F);
+    Changed |= setOnlyAccessesInaccessibleOrErrnoMem(F);
     Changed |= setRetNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setRetDoesNotAlias(F);
@@ -555,12 +610,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_mktime:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setWillReturn(F);
     Changed |= setDoesNotCapture(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_realloc:
   case LibFunc_reallocf:
@@ -570,7 +627,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setAllocKind(F, AllocFnKind::Realloc);
     Changed |= setAllocatedPointerParam(F, 0);
     Changed |= setAllocSize(F, 1, std::nullopt);
-    Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F);
+    Changed |= setOnlyAccessesInaccessibleOrArgOrErrnoMem(F);
     Changed |= setRetNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setRetDoesNotAlias(F);
@@ -583,7 +640,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setAllocKind(F, AllocFnKind::Realloc);
     Changed |= setAllocatedPointerParam(F, 0);
     Changed |= setAllocSize(F, 1, 2);
-    Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F);
+    Changed |= setOnlyAccessesInaccessibleOrArgOrErrnoMem(F);
     Changed |= setRetNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setRetDoesNotAlias(F);
@@ -596,6 +653,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     // May throw; "read" is a valid pthread cancellation point.
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_rewind:
     Changed |= setRetAndArgsNoUndef(F);
@@ -604,11 +662,18 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     break;
   case LibFunc_rmdir:
   case LibFunc_remove:
+    Changed |= setRetAndArgsNoUndef(F);
+    Changed |= setDoesNotThrow(F);
+    Changed |= setDoesNotCapture(F, 0);
+    Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
+    break;
   case LibFunc_realpath:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_rename:
     Changed |= setRetAndArgsNoUndef(F);
@@ -617,6 +682,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_readlink:
     Changed |= setRetAndArgsNoUndef(F);
@@ -624,12 +690,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_write:
     // May throw; "write" is a valid pthread cancellation point.
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_bcopy:
     Changed |= setDoesNotThrow(F);
@@ -661,7 +729,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
                                                                   : "malloc");
     Changed |= setAllocKind(F, AllocFnKind::Alloc | AllocFnKind::Zeroed);
     Changed |= setAllocSize(F, 0, 1);
-    Changed |= setOnlyAccessesInaccessibleMemory(F);
+    Changed |= setOnlyAccessesInaccessibleOrErrnoMem(F);
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setRetDoesNotAlias(F);
@@ -673,6 +741,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_ctermid:
   case LibFunc_clearerr:
@@ -680,6 +749,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_atoi:
   case LibFunc_atol:
@@ -695,6 +765,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_fopen:
     Changed |= setRetAndArgsNoUndef(F);
@@ -704,6 +775,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_fdopen:
     Changed |= setRetAndArgsNoUndef(F);
@@ -711,6 +783,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setRetDoesNotAlias(F);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_feof:
     Changed |= setRetAndArgsNoUndef(F);
@@ -723,7 +796,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
                                                                 : "malloc");
     Changed |= setAllocKind(F, AllocFnKind::Free);
     Changed |= setAllocatedPointerParam(F, 0);
-    Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F);
+    Changed |= setOnlyAccessesInaccessibleOrArgMem(F);
     Changed |= setArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setWillReturn(F);
@@ -739,6 +812,8 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_fflush:
   case LibFunc_fclose:
   case LibFunc_fsetpos:
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
+    [[fallthrough]];
   case LibFunc_flockfile:
   case LibFunc_funlockfile:
   case LibFunc_ftrylockfile:
@@ -758,6 +833,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_frexp:
   case LibFunc_frexpf:
@@ -772,6 +848,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_fgets:
   case LibFunc_fgets_unlocked:
@@ -785,6 +862,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 3);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_fwrite:
   case LibFunc_fwrite_unlocked:
@@ -792,7 +870,8 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 3);
-    // FIXME: readonly #1?
+    Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_fputs:
   case LibFunc_fputs_unlocked:
@@ -809,12 +888,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_fgetpos:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_getc:
     Changed |= setRetAndArgsNoUndef(F);
@@ -847,12 +928,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_getpwnam:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_ungetc:
     Changed |= setRetAndArgsNoUndef(F);
@@ -863,18 +946,21 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_unlink:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_unsetenv:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_utime:
   case LibFunc_utimes:
@@ -884,12 +970,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_putc:
   case LibFunc_putc_unlocked:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_puts:
   case LibFunc_printf:
@@ -898,17 +986,20 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_pread:
     // May throw; "pread" is a valid pthread cancellation point.
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_pwrite:
     // May throw; "pwrite" is a valid pthread cancellation point.
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_putchar:
   case LibFunc_putchar_unlocked:
@@ -923,17 +1014,20 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_pclose:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_vscanf:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_vsscanf:
     Changed |= setRetAndArgsNoUndef(F);
@@ -942,6 +1036,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_vfscanf:
     Changed |= setRetAndArgsNoUndef(F);
@@ -949,12 +1044,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_vprintf:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_vfprintf:
   case LibFunc_vsprintf:
@@ -963,6 +1060,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_vsnprintf:
     Changed |= setRetAndArgsNoUndef(F);
@@ -970,12 +1068,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 2);
     Changed |= setOnlyReadsMemory(F, 2);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_open:
     // May throw; "open" is a valid pthread cancellation point.
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_opendir:
     Changed |= setRetAndArgsNoUndef(F);
@@ -983,16 +1083,19 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setRetDoesNotAlias(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_tmpfile:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setRetDoesNotAlias(F);
+    Changed |= setOnlyAccessesErrnoMemory(F);
     break;
   case LibFunc_times:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_htonl:
   case LibFunc_htons:
@@ -1007,12 +1110,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_lchown:
     Changed |= setRetAndArgsNoUndef(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F, MR::Ref);
     break;
   case LibFunc_qsort:
     // May throw; places call through function pointer.
@@ -1059,6 +1164,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 0);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_dunder_isoc99_sscanf:
     Changed |= setRetAndArgsNoUndef(F);
@@ -1108,6 +1214,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 1);
+    Changed |= setOnlyAccessesArgOrErrnoMem(F);
     break;
   case LibFunc_memset_pattern4:
   case LibFunc_memset_pattern8:
@@ -1145,6 +1252,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_ldexp:
   case LibFunc_ldexpf:
   case LibFunc_ldexpl:
+    Changed |= setOnlyAccessesErrnoMemory(F);
     Changed |= setWillReturn(F);
     break;
   case LibFunc_remquo:
@@ -1152,7 +1260,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_remquol:
     Changed |= setDoesNotCapture(F, 2);
     [[fallthrough]];
-  case LibFunc_abs:
   case LibFunc_acos:
   case LibFunc_acosf:
   case LibFunc_acosh:
@@ -1174,15 +1281,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_atanhf:
   case LibFunc_atanhl:
   case LibFunc_atanl:
-  case LibFunc_cbrt:
-  case LibFunc_cbrtf:
-  case LibFunc_cbrtl:
   case LibFunc_ceil:
   case LibFunc_ceilf:
   case LibFunc_ceill:
-  case LibFunc_copysign:
-  case LibFunc_copysignf:
-  case LibFunc_copysignl:
   case LibFunc_cos:
   case LibFunc_cosh:
   case LibFunc_coshf:
@@ -1206,37 +1307,18 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_expm1:
   case LibFunc_expm1f:
   case LibFunc_expm1l:
-  case LibFunc_fabs:
-  case LibFunc_fabsf:
-  case LibFunc_fabsl:
   case LibFunc_fdim:
   case LibFunc_fdiml:
   case LibFunc_fdimf:
-  case LibFunc_ffs:
-  case LibFunc_ffsl:
-  case LibFunc_ffsll:
   case LibFunc_floor:
   case LibFunc_floorf:
   case LibFunc_floorl:
-  case LibFunc_fls:
-  case LibFunc_flsl:
-  case LibFunc_flsll:
-  case LibFunc_fmax:
-  case LibFunc_fmaxf:
-  case LibFunc_fmaxl:
-  case LibFunc_fmin:
-  case LibFunc_fminf:
-  case LibFunc_fminl:
   case LibFunc_fmod:
   case LibFunc_fmodf:
   case LibFunc_fmodl:
   case LibFunc_hypot:
   case LibFunc_hypotf:
   case LibFunc_hypotl:
-  case LibFunc_isascii:
-  case LibFunc_isdigit:
-  case LibFunc_labs:
-  case LibFunc_llabs:
   case LibFunc_log:
   case LibFunc_log10:
   case LibFunc_log10f:
@@ -1294,6 +1376,34 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_tanhf:
   case LibFunc_tanhl:
   case LibFunc_tanl:
+    Changed |= setOnlyAccessesErrnoMemory(F);
+    [[fallthrough]];
+  case LibFunc_abs:
+  case LibFunc_cbrt:
+  case LibFunc_cbrtf:
+  case LibFunc_cbrtl:
+  case LibFunc_copysign:
+  case LibFunc_copysignf:
+  case LibFunc_copysignl:
+  case LibFunc_fabs:
+  case LibFunc_fabsf:
+  case LibFunc_fabsl:
+  case LibFunc_ffs:
+  case LibFunc_ffsl:
+  case LibFunc_ffsll:
+  case LibFunc_fls:
+  case LibFunc_flsl:
+  case LibFunc_flsll:
+  case LibFunc_fmax:
+  case LibFunc_fmaxf:
+  case LibFunc_fmaxl:
+  case LibFunc_fmin:
+  case LibFunc_fminf:
+  case LibFunc_fminl:
+  case LibFunc_isascii:
+  case LibFunc_isdigit:
+  case LibFunc_labs:
+  case LibFunc_llabs:
   case LibFunc_toascii:
   case LibFunc_trunc:
   case LibFunc_truncf:
@@ -1314,6 +1424,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setDoesNotCapture(F, 2);
     Changed |= setWillReturn(F);
+    Changed |= setOnlyAccessesErrnoMemory(F);
     break;
   default:
     // FIXME: It'd be really nice to cover all the library functions we're
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index e4b9a8d25d1bc..e1715c511d5a4 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -198,73 +198,73 @@ declare float @__sinpif(float)
 ; CHECK: declare i32 @abs(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare i32 @abs(i32)
 
-; CHECK: declare noundef i32 @access(ptr noundef readonly captures(none), i32 noundef) [[NOFREE_NOUNWIND:#[0-9]+]]
+; CHECK: declare noundef i32 @access(ptr noundef readonly captures(none), i32 noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @access(ptr, i32)
 
-; CHECK: declare double @acos(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @acos(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @acos(double)
 
-; CHECK: declare float @acosf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @acosf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @acosf(float)
 
-; CHECK: declare double @acosh(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @acosh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @acosh(double)
 
-; CHECK: declare float @acoshf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @acoshf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @acoshf(float)
 
-; CHECK: declare x86_fp80 @acoshl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @acoshl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @acoshl(x86_fp80)
 
-; CHECK: declare x86_fp80 @acosl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @acosl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @acosl(x86_fp80)
 
-; CHECK: declare noalias noundef ptr @aligned_alloc(i64 allocalign noundef, i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC:#[0-9]+]]
+; CHECK: declare noalias noundef ptr @aligned_alloc(i64 allocalign noundef, i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC:#[0-9]+]]
 declare ptr @aligned_alloc(i64, i64)
 
-; CHECK: declare double @asin(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @asin(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @asin(double)
 
-; CHECK: declare float @asinf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @asinf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @asinf(float)
 
-; CHECK: declare double @asinh(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @asinh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @asinh(double)
 
-; CHECK: declare float @asinhf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @asinhf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @asinhf(float)
 
-; CHECK: declare x86_fp80 @asinhl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @asinhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @asinhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @asinl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @asinl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @asinl(x86_fp80)
 
-; CHECK: declare double @atan(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @atan(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @atan(double)
 
-; CHECK: declare double @atan2(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @atan2(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @atan2(double, double)
 
-; CHECK: declare float @atan2f(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @atan2f(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @atan2f(float, float)
 
-; CHECK: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @atan2l(x86_fp80, x86_fp80)
 
-; CHECK: declare float @atanf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @atanf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @atanf(float)
 
-; CHECK: declare double @atanh(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @atanh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @atanh(double)
 
-; CHECK: declare float @atanhf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @atanhf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @atanhf(float)
 
-; CHECK: declare x86_fp80 @atanhl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @atanhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @atanhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @atanl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @atanl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @atanl(x86_fp80)
 
 ; CHECK: declare double @atof(ptr captures(none)) [[NOFREE_NOUNWIND_READONLY_WILLRETURN:#[0-9]+]]
@@ -289,10 +289,10 @@ declare void @bcopy(ptr, ptr, i64)
 ; CHECK: declare void @bzero(ptr writeonly captures(none), i64)  [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare void @bzero(ptr, i64)
 
-; CHECK: declare noalias noundef ptr @calloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC:#[0-9]+]]
+; CHECK: declare noalias noundef ptr @calloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC:#[0-9]+]]
 declare ptr @calloc(i64, i64)
 
-; CHECK-AIX: declare noalias noundef ptr @vec_calloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE01_FAMILY_VEC_MALLOC:#[0-9]+]]
+; CHECK-AIX: declare noalias noundef ptr @vec_calloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE01_FAMILY_VEC_MALLOC:#[0-9]+]]
 declare ptr @vec_calloc(i64, i64)
 
 ; CHECK: declare double @cbrt(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
@@ -304,13 +304,13 @@ declare float @cbrtf(float)
 ; CHECK: declare x86_fp80 @cbrtl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare x86_fp80 @cbrtl(x86_fp80)
 
-; CHECK: declare double @ceil(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @ceil(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @ceil(double)
 
-; CHECK: declare float @ceilf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @ceilf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @ceilf(float)
 
-; CHECK: declare x86_fp80 @ceill(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @ceill(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @ceill(x86_fp80)
 
 ; The second argument of int chmod(FILE*, mode_t) is a 32-bit int on most
@@ -318,16 +318,16 @@ declare x86_fp80 @ceill(x86_fp80)
 ; the function is still recognized.
 ; FIXME: this should be tightened up to verify that only the type with
 ; the right size for the target matches.
-; CHECK: declare noundef i32 @chmod(ptr noundef readonly captures(none), i16 noundef zeroext) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @chmod(ptr noundef readonly captures(none), i16 noundef zeroext) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @chmod(ptr, i16 zeroext)
 
-; CHECK: declare noundef i32 @chown(ptr noundef readonly captures(none), i32 noundef, i32 noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @chown(ptr noundef readonly captures(none), i32 noundef, i32 noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @chown(ptr, i32, i32)
 
-; CHECK: declare void @clearerr(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare void @clearerr(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare void @clearerr(ptr)
 
-; CHECK: declare noundef i32 @closedir(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @closedir(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @closedir(ptr)
 
 ; CHECK: declare double @copysign(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
@@ -339,52 +339,52 @@ declare float @copysignf(float, float)
 ; CHECK: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare x86_fp80 @copysignl(x86_fp80, x86_fp80)
 
-; CHECK: declare double @cos(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @cos(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @cos(double)
 
-; CHECK: declare float @cosf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @cosf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @cosf(float)
 
-; CHECK: declare double @cosh(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @cosh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @cosh(double)
 
-; CHECK: declare float @coshf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @coshf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @coshf(float)
 
-; CHECK: declare x86_fp80 @coshl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @coshl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @coshl(x86_fp80)
 
-; CHECK: declare x86_fp80 @cosl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @cosl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @cosl(x86_fp80)
 
-; CHECK: declare noundef ptr @ctermid(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef ptr @ctermid(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @ctermid(ptr)
 
-; CHECK: declare double @exp(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @exp(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @exp(double)
 
-; CHECK: declare double @exp2(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @exp2(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @exp2(double)
 
-; CHECK: declare float @exp2f(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @exp2f(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @exp2f(float)
 
-; CHECK: declare x86_fp80 @exp2l(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @exp2l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @exp2l(x86_fp80)
 
-; CHECK: declare float @expf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @expf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @expf(float)
 
-; CHECK: declare x86_fp80 @expl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @expl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @expl(x86_fp80)
 
-; CHECK: declare double @expm1(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @expm1(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @expm1(double)
 
-; CHECK: declare float @expm1f(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @expm1f(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @expm1f(float)
 
-; CHECK: declare x86_fp80 @expm1l(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @expm1l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @expm1l(x86_fp80)
 
 ; CHECK: declare double @fabs(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
@@ -396,19 +396,19 @@ declare float @fabsf(float)
 ; CHECK: declare x86_fp80 @fabsl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare x86_fp80 @fabsl(x86_fp80)
 
-; CHECK: declare noundef i32 @fclose(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fclose(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fclose(ptr)
 
-; CHECK: declare noalias noundef ptr @fdopen(i32 noundef, ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noalias noundef ptr @fdopen(i32 noundef, ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @fdopen(i32, ptr)
 
-; CHECK: declare noundef i32 @feof(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @feof(ptr noundef captures(none)) [[NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @feof(ptr)
 
 ; CHECK: declare noundef i32 @ferror(ptr noundef captures(none)) [[NOFREE_NOUNWIND_READONLY:#[0-9]+]]
 declare i32 @ferror(ptr)
 
-; CHECK: declare noundef i32 @fflush(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fflush(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fflush(ptr)
 
 ; CHECK: declare i32 @ffs(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
@@ -422,28 +422,28 @@ declare i32 @ffsl(i64)
 ; CHECK-UNKNOWN: declare i32 @ffsll(i64){{$}}
 declare i32 @ffsll(i64)
 
-; CHECK: declare noundef i32 @fgetc(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fgetc(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fgetc(ptr)
 
-; CHECK: declare noundef i32 @fgetpos(ptr noundef captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fgetpos(ptr noundef captures(none), ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fgetpos(ptr, ptr)
 
 ; CHECK: declare noundef ptr @fgets(ptr noundef, i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare ptr @fgets(ptr, i32, ptr)
 
-; CHECK: declare noundef i32 @fileno(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fileno(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fileno(ptr)
 
 ; CHECK: declare void @flockfile(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare void @flockfile(ptr)
 
-; CHECK: declare double @floor(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @floor(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @floor(double)
 
-; CHECK: declare float @floorf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @floorf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @floorf(float)
 
-; CHECK: declare x86_fp80 @floorl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @floorl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @floorl(x86_fp80)
 
 ; CHECK: declare i32 @fls(i32)
@@ -473,28 +473,28 @@ declare float @fminf(float, float)
 ; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare x86_fp80 @fminl(x86_fp80, x86_fp80)
 
-; CHECK: declare double @fmod(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @fmod(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @fmod(double, double)
 
-; CHECK: declare float @fmodf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @fmodf(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @fmodf(float, float)
 
-; CHECK: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @fmodl(x86_fp80, x86_fp80)
 
-; CHECK: declare noalias noundef ptr @fopen(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noalias noundef ptr @fopen(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @fopen(ptr, ptr)
 
-; CHECK: declare noundef i32 @fprintf(ptr noundef captures(none), ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fprintf(ptr noundef captures(none), ptr noundef readonly captures(none), ...) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fprintf(ptr, ptr, ...)
 
-; CHECK: declare noundef i32 @fputc(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fputc(i32 noundef, ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fputc(i32, ptr)
 
 ; CHECK: declare noundef i32 @fputs(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare i32 @fputs(ptr, ptr)
 
-; CHECK: declare noundef i64 @fread(ptr noundef captures(none), i64 noundef, i64 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i64 @fread(ptr noundef captures(none), i64 noundef, i64 noundef, ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i64 @fread(ptr, i64, i64, ptr)
 
 ; CHECK: declare void @free(ptr allocptr noundef captures(none)) [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_FREE_FAMILY_MALLOC:#[0-9]+]]
@@ -512,37 +512,37 @@ declare float @frexpf(float, ptr)
 ; CHECK: declare x86_fp80 @frexpl(x86_fp80, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare x86_fp80 @frexpl(x86_fp80, ptr)
 
-; CHECK: declare noundef i32 @fscanf(ptr noundef captures(none), ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fscanf(ptr noundef captures(none), ptr noundef readonly captures(none), ...) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fscanf(ptr, ptr, ...)
 
-; CHECK: declare noundef i32 @fseek(ptr noundef captures(none), i64 noundef, i32 noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fseek(ptr noundef captures(none), i64 noundef, i32 noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fseek(ptr, i64, i32)
 
-; CHECK: declare noundef i32 @fseeko(ptr noundef captures(none), i64 noundef, i32 noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fseeko(ptr noundef captures(none), i64 noundef, i32 noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fseeko(ptr, i64, i32)
 
 ; CHECK-LINUX: declare noundef i32 @fseeko64(ptr noundef captures(none), i64 noundef, i32 noundef) [[NOFREE_NOUNWIND]]
 declare i32 @fseeko64(ptr, i64, i32)
 
-; CHECK: declare noundef i32 @fsetpos(ptr noundef captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fsetpos(ptr noundef captures(none), ptr noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fsetpos(ptr, ptr)
 
-; CHECK: declare noundef i32 @fstat(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fstat(i32 noundef, ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fstat(i32, ptr)
 
 ; CHECK-LINUX: declare noundef i32 @fstat64(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare i32 @fstat64(i32, ptr)
 
-; CHECK: declare noundef i32 @fstatvfs(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @fstatvfs(i32 noundef, ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fstatvfs(i32, ptr)
 
 ; CHECK-LINUX: declare noundef i32 @fstatvfs64(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare i32 @fstatvfs64(i32, ptr)
 
-; CHECK: declare noundef i64 @ftell(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i64 @ftell(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i64 @ftell(ptr)
 
-; CHECK: declare noundef i64 @ftello(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i64 @ftello(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i64 @ftello(ptr)
 
 ; CHECK-LINUX: declare noundef i64 @ftello64(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
@@ -554,7 +554,7 @@ declare i32 @ftrylockfile(ptr)
 ; CHECK: declare void @funlockfile(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare void @funlockfile(ptr)
 
-; CHECK: declare noundef i64 @fwrite(ptr noundef captures(none), i64 noundef, i64 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i64 @fwrite(ptr noundef readonly captures(none), i64 noundef, i64 noundef, ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i64 @fwrite(ptr, i64, i64, ptr)
 
 ; CHECK: declare noundef i32 @getc(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
@@ -574,28 +574,28 @@ declare i32 @getchar_unlocked()
 ; CHECK: declare noundef ptr @getenv(ptr noundef captures(none)) [[NOFREE_NOUNWIND_READONLY]]
 declare ptr @getenv(ptr)
 
-; CHECK: declare noundef i32 @getitimer(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @getitimer(i32 noundef, ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @getitimer(i32, ptr)
 
 ; CHECK: declare noundef i32 @getlogin_r(ptr noundef captures(none), i64 noundef) [[NOFREE_NOUNWIND]]
 declare i32 @getlogin_r(ptr, i64)
 
-; CHECK: declare noundef ptr @getpwnam(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef ptr @getpwnam(ptr noundef readonly captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @getpwnam(ptr)
 
 ; CHECK: declare noundef ptr @gets(ptr noundef) [[NOFREE_NOUNWIND]]
 declare ptr @gets(ptr)
 
-; CHECK: declare noundef i32 @gettimeofday(ptr noundef captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @gettimeofday(ptr noundef captures(none), ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @gettimeofday(ptr, ptr)
 
-; CHECK: declare double @hypot(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @hypot(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @hypot(double, double)
 
-; CHECK: declare float @hypotf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @hypotf(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @hypotf(float, float)
 
-; CHECK: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @hypotl(x86_fp80, x86_fp80)
 
 ; CHECK: declare i32 @isascii(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
@@ -607,94 +607,94 @@ declare i32 @isdigit(i32)
 ; CHECK: declare i64 @labs(i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare i64 @labs(i64)
 
-; CHECK: declare noundef i32 @lchown(ptr noundef readonly captures(none), i32 noundef, i32 noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @lchown(ptr noundef readonly captures(none), i32 noundef, i32 noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @lchown(ptr, i32, i32)
 
-; CHECK: declare double @ldexp(double, i32) [[NOFREE_WILLRETURN:#[0-9]+]]
+; CHECK: declare double @ldexp(double, i32) [[ERRNOMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
 declare double @ldexp(double, i32)
 
-; CHECK: declare float @ldexpf(float, i32) [[NOFREE_WILLRETURN]]
+; CHECK: declare float @ldexpf(float, i32) [[ERRNOMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
 declare float @ldexpf(float, i32)
 
-; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NOFREE_WILLRETURN]]
+; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32) [[ERRNOMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @ldexpl(x86_fp80, i32)
 
 ; CHECK: declare i64 @llabs(i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare i64 @llabs(i64)
 
-; CHECK: declare double @log(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @log(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @log(double)
 
-; CHECK: declare double @log10(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @log10(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @log10(double)
 
-; CHECK: declare float @log10f(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @log10f(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @log10f(float)
 
-; CHECK: declare x86_fp80 @log10l(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @log10l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @log10l(x86_fp80)
 
-; CHECK: declare double @log1p(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @log1p(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @log1p(double)
 
-; CHECK: declare float @log1pf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @log1pf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @log1pf(float)
 
-; CHECK: declare x86_fp80 @log1pl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @log1pl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @log1pl(x86_fp80)
 
-; CHECK: declare double @log2(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @log2(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @log2(double)
 
-; CHECK: declare float @log2f(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @log2f(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @log2f(float)
 
-; CHECK: declare x86_fp80 @log2l(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @log2l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @log2l(x86_fp80)
 
-; CHECK: declare i32 @ilogb(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i32 @ilogb(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare i32 @ilogb(double)
 
-; CHECK: declare i32 @ilogbf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i32 @ilogbf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare i32 @ilogbf(float)
 
-; CHECK: declare i32 @ilogbl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i32 @ilogbl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare i32 @ilogbl(x86_fp80)
 
-; CHECK: declare double @logb(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @logb(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @logb(double)
 
-; CHECK: declare float @logbf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @logbf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @logbf(float)
 
-; CHECK: declare x86_fp80 @logbl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @logbl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @logbl(x86_fp80)
 
-; CHECK: declare float @logf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @logf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @logf(float)
 
-; CHECK: declare x86_fp80 @logl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @logl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @logl(x86_fp80)
 
-; CHECK: declare double @tgamma(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @tgamma(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @tgamma(double)
 
-; CHECK: declare float @tgammaf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @tgammaf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @tgammaf(float)
 
-; CHECK: declare x86_fp80 @tgammal(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @tgammal(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @tgammal(x86_fp80)
 
-; CHECK: declare noundef i32 @lstat(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @lstat(ptr noundef readonly captures(none), ptr noundef captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @lstat(ptr, ptr)
 
-; CHECK-LINUX: declare noundef i32 @lstat64(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK-LINUX: declare noundef i32 @lstat64(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @lstat64(ptr, ptr)
 
-; CHECK: declare noalias noundef ptr @malloc(i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC:#[0-9]+]]
+; CHECK: declare noalias noundef ptr @malloc(i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC:#[0-9]+]]
 declare ptr @malloc(i64)
 
-; CHECK-AIX: declare noalias noundef ptr @vec_malloc(i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE0_FAMILY_VEC_MALLOC:#[0-9]+]]
+; CHECK-AIX: declare noalias noundef ptr @vec_malloc(i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE0_FAMILY_VEC_MALLOC:#[0-9]+]]
 declare ptr @vec_malloc(i64)
 
 ; CHECK-LINUX: declare noalias noundef ptr @memalign(i64 allocalign, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
@@ -729,7 +729,7 @@ declare ptr @memset(ptr, i32, i64)
 ; CHECK: declare ptr @__memset_chk(ptr writeonly, i32, i64, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
 declare ptr @__memset_chk(ptr, i32, i64, i64)
 
-; CHECK: declare noundef i32 @mkdir(ptr noundef readonly captures(none), i16 noundef zeroext) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @mkdir(ptr noundef readonly captures(none), i16 noundef zeroext) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @mkdir(ptr, i16 zeroext)
 
 ; CHECK: declare noundef i64 @mktime(ptr noundef captures(none)) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
@@ -753,223 +753,223 @@ declare float @nanf(ptr)
 ; CHECK: declare x86_fp80 @nanl(ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
 declare x86_fp80 @nanl(ptr)
 
-; CHECK: declare double @nearbyint(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @nearbyint(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @nearbyint(double)
 
-; CHECK: declare float @nearbyintf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @nearbyintf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @nearbyintf(float)
 
-; CHECK: declare x86_fp80 @nearbyintl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @nearbyintl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @nearbyintl(x86_fp80)
 
-; CHECK-LINUX: declare noundef i32 @open(ptr noundef readonly captures(none), i32 noundef, ...) [[NOFREE]]
+; CHECK-LINUX: declare noundef i32 @open(ptr noundef readonly captures(none), i32 noundef, ...) [[ARGMEMORERRNOMEMONLY_NOFREE:#[0-9]+]]
 ; CHECK-OPEN: declare noundef i32 @open(ptr noundef readonly captures(none), i32 noundef, ...) [[NOFREE:#[0-9]+]]
 declare i32 @open(ptr, i32, ...)
 
 ; CHECK-LINUX: declare noundef i32 @open64(ptr noundef readonly captures(none), i32 noundef, ...) [[NOFREE]]
 declare i32 @open64(ptr, i32, ...)
 
-; CHECK: declare noalias noundef ptr @opendir(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noalias noundef ptr @opendir(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @opendir(ptr)
 
-; CHECK: declare noundef i32 @pclose(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @pclose(ptr noundef captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @pclose(ptr)
 
-; CHECK: declare void @perror(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare void @perror(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare void @perror(ptr)
 
-; CHECK: declare noalias noundef ptr @popen(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noalias noundef ptr @popen(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @popen(ptr, ptr)
 
-; CHECK: declare i32 @posix_memalign(ptr, i64, i64) [[NOFREE]]
+; CHECK: declare i32 @posix_memalign(ptr, i64, i64) [[NOFREE:#[0-9]+]]
 declare i32 @posix_memalign(ptr, i64, i64)
 
-; CHECK: declare double @pow(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @pow(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @pow(double, double)
 
-; CHECK: declare float @powf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @powf(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @powf(float, float)
 
-; CHECK: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @powl(x86_fp80, x86_fp80)
 
-; CHECK: declare noundef i64 @pread(i32 noundef, ptr noundef captures(none), i64 noundef, i64 noundef) [[NOFREE]]
+; CHECK: declare noundef i64 @pread(i32 noundef, ptr noundef captures(none), i64 noundef, i64 noundef) [[ARGMEMRWORERRNOMEMONLY_NOFREE:#[0-9]+]]
 declare i64 @pread(i32, ptr, i64, i64)
 
-; CHECK: declare noundef i32 @printf(ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @printf(ptr noundef readonly captures(none), ...) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @printf(ptr, ...)
 
-; CHECK: declare noundef i32 @putc(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @putc(i32 noundef, ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @putc(i32, ptr)
 
-; CHECK: declare noundef i32 @putchar(i32 noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @putchar(i32 noundef) [[NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @putchar(i32)
 
 ; CHECK-KNOWN: declare noundef i32 @putchar_unlocked(i32 noundef) [[NOFREE_NOUNWIND]]
 ; CHECK-UNKNOWN: declare i32 @putchar_unlocked(i32){{$}}
 declare i32 @putchar_unlocked(i32)
 
-; CHECK: declare noundef i32 @puts(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @puts(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @puts(ptr)
 
-; CHECK: declare noundef i64 @pwrite(i32 noundef, ptr noundef readonly captures(none), i64 noundef, i64 noundef) [[NOFREE]]
+; CHECK: declare noundef i64 @pwrite(i32 noundef, ptr noundef readonly captures(none), i64 noundef, i64 noundef) [[ARGMEMORERRNOMEMONLY_NOFREE:#[0-9]+]]
 declare i64 @pwrite(i32, ptr, i64, i64)
 
 ; CHECK: declare void @qsort(ptr noundef, i64 noundef, i64 noundef, ptr noundef captures(none)) [[NOFREE]]
 declare void @qsort(ptr, i64, i64, ptr)
 
-; CHECK: declare noundef i64 @read(i32 noundef, ptr noundef captures(none), i64 noundef) [[NOFREE]]
+; CHECK: declare noundef i64 @read(i32 noundef, ptr noundef captures(none), i64 noundef) [[ARGMEMRWORERRNOMEMONLY_NOFREE:#[0-9]+]]
 declare i64 @read(i32, ptr, i64)
 
-; CHECK: declare noundef i64 @readlink(ptr noundef readonly captures(none), ptr noundef captures(none), i64 noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i64 @readlink(ptr noundef readonly captures(none), ptr noundef captures(none), i64 noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i64 @readlink(ptr, ptr, i64)
 
-; CHECK: declare noalias noundef ptr @realloc(ptr allocptr captures(none), i64 noundef) [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC:#[0-9]+]]
+; CHECK: declare noalias noundef ptr @realloc(ptr allocptr captures(none), i64 noundef) [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC:#[0-9]+]]
 declare ptr @realloc(ptr, i64)
 
-; CHECK: declare noalias noundef ptr @reallocarray(ptr allocptr captures(none), i64 noundef, i64 noundef) [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE12_FAMILY_MALLOC:#[0-9]+]]
+; CHECK: declare noalias noundef ptr @reallocarray(ptr allocptr captures(none), i64 noundef, i64 noundef) [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE12_FAMILY_MALLOC:#[0-9]+]]
 declare ptr @reallocarray(ptr, i64, i64)
 
-; CHECK: declare noalias noundef ptr @reallocf(ptr allocptr captures(none), i64 noundef) [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]]
+; CHECK: declare noalias noundef ptr @reallocf(ptr allocptr captures(none), i64 noundef) [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]]
 declare ptr @reallocf(ptr, i64)
 
-; CHECK-AIX: declare noalias noundef ptr @vec_realloc(ptr allocptr captures(none), i64 noundef) [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCSIZE_FAMILY_VEC_MALLOC:#[0-9]+]]
+; CHECK-AIX: declare noalias noundef ptr @vec_realloc(ptr allocptr captures(none), i64 noundef) [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOUNWIND_WILLRETURN_ALLOCSIZE_FAMILY_VEC_MALLOC:#[0-9]+]]
 declare ptr @vec_realloc(ptr, i64)
 
-; CHECK: declare noundef ptr @realpath(ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef ptr @realpath(ptr noundef readonly captures(none), ptr noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @realpath(ptr, ptr)
 
-; CHECK: declare double @remainder(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @remainder(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @remainder(double, double)
 
-; CHECK: declare float @remainderf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @remainderf(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @remainderf(float, float)
 
-; CHECK: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @remainderl(x86_fp80, x86_fp80)
 
-; CHECK: declare noundef i32 @remove(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @remove(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @remove(ptr)
 
-; CHECK: declare double @remquo(double, double, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @remquo(double, double, ptr captures(none)) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @remquo(double, double, ptr)
 
-; CHECK: declare float @remquof(float, float, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @remquof(float, float, ptr captures(none)) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @remquof(float, float, ptr)
 
-; CHECK: declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr captures(none)) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr)
 
 
-; CHECK: declare double @fdim(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @fdim(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @fdim(double, double)
 
-; CHECK: declare float @fdimf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @fdimf(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @fdimf(float, float)
 
-; CHECK: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @fdiml(x86_fp80, x86_fp80)
 
-; CHECK: declare noundef i32 @rename(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @rename(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @rename(ptr, ptr)
 
 ; CHECK: declare void @rewind(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare void @rewind(ptr)
 
-; CHECK: declare double @rint(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @rint(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @rint(double)
 
-; CHECK: declare float @rintf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @rintf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @rintf(float)
 
-; CHECK: declare x86_fp80 @rintl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @rintl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @rintl(x86_fp80)
 
-; CHECK: declare noundef i32 @rmdir(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @rmdir(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @rmdir(ptr)
 
-; CHECK: declare double @round(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @round(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @round(double)
 
-; CHECK: declare float @roundf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @roundf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @roundf(float)
 
-; CHECK: declare x86_fp80 @roundl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @roundl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @roundl(x86_fp80)
 
-; CHECK: declare double @scalbln(double, i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @scalbln(double, i64) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @scalbln(double, i64)
 
-; CHECK: declare float @scalblnf(float, i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @scalblnf(float, i64) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @scalblnf(float, i64)
 
-; CHECK: declare x86_fp80 @scalblnl(x86_fp80, i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @scalblnl(x86_fp80, i64) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @scalblnl(x86_fp80, i64)
 
-; CHECK: declare double @scalbn(double, i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @scalbn(double, i32) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @scalbn(double, i32)
 
-; CHECK: declare float @scalbnf(float, i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @scalbnf(float, i32) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @scalbnf(float, i32)
 
-; CHECK: declare x86_fp80 @scalbnl(x86_fp80, i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @scalbnl(x86_fp80, i32) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @scalbnl(x86_fp80, i32)
 
-; CHECK: declare noundef i32 @scanf(ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @scanf(ptr noundef readonly captures(none), ...) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @scanf(ptr, ...)
 
 ; CHECK: declare void @setbuf(ptr noundef captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
 declare void @setbuf(ptr, ptr)
 
-; CHECK: declare noundef i32 @setitimer(i32 noundef, ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare noundef i32 @setitimer(i32 noundef, ptr noundef readonly captures(none), ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i32 @setitimer(i32, ptr, ptr)
 
 ; CHECK: declare noundef i32 @setvbuf(ptr noundef captures(none), ptr noundef, i32 noundef, i64 noundef) [[NOFREE_NOUNWIND]]
 declare i32 @setvbuf(ptr, ptr, i32, i64)
 
-; CHECK: declare double @sin(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @sin(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @sin(double)
 
-; CHECK: declare float @sinf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @sinf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @sinf(float)
 
-; CHECK: declare double @sinh(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @sinh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @sinh(double)
 
-; CHECK: declare float @sinhf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @sinhf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @sinhf(float)
 
-; CHECK: declare x86_fp80 @sinhl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @sinhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @sinhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @sinl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @sinl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @sinl(x86_fp80)
 
-; CHECK: declare noundef i32 @snprintf(ptr noalias noundef writeonly captures(none), i64 noundef, ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @snprintf(ptr noalias noundef writeonly captures(none), i64 noundef, ptr noundef readonly captures(none), ...) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @snprintf(ptr, i64, ptr, ...)
 
-; CHECK: declare noundef i32 @sprintf(ptr noalias noundef writeonly captures(none), ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @sprintf(ptr noalias noundef writeonly captures(none), ptr noundef readonly captures(none), ...) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @sprintf(ptr, ptr, ...)
 
-; CHECK: declare double @sqrt(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @sqrt(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @sqrt(double)
 
-; CHECK: declare float @sqrtf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @sqrtf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @sqrtf(float)
 
-; CHECK: declare x86_fp80 @sqrtl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @sqrtl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @sqrtl(x86_fp80)
 
-; CHECK: declare noundef i32 @sscanf(ptr noundef readonly captures(none), ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @sscanf(ptr noundef readonly captures(none), ptr noundef readonly captures(none), ...) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @sscanf(ptr, ptr, ...)
 
-; CHECK: declare noundef i32 @stat(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @stat(ptr noundef readonly captures(none), ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @stat(ptr, ptr)
 
-; CHECK-LINUX: declare noundef i32 @stat64(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK-LINUX: declare noundef i32 @stat64(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @stat64(ptr, ptr)
 
-; CHECK: declare noundef i32 @statvfs(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @statvfs(ptr noundef readonly captures(none), ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @statvfs(ptr, ptr)
 
 ; CHECK-LINUX: declare noundef i32 @statvfs64(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
@@ -993,7 +993,7 @@ declare ptr @strchr(ptr, i32)
 ; CHECK: declare i32 @strcmp(ptr captures(none), ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
 declare i32 @strcmp(ptr, ptr)
 
-; CHECK: declare i32 @strcoll(ptr captures(none), ptr captures(none)) [[NOFREE_NOUNWIND_READONLY_WILLRETURN]]
+; CHECK: declare i32 @strcoll(ptr readonly captures(none), ptr readonly captures(none)) [[ARGMEMORERRNOMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN:#[0-9]+]]
 declare i32 @strcoll(ptr, ptr)
 
 ; CHECK: declare ptr @strcpy(ptr noalias returned writeonly, ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
@@ -1002,7 +1002,7 @@ declare ptr @strcpy(ptr, ptr)
 ; CHECK: declare i64 @strcspn(ptr captures(none), ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
 declare i64 @strcspn(ptr, ptr)
 
-; CHECK: declare noalias ptr @strdup(ptr readonly captures(none)) [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC:#[0-9]+]]
+; CHECK: declare noalias ptr @strdup(ptr readonly captures(none)) [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC:#[0-9]+]]
 declare ptr @strdup(ptr)
 
 ; CHECK: declare i64 @strlen(ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@@ -1020,7 +1020,7 @@ declare i32 @strncmp(ptr, ptr, i64)
 ; CHECK: declare ptr @strncpy(ptr noalias returned writeonly, ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @strncpy(ptr, ptr, i64)
 
-; CHECK: declare noalias ptr @strndup(ptr readonly captures(none), i64 noundef) [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]]
+; CHECK: declare noalias ptr @strndup(ptr readonly captures(none), i64 noundef) [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC:#[0-9]+]]
 declare ptr @strndup(ptr, i64)
 
 ; CHECK: declare i64 @strnlen(ptr captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
@@ -1038,64 +1038,64 @@ declare i64 @strspn(ptr, ptr)
 ; CHECK: declare ptr @strstr(ptr, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
 declare ptr @strstr(ptr, ptr)
 
-; CHECK: declare double @strtod(ptr readonly, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @strtod(ptr readonly, ptr captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @strtod(ptr, ptr)
 
-; CHECK: declare float @strtof(ptr readonly, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @strtof(ptr readonly, ptr captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @strtof(ptr, ptr)
 
-; CHECK: declare ptr @strtok(ptr, ptr readonly captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @strtok(ptr, ptr readonly captures(none)) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare ptr @strtok(ptr, ptr)
 
-; CHECK: declare ptr @strtok_r(ptr, ptr readonly captures(none), ptr) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @strtok_r(ptr, ptr readonly captures(none), ptr) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare ptr @strtok_r(ptr, ptr, ptr)
 
-; CHECK: declare i64 @strtol(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare i64 @strtol(ptr readonly, ptr captures(none), i32) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i64 @strtol(ptr, ptr, i32)
 
-; CHECK: declare x86_fp80 @strtold(ptr readonly, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @strtold(ptr readonly, ptr captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @strtold(ptr, ptr)
 
-; CHECK: declare i64 @strtoll(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare i64 @strtoll(ptr readonly, ptr captures(none), i32) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i64 @strtoll(ptr, ptr, i32)
 
-; CHECK: declare i64 @strtoul(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare i64 @strtoul(ptr readonly, ptr captures(none), i32) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i64 @strtoul(ptr, ptr, i32)
 
-; CHECK: declare i64 @strtoull(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare i64 @strtoull(ptr readonly, ptr captures(none), i32) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i64 @strtoull(ptr, ptr, i32)
 
-; CHECK: declare i64 @strxfrm(ptr captures(none), ptr readonly captures(none), i64) [[NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare i64 @strxfrm(ptr captures(none), ptr readonly captures(none), i64) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i64 @strxfrm(ptr, ptr, i64)
 
-; CHECK: declare noundef i32 @system(ptr noundef readonly captures(none)) [[NOFREE]]
+; CHECK: declare noundef i32 @system(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEMONLY_NOFREE:#[0-9]+]]
 declare i32 @system(ptr)
 
-; CHECK: declare double @tan(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @tan(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @tan(double)
 
-; CHECK: declare float @tanf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @tanf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @tanf(float)
 
-; CHECK: declare double @tanh(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @tanh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare double @tanh(double)
 
-; CHECK: declare float @tanhf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @tanhf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare float @tanhf(float)
 
-; CHECK: declare x86_fp80 @tanhl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @tanhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @tanhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @tanl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @tanl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @tanl(x86_fp80)
 
-; CHECK: declare noundef i64 @times(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i64 @times(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i64 @times(ptr)
 
-; CHECK: declare noalias noundef ptr @tmpfile() [[NOFREE_NOUNWIND]]
+; CHECK: declare noalias noundef ptr @tmpfile() [[ERRNOMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @tmpfile()
 
-; CHECK-LINUX: declare noalias noundef ptr @tmpfile64() [[NOFREE_NOUNWIND]]
+; CHECK-LINUX: declare noalias noundef ptr @tmpfile64() [[NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @tmpfile64()
 
 ; CHECK: declare i32 @toascii(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
@@ -1110,49 +1110,49 @@ declare float @truncf(float)
 ; CHECK: declare x86_fp80 @truncl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
 declare x86_fp80 @truncl(x86_fp80)
 
-; CHECK: declare noundef i32 @uname(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @uname(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @uname(ptr)
 
-; CHECK: declare noundef i32 @ungetc(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @ungetc(i32 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @ungetc(i32, ptr)
 
-; CHECK: declare noundef i32 @unlink(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @unlink(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @unlink(ptr)
 
-; CHECK: declare noundef i32 @unsetenv(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @unsetenv(ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @unsetenv(ptr)
 
-; CHECK: declare noundef i32 @utime(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @utime(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @utime(ptr, ptr)
 
-; CHECK: declare noundef i32 @utimes(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @utimes(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @utimes(ptr, ptr)
 
-; CHECK: declare noalias noundef ptr @valloc(i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]]
+; CHECK: declare noalias noundef ptr @valloc(i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]]
 declare ptr @valloc(i64)
 
-; CHECK: declare noundef i32 @vfprintf(ptr noundef captures(none), ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @vfprintf(ptr noundef captures(none), ptr noundef readonly captures(none), ptr noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @vfprintf(ptr, ptr, ptr)
 
-; CHECK: declare noundef i32 @vfscanf(ptr noundef captures(none), ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @vfscanf(ptr noundef captures(none), ptr noundef readonly captures(none), ptr noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @vfscanf(ptr, ptr, ptr)
 
-; CHECK: declare noundef i32 @vprintf(ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @vprintf(ptr noundef readonly captures(none), ptr noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @vprintf(ptr, ptr)
 
-; CHECK: declare noundef i32 @vscanf(ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @vscanf(ptr noundef readonly captures(none), ptr noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @vscanf(ptr, ptr)
 
-; CHECK: declare noundef i32 @vsnprintf(ptr noundef captures(none), i64 noundef, ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @vsnprintf(ptr noundef captures(none), i64 noundef, ptr noundef readonly captures(none), ptr noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @vsnprintf(ptr, i64, ptr, ptr)
 
-; CHECK: declare noundef i32 @vsprintf(ptr noundef captures(none), ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @vsprintf(ptr noundef captures(none), ptr noundef readonly captures(none), ptr noundef) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @vsprintf(ptr, ptr, ptr)
 
-; CHECK: declare noundef i32 @vsscanf(ptr noundef readonly captures(none), ptr noundef readonly captures(none), ptr noundef) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i32 @vsscanf(ptr noundef readonly captures(none), ptr noundef readonly captures(none), ptr noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @vsscanf(ptr, ptr, ptr)
 
-; CHECK: declare noundef i64 @write(i32 noundef, ptr noundef readonly captures(none), i64 noundef) [[NOFREE]]
+; CHECK: declare noundef i64 @write(i32 noundef, ptr noundef readonly captures(none), i64 noundef) [[ARGMEMORERRNOMEMONLY_NOFREE:#[0-9]+]]
 declare i64 @write(i32, ptr, i64)
 
 ; CHECK: declare void @abort() [[NOFREE_COLD:#[0-9]+]]
@@ -1164,13 +1164,13 @@ declare void @__cxa_throw(ptr, ptr, ptr)
 ; CHECK: declare void @_ZSt9terminatev() [[NOFREE_COLD_NORETURN:#[0-9]+]]
 declare void @_ZSt9terminatev()
 
-; CHECK: declare void @sincos(double, ptr writeonly captures(none), ptr writeonly captures(none)) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare void @sincos(double, ptr writeonly captures(none), ptr writeonly captures(none)) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare void @sincos(double, ptr, ptr)
 
-; CHECK: declare void @sincosf(float, ptr writeonly captures(none), ptr writeonly captures(none)) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare void @sincosf(float, ptr writeonly captures(none), ptr writeonly captures(none)) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare void @sincosf(float, ptr, ptr)
 
-; CHECK: declare void @sincosl(x86_fp80, ptr writeonly captures(none), ptr writeonly captures(none)) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare void @sincosl(x86_fp80, ptr writeonly captures(none), ptr writeonly captures(none)) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare void @sincosl(x86_fp80, ptr, ptr)
 
 ; memset_pattern{4,8,16} aren't available everywhere.
@@ -1183,29 +1183,37 @@ declare void @memset_pattern16(ptr, ptr, i64)
 
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn }
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(write) }
+; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(errnomem: write) }
 ; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(argmem: write) }
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind }
-; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized,aligned") allocsize(1) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
-; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
+; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_NOUNWIND]] = { nofree nounwind memory(errnomem: readwrite) }
+; CHECK-DAG: attributes [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND]] = { nofree nounwind memory(argmem: read, errnomem: readwrite) }
+; CHECK-DAG: attributes [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND]] = { nofree nounwind memory(argmem: readwrite, errnomem: readwrite) }
+; CHECK-DAG: attributes [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized,aligned") allocsize(1) memory(inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="malloc" }
+; CHECK-DAG: attributes [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) memory(inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="malloc" }
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(read) }
+; CHECK-DAG: attributes [[ARGMEMORERRNOMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: read, errnomem: readwrite) }
 ; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite) }
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind memory(read) }
 ; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_FREE_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
-; CHECK-DAG: attributes [[NOFREE_WILLRETURN]] = { mustprogress nofree willreturn }
-; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
+; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_WILLRETURN]] = { mustprogress nofree willreturn memory(errnomem: readwrite) }
+; CHECK-DAG: attributes [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="malloc" }
 ; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: read) }
+; CHECK-DAG: attributes [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, errnomem: readwrite) }
 ; CHECK-DAG: attributes [[NOFREE]] = { nofree }
+; CHECK-DAG: attributes [[ARGMEMORERRNOMEMONLY_NOFREE]] = { nofree memory(argmem: read, errnomem: readwrite) }
+; CHECK-DAG: attributes [[ARGMEMRWORERRNOMEMONLY_NOFREE]] = { nofree memory(argmem: readwrite, errnomem: readwrite) }
 ; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { nofree nounwind memory(argmem: readwrite) }
-; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
-; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE12_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1,2) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
-; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
+; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="malloc" }
+; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE12_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1,2) memory(argmem: readwrite, inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="malloc" }
+; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn memory(argmem: read, inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="malloc" }
 ; CHECK-DAG: attributes [[NOFREE_COLD]] = { cold nofree }
 ; CHECK-DAG: attributes [[NOFREE_COLD_NORETURN]] = { cold nofree noreturn }
 ; CHECK-DAG: attributes [[COLD_NORETURN]] = { cold noreturn }
 
 ; CHECK-NVPTX-DAG: attributes [[NOFREE_NOUNWIND_READNONE]] = { nofree nosync nounwind memory(none) }
 
-; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE0_FAMILY_VEC_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="vec_malloc" }
+; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE0_FAMILY_VEC_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="vec_malloc" }
 ; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_FAMILY_VEC_MALLOC]] = { mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="vec_malloc" }
-; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCSIZE_FAMILY_VEC_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="vec_malloc" }
-; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE01_FAMILY_VEC_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) memory(inaccessiblemem: readwrite) "alloc-family"="vec_malloc" }
+; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORARGMEMORERRNOMEMONLY_NOUNWIND_WILLRETURN_ALLOCSIZE_FAMILY_VEC_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="vec_malloc" }
+; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE01_FAMILY_VEC_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) memory(inaccessiblemem: readwrite, errnomem: readwrite) "alloc-family"="vec_malloc" }

>From a78d5bd5825f233aa559cec98275afadb735871e Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 25 Feb 2025 15:43:24 +0100
Subject: [PATCH 2/4] !fixup drop writeonly

---
 llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index c2bd4b0ec6ff1..5a03a178ada4a 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1410,7 +1410,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_truncl:
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotFreeMemory(F);
-    Changed |= setOnlyWritesMemory(F);
     Changed |= setWillReturn(F);
     break;
   case LibFunc_sincos:

>From b4c94f5e452806ae1daab255b8d9d778674fd699 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 25 Feb 2025 16:12:17 +0100
Subject: [PATCH 3/4] !fixup previously missing strtok arg0 as writeonly,
 update tests

---
 llvm/lib/Transforms/Utils/BuildLibCalls.cpp   |  1 +
 .../Transforms/InferFunctionAttrs/annotate.ll | 59 +++++++++----------
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 5a03a178ada4a..ec829a2d2e8af 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -437,6 +437,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setWillReturn(F);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
+    Changed |= setOnlyAccessesArgMemory(F);
     break;
   case LibFunc_scanf:
     Changed |= setRetAndArgsNoUndef(F);
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index e1715c511d5a4..62e765077676c 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -195,7 +195,7 @@ declare double @__sinpi(double)
 ; CHECK: declare float @__sinpif(float)
 declare float @__sinpif(float)
 
-; CHECK: declare i32 @abs(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
+; CHECK: declare i32 @abs(i32) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i32 @abs(i32)
 
 ; CHECK: declare noundef i32 @access(ptr noundef readonly captures(none), i32 noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
@@ -295,13 +295,13 @@ declare ptr @calloc(i64, i64)
 ; CHECK-AIX: declare noalias noundef ptr @vec_calloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE01_FAMILY_VEC_MALLOC:#[0-9]+]]
 declare ptr @vec_calloc(i64, i64)
 
-; CHECK: declare double @cbrt(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @cbrt(double) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @cbrt(double)
 
-; CHECK: declare float @cbrtf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @cbrtf(float) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @cbrtf(float)
 
-; CHECK: declare x86_fp80 @cbrtl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @cbrtl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @cbrtl(x86_fp80)
 
 ; CHECK: declare double @ceil(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
@@ -330,13 +330,13 @@ declare void @clearerr(ptr)
 ; CHECK: declare noundef i32 @closedir(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @closedir(ptr)
 
-; CHECK: declare double @copysign(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @copysign(double, double) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @copysign(double, double)
 
-; CHECK: declare float @copysignf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @copysignf(float, float) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @copysignf(float, float)
 
-; CHECK: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @copysignl(x86_fp80, x86_fp80)
 
 ; CHECK: declare double @cos(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
@@ -387,13 +387,13 @@ declare float @expm1f(float)
 ; CHECK: declare x86_fp80 @expm1l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @expm1l(x86_fp80)
 
-; CHECK: declare double @fabs(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @fabs(double) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @fabs(double)
 
-; CHECK: declare float @fabsf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @fabsf(float) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @fabsf(float)
 
-; CHECK: declare x86_fp80 @fabsl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @fabsl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @fabsl(x86_fp80)
 
 ; CHECK: declare noundef i32 @fclose(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
@@ -411,14 +411,14 @@ declare i32 @ferror(ptr)
 ; CHECK: declare noundef i32 @fflush(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
 declare i32 @fflush(ptr)
 
-; CHECK: declare i32 @ffs(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i32 @ffs(i32) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i32 @ffs(i32)
 
-; CHECK-KNOWN: declare i32 @ffsl(i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK-KNOWN: declare i32 @ffsl(i64) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 ; CHECK-UNKNOWN: declare i32 @ffsl(i64){{$}}
 declare i32 @ffsl(i64)
 
-; CHECK-KNOWN: declare i32 @ffsll(i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK-KNOWN: declare i32 @ffsll(i64) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 ; CHECK-UNKNOWN: declare i32 @ffsll(i64){{$}}
 declare i32 @ffsll(i64)
 
@@ -455,22 +455,22 @@ declare i32 @flsl(i64)
 ; CHECK: declare i32 @flsll(i64)
 declare i32 @flsll(i64)
 
-; CHECK: declare double @fmax(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @fmax(double, double) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @fmax(double, double)
 
-; CHECK: declare float @fmaxf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @fmaxf(float, float) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @fmaxf(float, float)
 
-; CHECK: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @fmaxl(x86_fp80, x86_fp80)
 
-; CHECK: declare double @fmin(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @fmin(double, double) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @fmin(double, double)
 
-; CHECK: declare float @fminf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @fminf(float, float) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @fminf(float, float)
 
-; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @fminl(x86_fp80, x86_fp80)
 
 ; CHECK: declare double @fmod(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
@@ -598,13 +598,13 @@ declare float @hypotf(float, float)
 ; CHECK: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
 declare x86_fp80 @hypotl(x86_fp80, x86_fp80)
 
-; CHECK: declare i32 @isascii(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i32 @isascii(i32) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i32 @isascii(i32)
 
-; CHECK: declare i32 @isdigit(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i32 @isdigit(i32) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i32 @isdigit(i32)
 
-; CHECK: declare i64 @labs(i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i64 @labs(i64) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i64 @labs(i64)
 
 ; CHECK: declare noundef i32 @lchown(ptr noundef readonly captures(none), i32 noundef, i32 noundef) [[ARGMEMORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
@@ -619,7 +619,7 @@ declare float @ldexpf(float, i32)
 ; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32) [[ERRNOMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @ldexpl(x86_fp80, i32)
 
-; CHECK: declare i64 @llabs(i64) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i64 @llabs(i64) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i64 @llabs(i64)
 
 ; CHECK: declare double @log(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
@@ -1044,10 +1044,10 @@ declare double @strtod(ptr, ptr)
 ; CHECK: declare float @strtof(ptr readonly, ptr captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @strtof(ptr, ptr)
 
-; CHECK: declare ptr @strtok(ptr, ptr readonly captures(none)) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare ptr @strtok(ptr, ptr readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare ptr @strtok(ptr, ptr)
 
-; CHECK: declare ptr @strtok_r(ptr, ptr readonly captures(none), ptr) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare ptr @strtok_r(ptr, ptr readonly captures(none), ptr) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare ptr @strtok_r(ptr, ptr, ptr)
 
 ; CHECK: declare i64 @strtol(ptr readonly, ptr captures(none), i32) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
@@ -1098,16 +1098,16 @@ declare ptr @tmpfile()
 ; CHECK-LINUX: declare noalias noundef ptr @tmpfile64() [[NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @tmpfile64()
 
-; CHECK: declare i32 @toascii(i32) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare i32 @toascii(i32) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare i32 @toascii(i32)
 
-; CHECK: declare double @trunc(double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare double @trunc(double) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @trunc(double)
 
-; CHECK: declare float @truncf(float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @truncf(float) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @truncf(float)
 
-; CHECK: declare x86_fp80 @truncl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @truncl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @truncl(x86_fp80)
 
 ; CHECK: declare noundef i32 @uname(ptr noundef captures(none)) [[ARGMEMRWORERRNOMEM_NOFREE_NOUNWIND:#[0-9]+]]
@@ -1182,7 +1182,6 @@ declare void @memset_pattern8(ptr, ptr, i64)
 declare void @memset_pattern16(ptr, ptr, i64)
 
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn }
-; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(write) }
 ; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(errnomem: write) }
 ; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(argmem: write) }
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind }

>From e638af7b89f3144863e32721859580a58959cbe1 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 25 Feb 2025 17:18:50 +0100
Subject: [PATCH 4/4] !fixup fix test acos readonly w/ errnomem

---
 .../Transforms/InferFunctionAttrs/readonly_and_writeonly.ll   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InferFunctionAttrs/readonly_and_writeonly.ll b/llvm/test/Transforms/InferFunctionAttrs/readonly_and_writeonly.ll
index c1a5f11cf94ab..40a1f64a72143 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/readonly_and_writeonly.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/readonly_and_writeonly.ll
@@ -2,7 +2,7 @@
 
 ; Frontends can emit math functions with 'readonly', don't crash on it.
 
-; CHECK: declare double @acos(double) [[NOFREE_NOUNWIND_WILLRETURN_READNONE:#[0-9]+]]
+; CHECK: declare double @acos(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_READNONE:#[0-9]+]]
 declare double @acos(double) readonly
 
-; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_READNONE]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
+; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_READNONE]] = { mustprogress nofree nounwind willreturn memory(errnomem: read) }



More information about the llvm-commits mailing list