[llvm] r365336 - Add, and infer, a nofree function attribute

Brian Homerding via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 8 08:57:56 PDT 2019


Author: homerdin
Date: Mon Jul  8 08:57:56 2019
New Revision: 365336

URL: http://llvm.org/viewvc/llvm-project?rev=365336&view=rev
Log:
Add, and infer, a nofree function attribute

This patch adds a function attribute, nofree, to indicate that a function does
not, directly or indirectly, call a memory-deallocation function (e.g., free,
C++'s operator delete).

Reviewers: jdoerfert

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

Added:
    llvm/trunk/test/Transforms/FunctionAttrs/nofree.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
    llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/IR/Attributes.td
    llvm/trunk/include/llvm/IR/Function.h
    llvm/trunk/lib/Analysis/MemoryBuiltins.cpp
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/IR/Attributes.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
    llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp
    llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
    llvm/trunk/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
    llvm/trunk/test/Bitcode/attributes.ll
    llvm/trunk/test/CodeGen/AMDGPU/inline-attr.ll
    llvm/trunk/test/CodeGen/X86/no-plt-libcalls.ll
    llvm/trunk/test/Feature/OperandBundles/function-attrs.ll
    llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll
    llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
    llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
    llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll
    llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
    llvm/trunk/test/Transforms/LICM/strlen.ll
    llvm/trunk/test/Transforms/LoopIdiom/basic.ll

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Mon Jul  8 08:57:56 2019
@@ -1453,6 +1453,14 @@ example:
     duplicated by inlining. That implies that the function has
     internal linkage and only has one call site, so the original
     call is dead after inlining.
+``nofree``
+    This function attribute indicates that the function does not, directly or
+    indirectly, call a memory-deallocation function (free, for example). As a
+    result, uncaptured pointers that are known to be dereferenceable prior to a
+    call to a function with the ``nofree`` attribute are still known to be
+    dereferenceable after the call (the capturing condition is necessary in
+    environments where the function might communicate the pointer to another thread
+    which then deallocates the memory).
 ``noimplicitfloat``
     This attributes disables implicit floating-point instructions.
 ``noinline``

Modified: llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h (original)
+++ llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h Mon Jul  8 08:57:56 2019
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Analysis/TargetFolder.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstVisitor.h"
@@ -83,6 +84,15 @@ bool isMallocOrCallocLikeFn(const Value
 bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
                    bool LookThroughBitCast = false);
 
+/// Tests if a value is a call or invoke to a library function that
+/// reallocates memory (e.g., realloc).
+bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
+                     bool LookThroughBitCast = false);
+
+/// Tests if a function is a call or invoke to a library function that
+/// reallocates memory (e.g., realloc).
+bool isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI);
+
 //===----------------------------------------------------------------------===//
 //  malloc Call Utility Functions.
 //
@@ -134,6 +144,9 @@ inline CallInst *extractCallocCall(Value
 //  free Call Utility Functions.
 //
 
+/// isLibFreeFunction - Returns true if the function is a builtin free()
+bool isLibFreeFunction(const Function *F, const LibFunc TLIFn);
+
 /// isFreeCall - Returns non-null if the value is a call to the builtin free()
 const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI);
 

Modified: llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def (original)
+++ llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def Mon Jul  8 08:57:56 2019
@@ -11,6 +11,15 @@
 // Which is defined depends on whether TLI_DEFINE_ENUM is defined or
 // TLI_DEFINE_STRING is defined. Only one should be defined at a time.
 
+// NOTE: The nofree attribute is added to Libfuncs which are not
+// listed as free or realloc functions in MemoryBuiltins.cpp
+//
+// When adding a function which frees memory include the LibFunc
+// in lib/Analysis/MemoryBuiltins.cpp "isLibFreeFunction".
+//
+// When adding a LibFunc which reallocates memory include the LibFunc
+// in lib/Analysis/MemoryBuiltins.cpp "AllocationFnData[]".
+
 #if !(defined(TLI_DEFINE_ENUM) || defined(TLI_DEFINE_STRING))
 #error "Must define TLI_DEFINE_ENUM or TLI_DEFINE_STRING for TLI .def."
 #elif defined(TLI_DEFINE_ENUM) && defined(TLI_DEFINE_STRING)

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Mon Jul  8 08:57:56 2019
@@ -629,6 +629,7 @@ enum AttributeKindCodes {
   ATTR_KIND_SPECULATIVE_LOAD_HARDENING = 59,
   ATTR_KIND_IMMARG = 60,
   ATTR_KIND_WILLRETURN = 61,
+  ATTR_KIND_NOFREE = 62
 };
 
 enum ComdatSelectionKindCodes {

Modified: llvm/trunk/include/llvm/IR/Attributes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.td?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.td (original)
+++ llvm/trunk/include/llvm/IR/Attributes.td Mon Jul  8 08:57:56 2019
@@ -85,6 +85,9 @@ def NoCapture : EnumAttr<"nocapture">;
 /// Call cannot be duplicated.
 def NoDuplicate : EnumAttr<"noduplicate">;
 
+/// Function does not deallocate memory.
+def NoFree : EnumAttr<"nofree">;
+
 /// Disable implicit floating point insts.
 def NoImplicitFloat : EnumAttr<"noimplicitfloat">;
 

Modified: llvm/trunk/include/llvm/IR/Function.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Function.h?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Function.h (original)
+++ llvm/trunk/include/llvm/IR/Function.h Mon Jul  8 08:57:56 2019
@@ -564,6 +564,14 @@ public:
     addFnAttr(Attribute::Speculatable);
   }
 
+  /// Determine if the call might deallocate memory.
+  bool doesNotFreeMemory() const {
+    return onlyReadsMemory() || hasFnAttribute(Attribute::NoFree);
+  }
+  void setDoesNotFreeMemory() {
+    addFnAttr(Attribute::NoFree);
+  }
+
   /// Determine if the function is known not to recurse, directly or
   /// indirectly.
   bool doesNotRecurse() const {

Modified: llvm/trunk/lib/Analysis/MemoryBuiltins.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryBuiltins.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/MemoryBuiltins.cpp (original)
+++ llvm/trunk/lib/Analysis/MemoryBuiltins.cpp Mon Jul  8 08:57:56 2019
@@ -263,6 +263,19 @@ bool llvm::isAllocLikeFn(const Value *V,
   return getAllocationData(V, AllocLike, TLI, LookThroughBitCast).hasValue();
 }
 
+/// Tests if a value is a call or invoke to a library function that
+/// reallocates memory (e.g., realloc).
+bool llvm::isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
+                     bool LookThroughBitCast) {
+  return getAllocationData(V, ReallocLike, TLI, LookThroughBitCast).hasValue();
+}
+
+/// Tests if a functions is a call or invoke to a library function that
+/// reallocates memory (e.g., realloc).
+bool llvm::isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI) {
+  return getAllocationDataForFunction(F, ReallocLike, TLI).hasValue();
+}
+
 /// extractMallocCall - Returns the corresponding CallInst if the instruction
 /// is a malloc call.  Since CallInst::CreateMalloc() only creates calls, we
 /// ignore InvokeInst here.
@@ -358,19 +371,8 @@ const CallInst *llvm::extractCallocCall(
   return isCallocLikeFn(I, TLI) ? cast<CallInst>(I) : nullptr;
 }
 
-/// isFreeCall - Returns non-null if the value is a call to the builtin free()
-const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
-  bool IsNoBuiltinCall;
-  const Function *Callee =
-      getCalledFunction(I, /*LookThroughBitCast=*/false, IsNoBuiltinCall);
-  if (Callee == nullptr || IsNoBuiltinCall)
-    return nullptr;
-
-  StringRef FnName = Callee->getName();
-  LibFunc TLIFn;
-  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
-    return nullptr;
-
+/// isLibFreeFunction - Returns true if the function is a builtin free()
+bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
   unsigned ExpectedNumParams;
   if (TLIFn == LibFunc_free ||
       TLIFn == LibFunc_ZdlPv || // operator delete(void*)
@@ -401,22 +403,39 @@ const CallInst *llvm::isFreeCall(const V
            TLIFn == LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t) // delete[](void*, align_val_t, nothrow)
     ExpectedNumParams = 3;
   else
-    return nullptr;
+    return false;
 
   // Check free prototype.
   // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
   // attribute will exist.
-  FunctionType *FTy = Callee->getFunctionType();
+  FunctionType *FTy = F->getFunctionType();
   if (!FTy->getReturnType()->isVoidTy())
-    return nullptr;
+    return false;
   if (FTy->getNumParams() != ExpectedNumParams)
+    return false;
+  if (FTy->getParamType(0) != Type::getInt8PtrTy(F->getContext()))
+    return false;
+
+  return true;
+}
+
+/// isFreeCall - Returns non-null if the value is a call to the builtin free()
+const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
+  bool IsNoBuiltinCall;
+  const Function *Callee =
+      getCalledFunction(I, /*LookThroughBitCast=*/false, IsNoBuiltinCall);
+  if (Callee == nullptr || IsNoBuiltinCall)
     return nullptr;
-  if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext()))
+
+  StringRef FnName = Callee->getName();
+  LibFunc TLIFn;
+  if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn))
     return nullptr;
 
-  return dyn_cast<CallInst>(I);
+  return isLibFreeFunction(Callee, TLIFn) ? dyn_cast<CallInst>(I) : nullptr;
 }
 
+
 //===----------------------------------------------------------------------===//
 //  Utility functions to compute size of objects.
 //

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Mon Jul  8 08:57:56 2019
@@ -650,6 +650,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(nobuiltin);
   KEYWORD(nocapture);
   KEYWORD(noduplicate);
+  KEYWORD(nofree);
   KEYWORD(noimplicitfloat);
   KEYWORD(noinline);
   KEYWORD(norecurse);

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Jul  8 08:57:56 2019
@@ -1280,6 +1280,7 @@ bool LLParser::ParseFnAttributeValuePair
     case lltok::kw_naked: B.addAttribute(Attribute::Naked); break;
     case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break;
     case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break;
+    case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break;
     case lltok::kw_noimplicitfloat:
       B.addAttribute(Attribute::NoImplicitFloat); break;
     case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break;

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Mon Jul  8 08:57:56 2019
@@ -195,6 +195,7 @@ enum Kind {
   kw_nobuiltin,
   kw_nocapture,
   kw_noduplicate,
+  kw_nofree,
   kw_noimplicitfloat,
   kw_noinline,
   kw_norecurse,

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Mon Jul  8 08:57:56 2019
@@ -1278,6 +1278,8 @@ static uint64_t getRawAttributeMask(Attr
     return 1ULL << 61;
   case Attribute::WillReturn:
     return 1ULL << 62;
+  case Attribute::NoFree:
+    return 1ULL << 63;
   case Attribute::Dereferenceable:
     llvm_unreachable("dereferenceable attribute not supported in raw format");
     break;
@@ -1442,6 +1444,8 @@ static Attribute::AttrKind getAttrFromCo
     return Attribute::NoCapture;
   case bitc::ATTR_KIND_NO_DUPLICATE:
     return Attribute::NoDuplicate;
+  case bitc::ATTR_KIND_NOFREE:
+    return Attribute::NoFree;
   case bitc::ATTR_KIND_NO_IMPLICIT_FLOAT:
     return Attribute::NoImplicitFloat;
   case bitc::ATTR_KIND_NO_INLINE:

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Mon Jul  8 08:57:56 2019
@@ -639,6 +639,8 @@ static uint64_t getAttrKindEncoding(Attr
     return bitc::ATTR_KIND_NO_CAPTURE;
   case Attribute::NoDuplicate:
     return bitc::ATTR_KIND_NO_DUPLICATE;
+  case Attribute::NoFree:
+    return bitc::ATTR_KIND_NOFREE;
   case Attribute::NoImplicitFloat:
     return bitc::ATTR_KIND_NO_IMPLICIT_FLOAT;
   case Attribute::NoInline:

Modified: llvm/trunk/lib/IR/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Attributes.cpp (original)
+++ llvm/trunk/lib/IR/Attributes.cpp Mon Jul  8 08:57:56 2019
@@ -321,6 +321,8 @@ std::string Attribute::getAsString(bool
     return "nocapture";
   if (hasAttribute(Attribute::NoDuplicate))
     return "noduplicate";
+  if (hasAttribute(Attribute::NoFree))
+    return "nofree";
   if (hasAttribute(Attribute::NoImplicitFloat))
     return "noimplicitfloat";
   if (hasAttribute(Attribute::NoInline))

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Mon Jul  8 08:57:56 2019
@@ -1497,6 +1497,7 @@ static bool isFuncOnlyAttr(Attribute::At
   case Attribute::NoCfCheck:
   case Attribute::NoUnwind:
   case Attribute::NoInline:
+  case Attribute::NoFree:
   case Attribute::AlwaysInline:
   case Attribute::OptimizeForSize:
   case Attribute::StackProtect:

Modified: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp Mon Jul  8 08:57:56 2019
@@ -27,6 +27,7 @@
 #include "llvm/Analysis/CallGraphSCCPass.h"
 #include "llvm/Analysis/CaptureTracking.h"
 #include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
 #include "llvm/Analysis/MemoryLocation.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/Argument.h"
@@ -75,6 +76,7 @@ STATISTIC(NumNoAlias, "Number of functio
 STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
 STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
 STATISTIC(NumNoUnwind, "Number of functions marked as nounwind");
+STATISTIC(NumNoFree, "Number of functions marked as nofree");
 
 // FIXME: This is disabled by default to avoid exposing security vulnerabilities
 // in C/C++ code compiled by clang:
@@ -88,6 +90,10 @@ static cl::opt<bool> DisableNoUnwindInfe
     "disable-nounwind-inference", cl::Hidden,
     cl::desc("Stop inferring nounwind attribute during function-attrs pass"));
 
+static cl::opt<bool> DisableNoFreeInference(
+    "disable-nofree-inference", cl::Hidden,
+    cl::desc("Stop inferring nofree attribute during function-attrs pass"));
+
 namespace {
 
 using SCCNodeSet = SmallSetVector<Function *, 8>;
@@ -1227,6 +1233,25 @@ static bool InstrBreaksNonThrowing(Instr
   return true;
 }
 
+/// Helper for NoFree inference predicate InstrBreaksAttribute.
+static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes) {
+  CallSite CS(&I);
+  if (!CS)
+    return false;
+
+  Function *Callee = CS.getCalledFunction();
+  if (!Callee)
+    return true;
+
+  if (Callee->doesNotFreeMemory())
+    return false;
+
+  if (SCCNodes.count(Callee) > 0)
+    return false;
+
+  return true;
+}
+
 /// Infer attributes from all functions in the SCC by scanning every
 /// instruction for compliance to the attribute assumptions. Currently it
 /// does:
@@ -1280,6 +1305,29 @@ static bool inferAttrsFromFunctionBodies
         },
         /* RequiresExactDefinition= */ true});
 
+  if (!DisableNoFreeInference)
+    // Request to infer nofree attribute for all the functions in the SCC if
+    // every callsite within the SCC does not directly or indirectly free
+    // memory (except for calls to functions within the SCC). Note that nofree
+    // attribute suffers from derefinement - results may change depending on
+    // how functions are optimized. Thus it can be inferred only from exact
+    // definitions.
+    AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
+        Attribute::NoFree,
+        // Skip functions known not to free memory.
+        [](const Function &F) { return F.doesNotFreeMemory(); },
+        // Instructions that break non-deallocating assumption.
+        [SCCNodes](Instruction &I) {
+          return InstrBreaksNoFree(I, SCCNodes);
+        },
+        [](Function &F) {
+          LLVM_DEBUG(dbgs()
+                     << "Adding nofree attr to fn " << F.getName() << "\n");
+          F.setDoesNotFreeMemory();
+          ++NumNoFree;
+        },
+        /* RequiresExactDefinition= */ true});
+
   // Perform all the requested attribute inference actions.
   return AI.run(SCCNodes);
 }
@@ -1322,7 +1370,8 @@ static bool addNoRecurseAttrs(const SCCN
 }
 
 template <typename AARGetterT>
-static bool deriveAttrsInPostOrder(SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
+static bool deriveAttrsInPostOrder(SCCNodeSet &SCCNodes,
+                                   AARGetterT &&AARGetter,
                                    bool HasUnknownCall) {
   bool Changed = false;
 
@@ -1353,6 +1402,11 @@ PreservedAnalyses PostOrderFunctionAttrs
   FunctionAnalysisManager &FAM =
       AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
 
+  const ModuleAnalysisManager &MAM =
+      AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
+  assert(C.size() > 0 && "Cannot handle an empty SCC!");
+  Module &M = *C.begin()->getFunction().getParent();
+
   // We pass a lambda into functions to wire them up to the analysis manager
   // for getting function analyses.
   auto AARGetter = [&](Function &F) -> AAResults & {

Modified: llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp Mon Jul  8 08:57:56 2019
@@ -22,6 +22,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Type.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
 
 using namespace llvm;
 
@@ -120,6 +121,13 @@ static bool setNonLazyBind(Function &F)
   return true;
 }
 
+static bool setDoesNotFreeMemory(Function &F) {
+  if (F.hasFnAttribute(Attribute::NoFree))
+    return false;
+  F.addFnAttr(Attribute::NoFree);
+  return true;
+}
+
 bool llvm::inferLibFuncAttributes(Module *M, StringRef Name,
                                   const TargetLibraryInfo &TLI) {
   Function *F = M->getFunction(Name);
@@ -135,6 +143,9 @@ bool llvm::inferLibFuncAttributes(Functi
 
   bool Changed = false;
 
+  if(!isLibFreeFunction(&F, TheLibFunc) && !isReallocLikeFn(&F,  &TLI))
+    Changed |= setDoesNotFreeMemory(F);
+
   if (F.getParent() != nullptr && F.getParent()->getRtLibUseGOT())
     Changed |= setNonLazyBind(F);
 

Modified: llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp Mon Jul  8 08:57:56 2019
@@ -814,6 +814,7 @@ Function *CodeExtractor::constructFuncti
       case Attribute::InlineHint:
       case Attribute::MinSize:
       case Attribute::NoDuplicate:
+      case Attribute::NoFree:
       case Attribute::NoImplicitFloat:
       case Attribute::NoInline:
       case Attribute::NonLazyBind:

Modified: llvm/trunk/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll (original)
+++ llvm/trunk/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll Mon Jul  8 08:57:56 2019
@@ -73,11 +73,11 @@ declare void @callee(i32* %p) nounwind
 declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1) nounwind
 
 ; CHECK: attributes #0 = { norecurse nounwind readnone }
-; CHECK: attributes #1 = { norecurse nounwind writeonly }
+; CHECK: attributes #1 = { nofree norecurse nounwind writeonly }
 ; CHECK: attributes #2 = { nounwind readonly }
 ; CHECK: attributes #3 = { nounwind }
 ; CHECK: attributes #4 = { nounwind readnone }
-; CHECK: attributes #5 = { norecurse nounwind }
+; CHECK: attributes #5 = { nofree norecurse nounwind }
 ; CHECK: attributes #6 = { argmemonly nounwind }
 
 ; Root note.

Modified: llvm/trunk/test/Bitcode/attributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Bitcode/attributes.ll (original)
+++ llvm/trunk/test/Bitcode/attributes.ll Mon Jul  8 08:57:56 2019
@@ -204,7 +204,7 @@ define void @f34()
 ; CHECK: define void @f34()
 {
         call void @nobuiltin() nobuiltin
-; CHECK: call void @nobuiltin() #37
+; CHECK: call void @nobuiltin() #38
         ret void;
 }
 
@@ -357,6 +357,11 @@ define void @f60() willreturn
   ret void
 }
 
+; CHECK: define void @f61() #37
+define void @f61() nofree {
+  ret void
+}
+
 ; CHECK: attributes #0 = { noreturn }
 ; CHECK: attributes #1 = { nounwind }
 ; CHECK: attributes #2 = { readnone }
@@ -394,4 +399,5 @@ define void @f60() willreturn
 ; CHECK: attributes #34 = { sanitize_hwaddress }
 ; CHECK: attributes #35 = { shadowcallstack }
 ; CHECK: attributes #36 = { willreturn }
-; CHECK: attributes #37 = { nobuiltin }
+; CHECK: attributes #37 = { nofree }
+; CHECK: attributes #38 = { nobuiltin }

Modified: llvm/trunk/test/CodeGen/AMDGPU/inline-attr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AMDGPU/inline-attr.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AMDGPU/inline-attr.ll (original)
+++ llvm/trunk/test/CodeGen/AMDGPU/inline-attr.ll Mon Jul  8 08:57:56 2019
@@ -7,13 +7,13 @@
 ; GCN: %mul.i = fmul float %load, 1.500000e+01
 
 ; UNSAFE: attributes #0 = { norecurse nounwind readnone "less-precise-fpmad"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "unsafe-fp-math"="true" }
-; UNSAFE: attributes #1 = { norecurse nounwind "less-precise-fpmad"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "unsafe-fp-math"="true" }
+; UNSAFE: attributes #1 = { nofree norecurse nounwind "less-precise-fpmad"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "unsafe-fp-math"="true" }
 
 ; NOINFS: attributes #0 = { norecurse nounwind readnone "no-infs-fp-math"="true" }
-; NOINFS: attributes #1 = { norecurse nounwind "less-precise-fpmad"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="false" "unsafe-fp-math"="false" }
+; NOINFS: attributes #1 = { nofree norecurse nounwind "less-precise-fpmad"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="false" "unsafe-fp-math"="false" }
 
 ; NONANS: attributes #0 = { norecurse nounwind readnone "no-nans-fp-math"="true" }
-; NONANS: attributes #1 = { norecurse nounwind "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="true" "unsafe-fp-math"="false" }
+; NONANS: attributes #1 = { nofree norecurse nounwind "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="true" "unsafe-fp-math"="false" }
 
 define float @foo(float %x) #0 {
 entry:

Modified: llvm/trunk/test/CodeGen/X86/no-plt-libcalls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/no-plt-libcalls.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/no-plt-libcalls.ll (original)
+++ llvm/trunk/test/CodeGen/X86/no-plt-libcalls.ll Mon Jul  8 08:57:56 2019
@@ -12,7 +12,7 @@ define void @printf_call() {
   ret void
 }
 
-; CHECK: Function Attrs: nounwind nonlazybind
+; CHECK: Function Attrs: nofree nounwind nonlazybind
 ; CHECK-NEXT: declare i32 @puts(i8* nocapture readonly)
 
 !llvm.module.flags = !{!0}

Modified: llvm/trunk/test/Feature/OperandBundles/function-attrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/OperandBundles/function-attrs.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Feature/OperandBundles/function-attrs.ll (original)
+++ llvm/trunk/test/Feature/OperandBundles/function-attrs.ll Mon Jul  8 08:57:56 2019
@@ -6,7 +6,7 @@ declare void @f_readnone() readnone
 define void @test_0(i32* %x) {
 ; FunctionAttrs must not infer readonly / readnone for %x
 
-; CHECK-LABEL: define void @test_0(i32* %x) {
+; CHECK-LABEL: define void @test_0(i32* %x) #2 {
  entry:
  ; CHECK: call void @f_readonly() [ "foo"(i32* %x) ]
   call void @f_readonly() [ "foo"(i32* %x) ]
@@ -16,7 +16,7 @@ define void @test_0(i32* %x) {
 define void @test_1(i32* %x) {
 ; FunctionAttrs must not infer readonly / readnone for %x
 
-; CHECK-LABEL: define void @test_1(i32* %x) {
+; CHECK-LABEL: define void @test_1(i32* %x) #2 {
  entry:
  ; CHECK: call void @f_readnone() [ "foo"(i32* %x) ]
   call void @f_readnone() [ "foo"(i32* %x) ]
@@ -31,3 +31,6 @@ define void @test_2(i32* %x) {
   call void @f_readonly() [ "deopt"(i32* %x) ]
   ret void
 }
+
+; CHECK: attributes #2 = { nofree }
+

Modified: llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll Mon Jul  8 08:57:56 2019
@@ -21,4 +21,4 @@ entry:
 }
 
 ; CHECK: attributes #0 = { norecurse nounwind readnone ssp uwtable }
-; CHECK: attributes #1 = { norecurse nounwind ssp uwtable }
+; CHECK: attributes #1 = { nofree norecurse nounwind ssp uwtable }

Added: llvm/trunk/test/Transforms/FunctionAttrs/nofree.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nofree.ll?rev=365336&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nofree.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nofree.ll Mon Jul  8 08:57:56 2019
@@ -0,0 +1,113 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: define void @_Z4foo1Pi(i32* nocapture readnone %a) local_unnamed_addr #0 {
+define void @_Z4foo1Pi(i32* nocapture readnone %a) local_unnamed_addr #0 {
+entry:
+  tail call void @_Z3extv()
+  ret void
+}
+
+declare void @_Z3extv() local_unnamed_addr
+
+; CHECK: define void @_Z4foo2Pi(i32* nocapture %a) local_unnamed_addr #1 {
+define void @_Z4foo2Pi(i32* nocapture %a) local_unnamed_addr #1 {
+entry:
+  %0 = bitcast i32* %a to i8*
+  tail call void @free(i8* %0) #2
+  ret void
+}
+
+declare void @free(i8* nocapture) local_unnamed_addr #2
+
+; CHECK: define i32 @_Z4foo3Pi(i32* nocapture readonly %a) local_unnamed_addr #3 {
+define i32 @_Z4foo3Pi(i32* nocapture readonly %a) local_unnamed_addr #3 {
+entry:
+  %0 = load i32, i32* %a, align 4
+  ret i32 %0
+}
+
+; CHECK: define double @_Z4foo4Pd(double* nocapture readonly %a) local_unnamed_addr #1 {
+define double @_Z4foo4Pd(double* nocapture readonly %a) local_unnamed_addr #1 {
+entry:
+  %0 = load double, double* %a, align 8
+  %call = tail call double @cos(double %0) #2
+  ret double %call
+}
+
+declare double @cos(double) local_unnamed_addr #2
+
+; CHECK: define noalias i32* @_Z4foo5Pm(i64* nocapture readonly %a) local_unnamed_addr #1 {
+define noalias i32* @_Z4foo5Pm(i64* nocapture readonly %a) local_unnamed_addr #1 {
+entry:
+  %0 = load i64, i64* %a, align 8
+  %call = tail call noalias i8* @malloc(i64 %0) #2
+  %1 = bitcast i8* %call to i32*
+  ret i32* %1
+}
+
+declare noalias i8* @malloc(i64) local_unnamed_addr #2
+
+; CHECK: define noalias i64* @_Z4foo6Pm(i64* nocapture %a) local_unnamed_addr #1 {
+define noalias i64* @_Z4foo6Pm(i64* nocapture %a) local_unnamed_addr #1 {
+entry:
+  %0 = bitcast i64* %a to i8*
+  %1 = load i64, i64* %a, align 8
+  %call = tail call i8* @realloc(i8* %0, i64 %1) #2
+  %2 = bitcast i8* %call to i64*
+  ret i64* %2
+}
+
+declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #2
+
+; CHECK: define void @_Z4foo7Pi(i32* %a) local_unnamed_addr #1 {
+define void @_Z4foo7Pi(i32* %a) local_unnamed_addr #1 {
+entry:
+  %isnull = icmp eq i32* %a, null
+  br i1 %isnull, label %delete.end, label %delete.notnull
+
+delete.notnull:                                   ; preds = %entry
+  %0 = bitcast i32* %a to i8*
+  tail call void @_ZdlPv(i8* %0) #5
+  br label %delete.end
+
+delete.end:                                       ; preds = %delete.notnull, %entry
+  ret void
+}
+
+declare void @_ZdlPv(i8*) local_unnamed_addr #4
+
+; CHECK: define void @_Z4foo8Pi(i32* %a) local_unnamed_addr #1 {
+define void @_Z4foo8Pi(i32* %a) local_unnamed_addr #1 {
+entry:
+  %isnull = icmp eq i32* %a, null
+  br i1 %isnull, label %delete.end, label %delete.notnull
+
+delete.notnull:                                   ; preds = %entry
+  %0 = bitcast i32* %a to i8*
+  tail call void @_ZdaPv(i8* %0) #5
+  br label %delete.end
+
+delete.end:                                       ; preds = %delete.notnull, %entry
+  ret void
+}
+
+declare void @_ZdaPv(i8*) local_unnamed_addr #4
+
+attributes #0 = { uwtable }
+attributes #1 = { nounwind uwtable }
+attributes #2 = { nounwind }
+attributes #3 = { norecurse nounwind readonly uwtable }
+attributes #4 = { nobuiltin nounwind }
+attributes #5 = { builtin nounwind }
+
+; CHECK: attributes #0 = { uwtable }
+; CHECK: attributes #1 = { nounwind uwtable }
+; CHECK: attributes #2 = { nounwind }
+; CHECK: attributes #3 = { norecurse nounwind readonly uwtable }
+; CHECK: attributes #4 = { nobuiltin nounwind }
+; CHECK: attributes #5 = { builtin nounwind }
+

Modified: llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll Mon Jul  8 08:57:56 2019
@@ -14,4 +14,4 @@ define void @g() {
 }
 
 
-; CHECK: attributes #0 = { nounwind }
+; CHECK: attributes #0 = { nofree nounwind }

Modified: llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Mon Jul  8 08:57:56 2019
@@ -30,7 +30,7 @@
 ;
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
-; CHECK: Function Attrs: nounwind
+; CHECK: Function Attrs: nofree nounwind
 ; CHECK-NEXT: define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* %w0)
 define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
 entry:
@@ -41,7 +41,7 @@ entry:
   ret i32* %call3
 }
 
-; CHECK: Function Attrs: nounwind
+; CHECK: Function Attrs: nofree nounwind
 ; CHECK-NEXT: define internal i32* @internal_ret0_nw(i32* %n0, i32* %w0)
 define internal i32* @internal_ret0_nw(i32* %n0, i32* %w0) {
 entry:
@@ -70,7 +70,7 @@ return:
   ret i32* %retval.0
 }
 
-; CHECK: Function Attrs: nounwind
+; CHECK: Function Attrs: nofree nounwind
 ; CHECK-NEXT: define internal i32* @internal_ret1_rrw(i32* %r0, i32* %r1, i32* %w0)
 define internal i32* @internal_ret1_rrw(i32* %r0, i32* %r1, i32* %w0) {
 entry:
@@ -102,7 +102,7 @@ return:
   ret i32* %retval.0
 }
 
-; CHECK: Function Attrs: norecurse nounwind
+; CHECK: Function Attrs: nofree norecurse nounwind
 ; CHECK-NEXT: define i32* @external_sink_ret2_nrw(i32* readnone %n0, i32* nocapture readonly %r0, i32* returned %w0)
 define i32* @external_sink_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
 entry:
@@ -121,7 +121,7 @@ return:
   ret i32* %w0
 }
 
-; CHECK: Function Attrs: nounwind
+; CHECK: Function Attrs: nofree nounwind
 ; CHECK-NEXT: define internal i32* @internal_ret1_rw(i32* %r0, i32* %w0)
 define internal i32* @internal_ret1_rw(i32* %r0, i32* %w0) {
 entry:
@@ -147,7 +147,7 @@ return:
   ret i32* %retval.0
 }
 
-; CHECK: Function Attrs: nounwind
+; CHECK: Function Attrs: nofree nounwind
 ; CHECK-NEXT: define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* %w0)
 define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
 entry:
@@ -160,6 +160,6 @@ entry:
 ; for a subset relation.
 ;
 ; CHECK-NOT: attributes #
-; CHECK: attributes #{{.*}} = { nounwind }
-; CHECK: attributes #{{.*}} = { norecurse nounwind }
+; CHECK: attributes #{{.*}} = { nofree nounwind }
+; CHECK: attributes #{{.*}} = { nofree norecurse nounwind }
 ; CHECK-NOT: attributes #

Modified: llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll (original)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll Mon Jul  8 08:57:56 2019
@@ -5,14 +5,14 @@
 ; RUN: opt < %s -mtriple=nvptx -inferattrs -S | FileCheck -check-prefix=CHECK-NVPTX %s
 
 ; operator new routines
-declare i8* @_Znwj(i64)
-; CHECK: declare noalias nonnull i8* @_Znwj(i64)
+declare i8* @_Znwj(i64 )
+; CHECK: declare noalias nonnull i8* @_Znwj(i64) [[G0:#[0-9]+]]
 declare i8* @_Znwm(i64)
-; CHECK: declare noalias nonnull i8* @_Znwm(i64)
+; CHECK: declare noalias nonnull i8* @_Znwm(i64) [[G0]]
 
 declare i32 @__nvvm_reflect(i8*)
 ; CHECK-NVPTX: declare i32 @__nvvm_reflect(i8*) [[G0:#[0-9]+]]
-; CHECK-NVPTX: attributes [[G0]] = { nounwind readnone }
+; CHECK-NVPTX: attributes [[G0]] = { nofree nounwind readnone }
 
 
 ; Check all the libc functions (thereby also exercising the prototype check).
@@ -160,244 +160,244 @@ declare double @__sinpi(double)
 ; CHECK: declare float @__sinpif(float)
 declare float @__sinpif(float)
 
-; CHECK: declare i32 @abs(i32)
+; CHECK: declare i32 @abs(i32) [[G0]]
 declare i32 @abs(i32)
 
-; CHECK: declare i32 @access(i8* nocapture readonly, i32) [[G0:#[0-9]+]]
+; CHECK: declare i32 @access(i8* nocapture readonly, i32) [[G1:#[0-9]+]]
 declare i32 @access(i8*, i32)
 
-; CHECK: declare double @acos(double)
+; CHECK: declare double @acos(double) [[G0]]
 declare double @acos(double)
 
-; CHECK: declare float @acosf(float)
+; CHECK: declare float @acosf(float) [[G0]]
 declare float @acosf(float)
 
-; CHECK: declare double @acosh(double)
+; CHECK: declare double @acosh(double) [[G0]]
 declare double @acosh(double)
 
-; CHECK: declare float @acoshf(float)
+; CHECK: declare float @acoshf(float) [[G0]]
 declare float @acoshf(float)
 
-; CHECK: declare x86_fp80 @acoshl(x86_fp80)
+; CHECK: declare x86_fp80 @acoshl(x86_fp80) [[G0]]
 declare x86_fp80 @acoshl(x86_fp80)
 
-; CHECK: declare x86_fp80 @acosl(x86_fp80)
+; CHECK: declare x86_fp80 @acosl(x86_fp80) [[G0]]
 declare x86_fp80 @acosl(x86_fp80)
 
-; CHECK: declare double @asin(double)
+; CHECK: declare double @asin(double) [[G0]]
 declare double @asin(double)
 
-; CHECK: declare float @asinf(float)
+; CHECK: declare float @asinf(float) [[G0]]
 declare float @asinf(float)
 
-; CHECK: declare double @asinh(double)
+; CHECK: declare double @asinh(double) [[G0]]
 declare double @asinh(double)
 
-; CHECK: declare float @asinhf(float)
+; CHECK: declare float @asinhf(float) [[G0]]
 declare float @asinhf(float)
 
-; CHECK: declare x86_fp80 @asinhl(x86_fp80)
+; CHECK: declare x86_fp80 @asinhl(x86_fp80) [[G0]]
 declare x86_fp80 @asinhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @asinl(x86_fp80)
+; CHECK: declare x86_fp80 @asinl(x86_fp80) [[G0]]
 declare x86_fp80 @asinl(x86_fp80)
 
-; CHECK: declare double @atan(double)
+; CHECK: declare double @atan(double) [[G0]]
 declare double @atan(double)
 
-; CHECK: declare double @atan2(double, double)
+; CHECK: declare double @atan2(double, double) [[G0]]
 declare double @atan2(double, double)
 
-; CHECK: declare float @atan2f(float, float)
+; CHECK: declare float @atan2f(float, float) [[G0]]
 declare float @atan2f(float, float)
 
-; CHECK: declare x86_fp80 @atan2l(x86_fp80, x86_fp80)
+; CHECK: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[G0]]
 declare x86_fp80 @atan2l(x86_fp80, x86_fp80)
 
-; CHECK: declare float @atanf(float)
+; CHECK: declare float @atanf(float) [[G0]]
 declare float @atanf(float)
 
-; CHECK: declare double @atanh(double)
+; CHECK: declare double @atanh(double) [[G0]]
 declare double @atanh(double)
 
-; CHECK: declare float @atanhf(float)
+; CHECK: declare float @atanhf(float) [[G0]]
 declare float @atanhf(float)
 
-; CHECK: declare x86_fp80 @atanhl(x86_fp80)
+; CHECK: declare x86_fp80 @atanhl(x86_fp80) [[G0]]
 declare x86_fp80 @atanhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @atanl(x86_fp80)
+; CHECK: declare x86_fp80 @atanl(x86_fp80) [[G0]]
 declare x86_fp80 @atanl(x86_fp80)
 
-; CHECK: declare double @atof(i8* nocapture) [[G1:#[0-9]+]]
+; CHECK: declare double @atof(i8* nocapture) [[G2:#[0-9]+]]
 declare double @atof(i8*)
 
-; CHECK: declare i32 @atoi(i8* nocapture) [[G1]]
+; CHECK: declare i32 @atoi(i8* nocapture) [[G2]]
 declare i32 @atoi(i8*)
 
-; CHECK: declare i64 @atol(i8* nocapture) [[G1]]
+; CHECK: declare i64 @atol(i8* nocapture) [[G2]]
 declare i64 @atol(i8*)
 
-; CHECK: declare i64 @atoll(i8* nocapture) [[G1]]
+; CHECK: declare i64 @atoll(i8* nocapture) [[G2]]
 declare i64 @atoll(i8*)
 
-; CHECK-DARWIN: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
-; CHECK-LINUX: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
-; CHECK-UNKNOWN-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
-; CHECK-NVPTX-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+; CHECK-DARWIN: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G2]]
+; CHECK-LINUX: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G2]]
+; CHECK-UNKNOWN-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G2]]
+; CHECK-NVPTX-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G2]]
 declare i32 @bcmp(i8*, i8*, i64)
 
-; CHECK: declare void @bcopy(i8* nocapture readonly, i8* nocapture, i64) [[G0]]
+; CHECK: declare void @bcopy(i8* nocapture readonly, i8* nocapture, i64) [[G1]]
 declare void @bcopy(i8*, i8*, i64)
 
-; CHECK: declare void @bzero(i8* nocapture, i64) [[G0]]
+; CHECK: declare void @bzero(i8* nocapture, i64) [[G1]]
 declare void @bzero(i8*, i64)
 
-; CHECK: declare noalias i8* @calloc(i64, i64) [[G0]]
+; CHECK: declare noalias i8* @calloc(i64, i64) [[G1]]
 declare i8* @calloc(i64, i64)
 
-; CHECK: declare double @cbrt(double)
+; CHECK: declare double @cbrt(double) [[G0]]
 declare double @cbrt(double)
 
-; CHECK: declare float @cbrtf(float)
+; CHECK: declare float @cbrtf(float) [[G0]]
 declare float @cbrtf(float)
 
-; CHECK: declare x86_fp80 @cbrtl(x86_fp80)
+; CHECK: declare x86_fp80 @cbrtl(x86_fp80) [[G0]]
 declare x86_fp80 @cbrtl(x86_fp80)
 
-; CHECK: declare double @ceil(double)
+; CHECK: declare double @ceil(double) [[G0]]
 declare double @ceil(double)
 
-; CHECK: declare float @ceilf(float)
+; CHECK: declare float @ceilf(float) [[G0]]
 declare float @ceilf(float)
 
-; CHECK: declare x86_fp80 @ceill(x86_fp80)
+; CHECK: declare x86_fp80 @ceill(x86_fp80) [[G0]]
 declare x86_fp80 @ceill(x86_fp80)
 
-; CHECK: declare i32 @chmod(i8* nocapture readonly, i16 zeroext) [[G0]]
+; CHECK: declare i32 @chmod(i8* nocapture readonly, i16 zeroext) [[G1]]
 declare i32 @chmod(i8*, i16 zeroext)
 
-; CHECK: declare i32 @chown(i8* nocapture readonly, i32, i32) [[G0]]
+; CHECK: declare i32 @chown(i8* nocapture readonly, i32, i32) [[G1]]
 declare i32 @chown(i8*, i32, i32)
 
-; CHECK: declare void @clearerr(%opaque* nocapture) [[G0]]
+; CHECK: declare void @clearerr(%opaque* nocapture) [[G1]]
 declare void @clearerr(%opaque*)
 
-; CHECK: declare i32 @closedir(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @closedir(%opaque* nocapture) [[G1]]
 declare i32 @closedir(%opaque*)
 
-; CHECK: declare double @copysign(double, double)
+; CHECK: declare double @copysign(double, double) [[G0]]
 declare double @copysign(double, double)
 
-; CHECK: declare float @copysignf(float, float)
+; CHECK: declare float @copysignf(float, float) [[G0]]
 declare float @copysignf(float, float)
 
-; CHECK: declare x86_fp80 @copysignl(x86_fp80, x86_fp80)
+; CHECK: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[G0]]
 declare x86_fp80 @copysignl(x86_fp80, x86_fp80)
 
-; CHECK: declare double @cos(double)
+; CHECK: declare double @cos(double) [[G0]]
 declare double @cos(double)
 
-; CHECK: declare float @cosf(float)
+; CHECK: declare float @cosf(float) [[G0]]
 declare float @cosf(float)
 
-; CHECK: declare double @cosh(double)
+; CHECK: declare double @cosh(double) [[G0]]
 declare double @cosh(double)
 
-; CHECK: declare float @coshf(float)
+; CHECK: declare float @coshf(float) [[G0]]
 declare float @coshf(float)
 
-; CHECK: declare x86_fp80 @coshl(x86_fp80)
+; CHECK: declare x86_fp80 @coshl(x86_fp80) [[G0]]
 declare x86_fp80 @coshl(x86_fp80)
 
-; CHECK: declare x86_fp80 @cosl(x86_fp80)
+; CHECK: declare x86_fp80 @cosl(x86_fp80) [[G0]]
 declare x86_fp80 @cosl(x86_fp80)
 
-; CHECK: declare i8* @ctermid(i8* nocapture) [[G0]]
+; CHECK: declare i8* @ctermid(i8* nocapture) [[G1]]
 declare i8* @ctermid(i8*)
 
-; CHECK: declare double @exp(double)
+; CHECK: declare double @exp(double) [[G0]]
 declare double @exp(double)
 
-; CHECK: declare double @exp2(double)
+; CHECK: declare double @exp2(double) [[G0]]
 declare double @exp2(double)
 
-; CHECK: declare float @exp2f(float)
+; CHECK: declare float @exp2f(float) [[G0]]
 declare float @exp2f(float)
 
-; CHECK: declare x86_fp80 @exp2l(x86_fp80)
+; CHECK: declare x86_fp80 @exp2l(x86_fp80) [[G0]]
 declare x86_fp80 @exp2l(x86_fp80)
 
-; CHECK: declare float @expf(float)
+; CHECK: declare float @expf(float) [[G0]]
 declare float @expf(float)
 
-; CHECK: declare x86_fp80 @expl(x86_fp80)
+; CHECK: declare x86_fp80 @expl(x86_fp80) [[G0]]
 declare x86_fp80 @expl(x86_fp80)
 
-; CHECK: declare double @expm1(double)
+; CHECK: declare double @expm1(double) [[G0]]
 declare double @expm1(double)
 
-; CHECK: declare float @expm1f(float)
+; CHECK: declare float @expm1f(float) [[G0]]
 declare float @expm1f(float)
 
-; CHECK: declare x86_fp80 @expm1l(x86_fp80)
+; CHECK: declare x86_fp80 @expm1l(x86_fp80) [[G0]]
 declare x86_fp80 @expm1l(x86_fp80)
 
-; CHECK: declare double @fabs(double)
+; CHECK: declare double @fabs(double) [[G0]]
 declare double @fabs(double)
 
-; CHECK: declare float @fabsf(float)
+; CHECK: declare float @fabsf(float) [[G0]]
 declare float @fabsf(float)
 
-; CHECK: declare x86_fp80 @fabsl(x86_fp80)
+; CHECK: declare x86_fp80 @fabsl(x86_fp80) [[G0]]
 declare x86_fp80 @fabsl(x86_fp80)
 
-; CHECK: declare i32 @fclose(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fclose(%opaque* nocapture) [[G1]]
 declare i32 @fclose(%opaque*)
 
-; CHECK: declare noalias %opaque* @fdopen(i32, i8* nocapture readonly) [[G0]]
+; CHECK: declare noalias %opaque* @fdopen(i32, i8* nocapture readonly) [[G1]]
 declare %opaque* @fdopen(i32, i8*)
 
-; CHECK: declare i32 @feof(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @feof(%opaque* nocapture) [[G1]]
 declare i32 @feof(%opaque*)
 
-; CHECK: declare i32 @ferror(%opaque* nocapture) [[G1]]
+; CHECK: declare i32 @ferror(%opaque* nocapture) [[G2]]
 declare i32 @ferror(%opaque*)
 
-; CHECK: declare i32 @fflush(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fflush(%opaque* nocapture) [[G1]]
 declare i32 @fflush(%opaque*)
 
-; CHECK: declare i32 @ffs(i32)
+; CHECK: declare i32 @ffs(i32) [[G0]]
 declare i32 @ffs(i32)
 
-; CHECK: declare i32 @ffsl(i64)
+; CHECK: declare i32 @ffsl(i64) [[G0]]
 declare i32 @ffsl(i64)
 
-; CHECK: declare i32 @ffsll(i64)
+; CHECK: declare i32 @ffsll(i64) [[G0]]
 declare i32 @ffsll(i64)
 
-; CHECK: declare i32 @fgetc(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fgetc(%opaque* nocapture) [[G1]]
 declare i32 @fgetc(%opaque*)
 
-; CHECK: declare i32 @fgetpos(%opaque* nocapture, i64* nocapture) [[G0]]
+; CHECK: declare i32 @fgetpos(%opaque* nocapture, i64* nocapture) [[G1]]
 declare i32 @fgetpos(%opaque*, i64*)
 
-; CHECK: declare i8* @fgets(i8*, i32, %opaque* nocapture) [[G0]]
+; CHECK: declare i8* @fgets(i8*, i32, %opaque* nocapture) [[G1]]
 declare i8* @fgets(i8*, i32, %opaque*)
 
-; CHECK: declare i32 @fileno(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fileno(%opaque* nocapture) [[G1]]
 declare i32 @fileno(%opaque*)
 
-; CHECK: declare void @flockfile(%opaque* nocapture) [[G0]]
+; CHECK: declare void @flockfile(%opaque* nocapture) [[G1]]
 declare void @flockfile(%opaque*)
 
-; CHECK: declare double @floor(double)
+; CHECK: declare double @floor(double) [[G0]]
 declare double @floor(double)
 
-; CHECK: declare float @floorf(float)
+; CHECK: declare float @floorf(float) [[G0]]
 declare float @floorf(float)
 
-; CHECK: declare x86_fp80 @floorl(x86_fp80)
+; CHECK: declare x86_fp80 @floorl(x86_fp80) [[G0]]
 declare x86_fp80 @floorl(x86_fp80)
 
 ; CHECK: declare i32 @fls(i32)
@@ -409,607 +409,608 @@ declare i32 @flsl(i64)
 ; CHECK: declare i32 @flsll(i64)
 declare i32 @flsll(i64)
 
-; CHECK: declare double @fmax(double, double)
+; CHECK: declare double @fmax(double, double) [[G0]]
 declare double @fmax(double, double)
 
-; CHECK: declare float @fmaxf(float, float)
+; CHECK: declare float @fmaxf(float, float) [[G0]]
 declare float @fmaxf(float, float)
 
-; CHECK: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80)
+; CHECK: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[G0]]
 declare x86_fp80 @fmaxl(x86_fp80, x86_fp80)
 
-; CHECK: declare double @fmin(double, double)
+; CHECK: declare double @fmin(double, double) [[G0]]
 declare double @fmin(double, double)
 
-; CHECK: declare float @fminf(float, float)
+; CHECK: declare float @fminf(float, float) [[G0]]
 declare float @fminf(float, float)
 
-; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80)
+; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[G0]]
 declare x86_fp80 @fminl(x86_fp80, x86_fp80)
 
-; CHECK: declare double @fmod(double, double)
+; CHECK: declare double @fmod(double, double) [[G0]]
 declare double @fmod(double, double)
 
-; CHECK: declare float @fmodf(float, float)
+; CHECK: declare float @fmodf(float, float) [[G0]]
 declare float @fmodf(float, float)
 
-; CHECK: declare x86_fp80 @fmodl(x86_fp80, x86_fp80)
+; CHECK: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[G0]]
 declare x86_fp80 @fmodl(x86_fp80, x86_fp80)
 
-; CHECK: declare noalias %opaque* @fopen(i8* nocapture readonly, i8* nocapture readonly) [[G0]]
+; CHECK: declare noalias %opaque* @fopen(i8* nocapture readonly, i8* nocapture readonly) [[G1]]
 declare %opaque* @fopen(i8*, i8*)
 
-; CHECK: declare i32 @fprintf(%opaque* nocapture, i8* nocapture readonly, ...) [[G0]]
+; CHECK: declare i32 @fprintf(%opaque* nocapture, i8* nocapture readonly, ...) [[G1]]
 declare i32 @fprintf(%opaque*, i8*, ...)
 
-; CHECK: declare i32 @fputc(i32, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fputc(i32, %opaque* nocapture) [[G1]]
 declare i32 @fputc(i32, %opaque*)
 
-; CHECK: declare i32 @fputs(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fputs(i8* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @fputs(i8*, %opaque*)
 
-; CHECK: declare i64 @fread(i8* nocapture, i64, i64, %opaque* nocapture) [[G0]]
+; CHECK: declare i64 @fread(i8* nocapture, i64, i64, %opaque* nocapture) [[G1]]
 declare i64 @fread(i8*, i64, i64, %opaque*)
 
-; CHECK: declare void @free(i8* nocapture) [[G0]]
+; CHECK: declare void @free(i8* nocapture) [[G3:#[0-9]+]]
 declare void @free(i8*)
 
-; CHECK: declare double @frexp(double, i32* nocapture) [[G0]]
+; CHECK: declare double @frexp(double, i32* nocapture) [[G1]]
 declare double @frexp(double, i32*)
 
-; CHECK: declare float @frexpf(float, i32* nocapture) [[G0]]
+; CHECK: declare float @frexpf(float, i32* nocapture) [[G1]]
 declare float @frexpf(float, i32*)
 
-; CHECK: declare x86_fp80 @frexpl(x86_fp80, i32* nocapture) [[G0]]
+; CHECK: declare x86_fp80 @frexpl(x86_fp80, i32* nocapture) [[G1]]
 declare x86_fp80 @frexpl(x86_fp80, i32*)
 
-; CHECK: declare i32 @fscanf(%opaque* nocapture, i8* nocapture readonly, ...) [[G0]]
+; CHECK: declare i32 @fscanf(%opaque* nocapture, i8* nocapture readonly, ...) [[G1]]
 declare i32 @fscanf(%opaque*, i8*, ...)
 
-; CHECK: declare i32 @fseek(%opaque* nocapture, i64, i32) [[G0]]
+; CHECK: declare i32 @fseek(%opaque* nocapture, i64, i32) [[G1]]
 declare i32 @fseek(%opaque*, i64, i32)
 
-; CHECK: declare i32 @fseeko(%opaque* nocapture, i64, i32) [[G0]]
+; CHECK: declare i32 @fseeko(%opaque* nocapture, i64, i32) [[G1]]
 declare i32 @fseeko(%opaque*, i64, i32)
 
-; CHECK-LINUX: declare i32 @fseeko64(%opaque* nocapture, i64, i32) [[G0]]
+; CHECK-LINUX: declare i32 @fseeko64(%opaque* nocapture, i64, i32) [[G1]]
 declare i32 @fseeko64(%opaque*, i64, i32)
 
-; CHECK: declare i32 @fsetpos(%opaque* nocapture, i64*) [[G0]]
+; CHECK: declare i32 @fsetpos(%opaque* nocapture, i64*) [[G1]]
 declare i32 @fsetpos(%opaque*, i64*)
 
-; CHECK: declare i32 @fstat(i32, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fstat(i32, %opaque* nocapture) [[G1]]
 declare i32 @fstat(i32, %opaque*)
 
-; CHECK-LINUX: declare i32 @fstat64(i32, %opaque* nocapture) [[G0]]
+; CHECK-LINUX: declare i32 @fstat64(i32, %opaque* nocapture) [[G1]]
 declare i32 @fstat64(i32, %opaque*)
 
-; CHECK: declare i32 @fstatvfs(i32, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @fstatvfs(i32, %opaque* nocapture) [[G1]]
 declare i32 @fstatvfs(i32, %opaque*)
 
-; CHECK-LINUX: declare i32 @fstatvfs64(i32, %opaque* nocapture) [[G0]]
+; CHECK-LINUX: declare i32 @fstatvfs64(i32, %opaque* nocapture) [[G1]]
 declare i32 @fstatvfs64(i32, %opaque*)
 
-; CHECK: declare i64 @ftell(%opaque* nocapture) [[G0]]
+; CHECK: declare i64 @ftell(%opaque* nocapture) [[G1]]
 declare i64 @ftell(%opaque*)
 
-; CHECK: declare i64 @ftello(%opaque* nocapture) [[G0]]
+; CHECK: declare i64 @ftello(%opaque* nocapture) [[G1]]
 declare i64 @ftello(%opaque*)
 
-; CHECK-LINUX: declare i64 @ftello64(%opaque* nocapture) [[G0]]
+; CHECK-LINUX: declare i64 @ftello64(%opaque* nocapture) [[G1]]
 declare i64 @ftello64(%opaque*)
 
-; CHECK: declare i32 @ftrylockfile(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @ftrylockfile(%opaque* nocapture) [[G1]]
 declare i32 @ftrylockfile(%opaque*)
 
-; CHECK: declare void @funlockfile(%opaque* nocapture) [[G0]]
+; CHECK: declare void @funlockfile(%opaque* nocapture) [[G1]]
 declare void @funlockfile(%opaque*)
 
-; CHECK: declare i64 @fwrite(i8* nocapture, i64, i64, %opaque* nocapture) [[G0]]
+; CHECK: declare i64 @fwrite(i8* nocapture, i64, i64, %opaque* nocapture) [[G1]]
 declare i64 @fwrite(i8*, i64, i64, %opaque*)
 
-; CHECK: declare i32 @getc(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @getc(%opaque* nocapture) [[G1]]
 declare i32 @getc(%opaque*)
 
-; CHECK: declare i32 @getc_unlocked(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @getc_unlocked(%opaque* nocapture) [[G1]]
 declare i32 @getc_unlocked(%opaque*)
 
-; CHECK: declare i32 @getchar()
+; CHECK: declare i32 @getchar() [[G1]]
 declare i32 @getchar()
 
-; CHECK: declare i32 @getchar_unlocked()
+; CHECK: declare i32 @getchar_unlocked() [[G1]]
 declare i32 @getchar_unlocked()
 
-; CHECK: declare i8* @getenv(i8* nocapture) [[G1]]
+; CHECK: declare i8* @getenv(i8* nocapture) [[G2]]
 declare i8* @getenv(i8*)
 
-; CHECK: declare i32 @getitimer(i32, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @getitimer(i32, %opaque* nocapture) [[G1]]
 declare i32 @getitimer(i32, %opaque*)
 
-; CHECK: declare i32 @getlogin_r(i8* nocapture, i64) [[G0]]
+; CHECK: declare i32 @getlogin_r(i8* nocapture, i64) [[G1]]
 declare i32 @getlogin_r(i8*, i64)
 
-; CHECK: declare %opaque* @getpwnam(i8* nocapture readonly) [[G0]]
+; CHECK: declare %opaque* @getpwnam(i8* nocapture readonly) [[G1]]
 declare %opaque* @getpwnam(i8*)
 
-; CHECK: declare i8* @gets(i8*)
+; CHECK: declare i8* @gets(i8*) [[G1]]
 declare i8* @gets(i8*)
 
-; CHECK: declare i32 @gettimeofday(%opaque* nocapture, i8* nocapture) [[G0]]
+; CHECK: declare i32 @gettimeofday(%opaque* nocapture, i8* nocapture) [[G1]]
 declare i32 @gettimeofday(%opaque*, i8*)
 
-; CHECK: declare i32 @isascii(i32)
+; CHECK: declare i32 @isascii(i32) [[G0]]
 declare i32 @isascii(i32)
 
-; CHECK: declare i32 @isdigit(i32)
+; CHECK: declare i32 @isdigit(i32) [[G0]]
 declare i32 @isdigit(i32)
 
-; CHECK: declare i64 @labs(i64)
+; CHECK: declare i64 @labs(i64) [[G0]]
 declare i64 @labs(i64)
 
-; CHECK: declare i32 @lchown(i8* nocapture readonly, i32, i32) [[G0]]
+; CHECK: declare i32 @lchown(i8* nocapture readonly, i32, i32) [[G1]]
 declare i32 @lchown(i8*, i32, i32)
 
-; CHECK: declare double @ldexp(double, i32)
+; CHECK: declare double @ldexp(double, i32) [[G0]]
 declare double @ldexp(double, i32)
 
-; CHECK: declare float @ldexpf(float, i32)
+; CHECK: declare float @ldexpf(float, i32) [[G0]]
 declare float @ldexpf(float, i32)
 
-; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32)
+; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32) [[G0]]
 declare x86_fp80 @ldexpl(x86_fp80, i32)
 
-; CHECK: declare i64 @llabs(i64)
+; CHECK: declare i64 @llabs(i64) [[G0]]
 declare i64 @llabs(i64)
 
-; CHECK: declare double @log(double)
+; CHECK: declare double @log(double) [[G0]]
 declare double @log(double)
 
-; CHECK: declare double @log10(double)
+; CHECK: declare double @log10(double) [[G0]]
 declare double @log10(double)
 
-; CHECK: declare float @log10f(float)
+; CHECK: declare float @log10f(float) [[G0]]
 declare float @log10f(float)
 
-; CHECK: declare x86_fp80 @log10l(x86_fp80)
+; CHECK: declare x86_fp80 @log10l(x86_fp80) [[G0]]
 declare x86_fp80 @log10l(x86_fp80)
 
-; CHECK: declare double @log1p(double)
+; CHECK: declare double @log1p(double) [[G0]]
 declare double @log1p(double)
 
-; CHECK: declare float @log1pf(float)
+; CHECK: declare float @log1pf(float) [[G0]]
 declare float @log1pf(float)
 
-; CHECK: declare x86_fp80 @log1pl(x86_fp80)
+; CHECK: declare x86_fp80 @log1pl(x86_fp80) [[G0]]
 declare x86_fp80 @log1pl(x86_fp80)
 
-; CHECK: declare double @log2(double)
+; CHECK: declare double @log2(double) [[G0]]
 declare double @log2(double)
 
-; CHECK: declare float @log2f(float)
+; CHECK: declare float @log2f(float) [[G0]]
 declare float @log2f(float)
 
-; CHECK: declare x86_fp80 @log2l(x86_fp80)
+; CHECK: declare x86_fp80 @log2l(x86_fp80) [[G0]]
 declare x86_fp80 @log2l(x86_fp80)
 
-; CHECK: declare double @logb(double)
+; CHECK: declare double @logb(double) [[G0]]
 declare double @logb(double)
 
-; CHECK: declare float @logbf(float)
+; CHECK: declare float @logbf(float) [[G0]]
 declare float @logbf(float)
 
-; CHECK: declare x86_fp80 @logbl(x86_fp80)
+; CHECK: declare x86_fp80 @logbl(x86_fp80) [[G0]]
 declare x86_fp80 @logbl(x86_fp80)
 
-; CHECK: declare float @logf(float)
+; CHECK: declare float @logf(float) [[G0]]
 declare float @logf(float)
 
-; CHECK: declare x86_fp80 @logl(x86_fp80)
+; CHECK: declare x86_fp80 @logl(x86_fp80) [[G0]]
 declare x86_fp80 @logl(x86_fp80)
 
-; CHECK: declare i32 @lstat(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @lstat(i8* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @lstat(i8*, %opaque*)
 
-; CHECK-LINUX: declare i32 @lstat64(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK-LINUX: declare i32 @lstat64(i8* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @lstat64(i8*, %opaque*)
 
-; CHECK: declare noalias i8* @malloc(i64) [[G0]]
+; CHECK: declare noalias i8* @malloc(i64) [[G1]]
 declare i8* @malloc(i64)
 
-; CHECK-LINUX: declare noalias i8* @memalign(i64, i64)
+; CHECK-LINUX: declare noalias i8* @memalign(i64, i64) [[G0]]
 declare i8* @memalign(i64, i64)
 
-; CHECK: declare i8* @memccpy(i8*, i8* nocapture readonly, i32, i64) [[G0]]
+; CHECK: declare i8* @memccpy(i8*, i8* nocapture readonly, i32, i64) [[G1]]
 declare i8* @memccpy(i8*, i8*, i32, i64)
 
-; CHECK: declare i8* @memchr(i8*, i32, i64) [[G1]]
+; CHECK: declare i8* @memchr(i8*, i32, i64) [[G2]]
 declare i8* @memchr(i8*, i32, i64)
 
-; CHECK: declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+; CHECK: declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) [[G2]]
 declare i32 @memcmp(i8*, i8*, i64)
 
-; CHECK: declare i8* @memcpy(i8* returned, i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare i8* @memcpy(i8* returned, i8* nocapture readonly, i64) [[G1]]
 declare i8* @memcpy(i8*, i8*, i64)
 
-; CHECK: declare i8* @mempcpy(i8*, i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare i8* @mempcpy(i8*, i8* nocapture readonly, i64) [[G1]]
 declare i8* @mempcpy(i8*, i8*, i64)
 
-; CHECK: declare i8* @memmove(i8* returned, i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare i8* @memmove(i8* returned, i8* nocapture readonly, i64) [[G1]]
 declare i8* @memmove(i8*, i8*, i64)
 
-; CHECK: declare i8* @memset(i8*, i32, i64)
+; CHECK: declare i8* @memset(i8*, i32, i64) [[G0]]
 declare i8* @memset(i8*, i32, i64)
 
-; CHECK: declare i32 @mkdir(i8* nocapture readonly, i16 zeroext) [[G0]]
+; CHECK: declare i32 @mkdir(i8* nocapture readonly, i16 zeroext) [[G1]]
 declare i32 @mkdir(i8*, i16 zeroext)
 
-; CHECK: declare i64 @mktime(%opaque* nocapture) [[G0]]
+; CHECK: declare i64 @mktime(%opaque* nocapture) [[G1]]
 declare i64 @mktime(%opaque*)
 
-; CHECK: declare double @modf(double, double* nocapture) [[G0]]
+; CHECK: declare double @modf(double, double* nocapture) [[G1]]
 declare double @modf(double, double*)
 
-; CHECK: declare float @modff(float, float* nocapture) [[G0]]
+; CHECK: declare float @modff(float, float* nocapture) [[G1]]
 declare float @modff(float, float*)
 
-; CHECK: declare x86_fp80 @modfl(x86_fp80, x86_fp80* nocapture) [[G0]]
+; CHECK: declare x86_fp80 @modfl(x86_fp80, x86_fp80* nocapture) [[G1]]
 declare x86_fp80 @modfl(x86_fp80, x86_fp80*)
 
-; CHECK: declare double @nearbyint(double)
+; CHECK: declare double @nearbyint(double) [[G0]]
 declare double @nearbyint(double)
 
-; CHECK: declare float @nearbyintf(float)
+; CHECK: declare float @nearbyintf(float) [[G0]]
 declare float @nearbyintf(float)
 
-; CHECK: declare x86_fp80 @nearbyintl(x86_fp80)
+; CHECK: declare x86_fp80 @nearbyintl(x86_fp80) [[G0]]
 declare x86_fp80 @nearbyintl(x86_fp80)
 
-; CHECK: declare i32 @open(i8* nocapture readonly, i32, ...)
+; CHECK: declare i32 @open(i8* nocapture readonly, i32, ...) [[G0]]
 declare i32 @open(i8*, i32, ...)
 
-; CHECK-LINUX: declare i32 @open64(i8* nocapture readonly, i32, ...)
+; CHECK-LINUX: declare i32 @open64(i8* nocapture readonly, i32, ...) [[G0]]
 declare i32 @open64(i8*, i32, ...)
 
-; CHECK: declare noalias %opaque* @opendir(i8* nocapture readonly) [[G0]]
+; CHECK: declare noalias %opaque* @opendir(i8* nocapture readonly) [[G1]]
 declare %opaque* @opendir(i8*)
 
-; CHECK: declare i32 @pclose(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @pclose(%opaque* nocapture) [[G1]]
 declare i32 @pclose(%opaque*)
 
-; CHECK: declare void @perror(i8* nocapture readonly) [[G0]]
+; CHECK: declare void @perror(i8* nocapture readonly) [[G1]]
 declare void @perror(i8*)
 
-; CHECK: declare noalias %opaque* @popen(i8* nocapture readonly, i8* nocapture readonly) [[G0]]
+; CHECK: declare noalias %opaque* @popen(i8* nocapture readonly, i8* nocapture readonly) [[G1]]
 declare %opaque* @popen(i8*, i8*)
 
-; CHECK: declare i32 @posix_memalign(i8**, i64, i64)
+; CHECK: declare i32 @posix_memalign(i8**, i64, i64) [[G0]]
 declare i32 @posix_memalign(i8**, i64, i64)
 
-; CHECK: declare double @pow(double, double)
+; CHECK: declare double @pow(double, double) [[G0]]
 declare double @pow(double, double)
 
-; CHECK: declare float @powf(float, float)
+; CHECK: declare float @powf(float, float) [[G0]]
 declare float @powf(float, float)
 
-; CHECK: declare x86_fp80 @powl(x86_fp80, x86_fp80)
+; CHECK: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[G0]]
 declare x86_fp80 @powl(x86_fp80, x86_fp80)
 
-; CHECK: declare i64 @pread(i32, i8* nocapture, i64, i64)
+; CHECK: declare i64 @pread(i32, i8* nocapture, i64, i64) [[G0]]
 declare i64 @pread(i32, i8*, i64, i64)
 
-; CHECK: declare i32 @printf(i8* nocapture readonly, ...) [[G0]]
+; CHECK: declare i32 @printf(i8* nocapture readonly, ...) [[G1]]
 declare i32 @printf(i8*, ...)
 
-; CHECK: declare i32 @putc(i32, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @putc(i32, %opaque* nocapture) [[G1]]
 declare i32 @putc(i32, %opaque*)
 
-; CHECK: declare i32 @putchar(i32)
+; CHECK: declare i32 @putchar(i32) [[G1]]
 declare i32 @putchar(i32)
 
-; CHECK: declare i32 @putchar_unlocked(i32)
+; CHECK: declare i32 @putchar_unlocked(i32) [[G1]]
 declare i32 @putchar_unlocked(i32)
 
-; CHECK: declare i32 @puts(i8* nocapture readonly) [[G0]]
+; CHECK: declare i32 @puts(i8* nocapture readonly) [[G1]]
 declare i32 @puts(i8*)
 
-; CHECK: declare i64 @pwrite(i32, i8* nocapture readonly, i64, i64)
+; CHECK: declare i64 @pwrite(i32, i8* nocapture readonly, i64, i64) [[G0]]
 declare i64 @pwrite(i32, i8*, i64, i64)
 
-; CHECK: declare void @qsort(i8*, i64, i64, i32 (i8*, i8*)* nocapture)
+; CHECK: declare void @qsort(i8*, i64, i64, i32 (i8*, i8*)* nocapture) [[G0]]
 declare void @qsort(i8*, i64, i64, i32 (i8*, i8*)*)
 
-; CHECK: declare i64 @read(i32, i8* nocapture, i64)
+; CHECK: declare i64 @read(i32, i8* nocapture, i64) [[G0]]
 declare i64 @read(i32, i8*, i64)
 
-; CHECK: declare i64 @readlink(i8* nocapture readonly, i8* nocapture, i64) [[G0]]
+; CHECK: declare i64 @readlink(i8* nocapture readonly, i8* nocapture, i64) [[G1]]
 declare i64 @readlink(i8*, i8*, i64)
 
-; CHECK: declare noalias i8* @realloc(i8* nocapture, i64) [[G0]]
+; CHECK: declare noalias i8* @realloc(i8* nocapture, i64) [[G3]]
 declare i8* @realloc(i8*, i64)
 
 ; CHECK: declare i8* @reallocf(i8*, i64)
 declare i8* @reallocf(i8*, i64)
 
-; CHECK: declare i8* @realpath(i8* nocapture readonly, i8*)
+; CHECK: declare i8* @realpath(i8* nocapture readonly, i8*) [[G1]]
 declare i8* @realpath(i8*, i8*)
 
-; CHECK: declare i32 @remove(i8* nocapture readonly) [[G0]]
+; CHECK: declare i32 @remove(i8* nocapture readonly) [[G1]]
 declare i32 @remove(i8*)
 
-; CHECK: declare i32 @rename(i8* nocapture readonly, i8* nocapture readonly) [[G0]]
+; CHECK: declare i32 @rename(i8* nocapture readonly, i8* nocapture readonly) [[G1]]
 declare i32 @rename(i8*, i8*)
 
-; CHECK: declare void @rewind(%opaque* nocapture) [[G0]]
+; CHECK: declare void @rewind(%opaque* nocapture) [[G1]]
 declare void @rewind(%opaque*)
 
-; CHECK: declare double @rint(double)
+; CHECK: declare double @rint(double) [[G0]]
 declare double @rint(double)
 
-; CHECK: declare float @rintf(float)
+; CHECK: declare float @rintf(float) [[G0]]
 declare float @rintf(float)
 
-; CHECK: declare x86_fp80 @rintl(x86_fp80)
+; CHECK: declare x86_fp80 @rintl(x86_fp80) [[G0]]
 declare x86_fp80 @rintl(x86_fp80)
 
-; CHECK: declare i32 @rmdir(i8* nocapture readonly) [[G0]]
+; CHECK: declare i32 @rmdir(i8* nocapture readonly) [[G1]]
 declare i32 @rmdir(i8*)
 
-; CHECK: declare double @round(double)
+; CHECK: declare double @round(double) [[G0]]
 declare double @round(double)
 
-; CHECK: declare float @roundf(float)
+; CHECK: declare float @roundf(float) [[G0]]
 declare float @roundf(float)
 
-; CHECK: declare x86_fp80 @roundl(x86_fp80)
+; CHECK: declare x86_fp80 @roundl(x86_fp80) [[G0]]
 declare x86_fp80 @roundl(x86_fp80)
 
-; CHECK: declare i32 @scanf(i8* nocapture readonly, ...) [[G0]]
+; CHECK: declare i32 @scanf(i8* nocapture readonly, ...) [[G1]]
 declare i32 @scanf(i8*, ...)
 
-; CHECK: declare void @setbuf(%opaque* nocapture, i8*) [[G0]]
+; CHECK: declare void @setbuf(%opaque* nocapture, i8*) [[G1]]
 declare void @setbuf(%opaque*, i8*)
 
-; CHECK: declare i32 @setitimer(i32, %opaque* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @setitimer(i32, %opaque* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @setitimer(i32, %opaque*, %opaque*)
 
-; CHECK: declare i32 @setvbuf(%opaque* nocapture, i8*, i32, i64) [[G0]]
+; CHECK: declare i32 @setvbuf(%opaque* nocapture, i8*, i32, i64) [[G1]]
 declare i32 @setvbuf(%opaque*, i8*, i32, i64)
 
-; CHECK: declare double @sin(double)
+; CHECK: declare double @sin(double) [[G0]]
 declare double @sin(double)
 
-; CHECK: declare float @sinf(float)
+; CHECK: declare float @sinf(float) [[G0]]
 declare float @sinf(float)
 
-; CHECK: declare double @sinh(double)
+; CHECK: declare double @sinh(double) [[G0]]
 declare double @sinh(double)
 
-; CHECK: declare float @sinhf(float)
+; CHECK: declare float @sinhf(float) [[G0]]
 declare float @sinhf(float)
 
-; CHECK: declare x86_fp80 @sinhl(x86_fp80)
+; CHECK: declare x86_fp80 @sinhl(x86_fp80) [[G0]]
 declare x86_fp80 @sinhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @sinl(x86_fp80)
+; CHECK: declare x86_fp80 @sinl(x86_fp80) [[G0]]
 declare x86_fp80 @sinl(x86_fp80)
 
-; CHECK: declare i32 @snprintf(i8* nocapture, i64, i8* nocapture readonly, ...) [[G0]]
+; CHECK: declare i32 @snprintf(i8* nocapture, i64, i8* nocapture readonly, ...) [[G1]]
 declare i32 @snprintf(i8*, i64, i8*, ...)
 
-; CHECK: declare i32 @sprintf(i8* nocapture, i8* nocapture readonly, ...) [[G0]]
+; CHECK: declare i32 @sprintf(i8* nocapture, i8* nocapture readonly, ...) [[G1]]
 declare i32 @sprintf(i8*, i8*, ...)
 
-; CHECK: declare double @sqrt(double)
+; CHECK: declare double @sqrt(double) [[G0]]
 declare double @sqrt(double)
 
-; CHECK: declare float @sqrtf(float)
+; CHECK: declare float @sqrtf(float) [[G0]]
 declare float @sqrtf(float)
 
-; CHECK: declare x86_fp80 @sqrtl(x86_fp80)
+; CHECK: declare x86_fp80 @sqrtl(x86_fp80) [[G0]]
 declare x86_fp80 @sqrtl(x86_fp80)
 
-; CHECK: declare i32 @sscanf(i8* nocapture readonly, i8* nocapture readonly, ...) [[G0]]
+; CHECK: declare i32 @sscanf(i8* nocapture readonly, i8* nocapture readonly, ...) [[G1]]
 declare i32 @sscanf(i8*, i8*, ...)
 
-; CHECK: declare i32 @stat(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @stat(i8* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @stat(i8*, %opaque*)
 
-; CHECK-LINUX: declare i32 @stat64(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK-LINUX: declare i32 @stat64(i8* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @stat64(i8*, %opaque*)
 
-; CHECK: declare i32 @statvfs(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @statvfs(i8* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @statvfs(i8*, %opaque*)
 
-; CHECK-LINUX: declare i32 @statvfs64(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+; CHECK-LINUX: declare i32 @statvfs64(i8* nocapture readonly, %opaque* nocapture) [[G1]]
 declare i32 @statvfs64(i8*, %opaque*)
 
-; CHECK: declare i8* @stpcpy(i8*, i8* nocapture readonly) [[G0]]
+; CHECK: declare i8* @stpcpy(i8*, i8* nocapture readonly) [[G1]]
 declare i8* @stpcpy(i8*, i8*)
 
-; CHECK: declare i8* @stpncpy(i8*, i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare i8* @stpncpy(i8*, i8* nocapture readonly, i64) [[G1]]
 declare i8* @stpncpy(i8*, i8*, i64)
 
-; CHECK: declare i32 @strcasecmp(i8* nocapture, i8* nocapture) [[G1]]
+; CHECK: declare i32 @strcasecmp(i8* nocapture, i8* nocapture) [[G2]]
 declare i32 @strcasecmp(i8*, i8*)
 
-; CHECK: declare i8* @strcat(i8* returned, i8* nocapture readonly) [[G0]]
+; CHECK: declare i8* @strcat(i8* returned, i8* nocapture readonly) [[G1]]
 declare i8* @strcat(i8*, i8*)
 
-; CHECK: declare i8* @strchr(i8*, i32) [[G1]]
+; CHECK: declare i8* @strchr(i8*, i32) [[G2]]
 declare i8* @strchr(i8*, i32)
 
-; CHECK: declare i32 @strcmp(i8* nocapture, i8* nocapture) [[G1]]
+; CHECK: declare i32 @strcmp(i8* nocapture, i8* nocapture) [[G2]]
 declare i32 @strcmp(i8*, i8*)
 
-; CHECK: declare i32 @strcoll(i8* nocapture, i8* nocapture) [[G1]]
+; CHECK: declare i32 @strcoll(i8* nocapture, i8* nocapture) [[G2]]
 declare i32 @strcoll(i8*, i8*)
 
-; CHECK: declare i8* @strcpy(i8* returned, i8* nocapture readonly) [[G0]]
+; CHECK: declare i8* @strcpy(i8* returned, i8* nocapture readonly) [[G1]]
 declare i8* @strcpy(i8*, i8*)
 
-; CHECK: declare i64 @strcspn(i8* nocapture, i8* nocapture) [[G1]]
+; CHECK: declare i64 @strcspn(i8* nocapture, i8* nocapture) [[G2]]
 declare i64 @strcspn(i8*, i8*)
 
-; CHECK: declare noalias i8* @strdup(i8* nocapture readonly) [[G0]]
+; CHECK: declare noalias i8* @strdup(i8* nocapture readonly) [[G1]]
 declare i8* @strdup(i8*)
 
-; CHECK: declare i64 @strlen(i8* nocapture) [[G2:#[0-9]+]]
+; CHECK: declare i64 @strlen(i8* nocapture) [[G4:#[0-9]+]]
 declare i64 @strlen(i8*)
 
-; CHECK: declare i32 @strncasecmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+; CHECK: declare i32 @strncasecmp(i8* nocapture, i8* nocapture, i64) [[G2]]
 declare i32 @strncasecmp(i8*, i8*, i64)
 
-; CHECK: declare i8* @strncat(i8* returned, i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare i8* @strncat(i8* returned, i8* nocapture readonly, i64) [[G1]]
 declare i8* @strncat(i8*, i8*, i64)
 
-; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[G2]]
 declare i32 @strncmp(i8*, i8*, i64)
 
-; CHECK: declare i8* @strncpy(i8* returned, i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare i8* @strncpy(i8* returned, i8* nocapture readonly, i64) [[G1]]
 declare i8* @strncpy(i8*, i8*, i64)
 
-; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[G1]]
 declare i8* @strndup(i8*, i64)
 
-; CHECK: declare i64 @strnlen(i8*, i64)
+; CHECK: declare i64 @strnlen(i8*, i64) [[G0]]
 declare i64 @strnlen(i8*, i64)
 
-; CHECK: declare i8* @strpbrk(i8*, i8* nocapture) [[G1]]
+; CHECK: declare i8* @strpbrk(i8*, i8* nocapture) [[G2]]
 declare i8* @strpbrk(i8*, i8*)
 
-; CHECK: declare i8* @strrchr(i8*, i32) [[G1]]
+; CHECK: declare i8* @strrchr(i8*, i32) [[G2]]
 declare i8* @strrchr(i8*, i32)
 
-; CHECK: declare i64 @strspn(i8* nocapture, i8* nocapture) [[G1]]
+; CHECK: declare i64 @strspn(i8* nocapture, i8* nocapture) [[G2]]
 declare i64 @strspn(i8*, i8*)
 
-; CHECK: declare i8* @strstr(i8*, i8* nocapture) [[G1]]
+; CHECK: declare i8* @strstr(i8*, i8* nocapture) [[G2]]
 declare i8* @strstr(i8*, i8*)
 
-; CHECK: declare double @strtod(i8* readonly, i8** nocapture) [[G0]]
+; CHECK: declare double @strtod(i8* readonly, i8** nocapture) [[G1]]
 declare double @strtod(i8*, i8**)
 
-; CHECK: declare float @strtof(i8* readonly, i8** nocapture) [[G0]]
+; CHECK: declare float @strtof(i8* readonly, i8** nocapture) [[G1]]
 declare float @strtof(i8*, i8**)
 
-; CHECK: declare i8* @strtok(i8*, i8* nocapture readonly) [[G0]]
+; CHECK: declare i8* @strtok(i8*, i8* nocapture readonly) [[G1]]
 declare i8* @strtok(i8*, i8*)
 
-; CHECK: declare i8* @strtok_r(i8*, i8* nocapture readonly, i8**) [[G0]]
+; CHECK: declare i8* @strtok_r(i8*, i8* nocapture readonly, i8**) [[G1]]
 declare i8* @strtok_r(i8*, i8*, i8**)
 
-; CHECK: declare i64 @strtol(i8* readonly, i8** nocapture, i32) [[G0]]
+; CHECK: declare i64 @strtol(i8* readonly, i8** nocapture, i32) [[G1]]
 declare i64 @strtol(i8*, i8**, i32)
 
-; CHECK: declare x86_fp80 @strtold(i8* readonly, i8** nocapture) [[G0]]
+; CHECK: declare x86_fp80 @strtold(i8* readonly, i8** nocapture) [[G1]]
 declare x86_fp80 @strtold(i8*, i8**)
 
-; CHECK: declare i64 @strtoll(i8* readonly, i8** nocapture, i32) [[G0]]
+; CHECK: declare i64 @strtoll(i8* readonly, i8** nocapture, i32) [[G1]]
 declare i64 @strtoll(i8*, i8**, i32)
 
-; CHECK: declare i64 @strtoul(i8* readonly, i8** nocapture, i32) [[G0]]
+; CHECK: declare i64 @strtoul(i8* readonly, i8** nocapture, i32) [[G1]]
 declare i64 @strtoul(i8*, i8**, i32)
 
-; CHECK: declare i64 @strtoull(i8* readonly, i8** nocapture, i32) [[G0]]
+; CHECK: declare i64 @strtoull(i8* readonly, i8** nocapture, i32) [[G1]]
 declare i64 @strtoull(i8*, i8**, i32)
 
-; CHECK: declare i64 @strxfrm(i8* nocapture, i8* nocapture readonly, i64) [[G0]]
+; CHECK: declare i64 @strxfrm(i8* nocapture, i8* nocapture readonly, i64) [[G1]]
 declare i64 @strxfrm(i8*, i8*, i64)
 
-; CHECK: declare i32 @system(i8* nocapture readonly)
+; CHECK: declare i32 @system(i8* nocapture readonly) [[G0]]
 declare i32 @system(i8*)
 
-; CHECK: declare double @tan(double)
+; CHECK: declare double @tan(double) [[G0]]
 declare double @tan(double)
 
-; CHECK: declare float @tanf(float)
+; CHECK: declare float @tanf(float) [[G0]]
 declare float @tanf(float)
 
-; CHECK: declare double @tanh(double)
+; CHECK: declare double @tanh(double) [[G0]]
 declare double @tanh(double)
 
-; CHECK: declare float @tanhf(float)
+; CHECK: declare float @tanhf(float) [[G0]]
 declare float @tanhf(float)
 
-; CHECK: declare x86_fp80 @tanhl(x86_fp80)
+; CHECK: declare x86_fp80 @tanhl(x86_fp80) [[G0]]
 declare x86_fp80 @tanhl(x86_fp80)
 
-; CHECK: declare x86_fp80 @tanl(x86_fp80)
+; CHECK: declare x86_fp80 @tanl(x86_fp80) [[G0]]
 declare x86_fp80 @tanl(x86_fp80)
 
-; CHECK: declare i64 @times(%opaque* nocapture) [[G0]]
+; CHECK: declare i64 @times(%opaque* nocapture) [[G1]]
 declare i64 @times(%opaque*)
 
-; CHECK: declare noalias %opaque* @tmpfile() [[G0]]
+; CHECK: declare noalias %opaque* @tmpfile() [[G1]]
 declare %opaque* @tmpfile()
 
-; CHECK-LINUX: declare noalias %opaque* @tmpfile64() [[G0]]
+; CHECK-LINUX: declare noalias %opaque* @tmpfile64() [[G1]]
 declare %opaque* @tmpfile64()
 
-; CHECK: declare i32 @toascii(i32)
+; CHECK: declare i32 @toascii(i32) [[G0]]
 declare i32 @toascii(i32)
 
-; CHECK: declare double @trunc(double)
+; CHECK: declare double @trunc(double) [[G0]]
 declare double @trunc(double)
 
-; CHECK: declare float @truncf(float)
+; CHECK: declare float @truncf(float) [[G0]]
 declare float @truncf(float)
 
-; CHECK: declare x86_fp80 @truncl(x86_fp80)
+; CHECK: declare x86_fp80 @truncl(x86_fp80) [[G0]]
 declare x86_fp80 @truncl(x86_fp80)
 
-; CHECK: declare i32 @uname(%opaque* nocapture) [[G0]]
+; CHECK: declare i32 @uname(%opaque* nocapture) [[G1]]
 declare i32 @uname(%opaque*)
 
-; CHECK: declare i32 @ungetc(i32, %opaque* nocapture) [[G0]]
+; CHECK: declare i32 @ungetc(i32, %opaque* nocapture) [[G1]]
 declare i32 @ungetc(i32, %opaque*)
 
-; CHECK: declare i32 @unlink(i8* nocapture readonly) [[G0]]
+; CHECK: declare i32 @unlink(i8* nocapture readonly) [[G1]]
 declare i32 @unlink(i8*)
 
-; CHECK: declare i32 @unsetenv(i8* nocapture readonly) [[G0]]
+; CHECK: declare i32 @unsetenv(i8* nocapture readonly) [[G1]]
 declare i32 @unsetenv(i8*)
 
-; CHECK: declare i32 @utime(i8* nocapture readonly, %opaque* nocapture readonly) [[G0]]
+; CHECK: declare i32 @utime(i8* nocapture readonly, %opaque* nocapture readonly) [[G1]]
 declare i32 @utime(i8*, %opaque*)
 
-; CHECK: declare i32 @utimes(i8* nocapture readonly, %opaque* nocapture readonly) [[G0]]
+; CHECK: declare i32 @utimes(i8* nocapture readonly, %opaque* nocapture readonly) [[G1]]
 declare i32 @utimes(i8*, %opaque*)
 
-; CHECK: declare noalias i8* @valloc(i64) [[G0]]
+; CHECK: declare noalias i8* @valloc(i64) [[G1]]
 declare i8* @valloc(i64)
 
-; CHECK: declare i32 @vfprintf(%opaque* nocapture, i8* nocapture readonly, %opaque*) [[G0]]
+; CHECK: declare i32 @vfprintf(%opaque* nocapture, i8* nocapture readonly, %opaque*) [[G1]]
 declare i32 @vfprintf(%opaque*, i8*, %opaque*)
 
-; CHECK: declare i32 @vfscanf(%opaque* nocapture, i8* nocapture readonly, %opaque*) [[G0]]
+; CHECK: declare i32 @vfscanf(%opaque* nocapture, i8* nocapture readonly, %opaque*) [[G1]]
 declare i32 @vfscanf(%opaque*, i8*, %opaque*)
 
-; CHECK: declare i32 @vprintf(i8* nocapture readonly, %opaque*) [[G0]]
+; CHECK: declare i32 @vprintf(i8* nocapture readonly, %opaque*) [[G1]]
 declare i32 @vprintf(i8*, %opaque*)
 
-; CHECK: declare i32 @vscanf(i8* nocapture readonly, %opaque*) [[G0]]
+; CHECK: declare i32 @vscanf(i8* nocapture readonly, %opaque*) [[G1]]
 declare i32 @vscanf(i8*, %opaque*)
 
-; CHECK: declare i32 @vsnprintf(i8* nocapture, i64, i8* nocapture readonly, %opaque*) [[G0]]
+; CHECK: declare i32 @vsnprintf(i8* nocapture, i64, i8* nocapture readonly, %opaque*) [[G1]]
 declare i32 @vsnprintf(i8*, i64, i8*, %opaque*)
 
-; CHECK: declare i32 @vsprintf(i8* nocapture, i8* nocapture readonly, %opaque*) [[G0]]
+; CHECK: declare i32 @vsprintf(i8* nocapture, i8* nocapture readonly, %opaque*) [[G1]]
 declare i32 @vsprintf(i8*, i8*, %opaque*)
 
-; CHECK: declare i32 @vsscanf(i8* nocapture readonly, i8* nocapture readonly, %opaque*) [[G0]]
+; CHECK: declare i32 @vsscanf(i8* nocapture readonly, i8* nocapture readonly, %opaque*) [[G1]]
 declare i32 @vsscanf(i8*, i8*, %opaque*)
 
-; CHECK: declare i64 @write(i32, i8* nocapture readonly, i64)
+; CHECK: declare i64 @write(i32, i8* nocapture readonly, i64) [[G0]]
 declare i64 @write(i32, i8*, i64)
 
 
 ; memset_pattern16 isn't available everywhere.
-; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[G3:#[0-9]+]]
+; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[G5:#[0-9]+]]
 declare void @memset_pattern16(i8*, i8*, i64)
 
-
-; CHECK: attributes [[G0]] = { nounwind }
-; CHECK: attributes [[G1]] = { nounwind readonly }
-; CHECK: attributes [[G2]] = { argmemonly nounwind readonly }
-; CHECK-DARWIN: attributes [[G3]] = { argmemonly }
+; CHECK: attributes [[G0]] = { nofree }
+; CHECK: attributes [[G1]] = { nofree nounwind }
+; CHECK: attributes [[G2]] = { nofree nounwind readonly }
+; CHECK: attributes [[G3]] = { nounwind }
+; CHECK: attributes [[G4]] = { argmemonly nofree nounwind readonly }
+; CHECK-DARWIN: attributes [[G5]] = { argmemonly nofree }

Modified: llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll (original)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll Mon Jul  8 08:57:56 2019
@@ -52,5 +52,5 @@ attributes #1 = { nounwind readnone spec
 !28 = !DILocation(line: 9, column: 18, scope: !2)
 !29 = !DILocation(line: 10, column: 1, scope: !2)
 
-; CHECK: attributes #0 = { norecurse nounwind }
+; CHECK: attributes #0 = { nofree norecurse nounwind }
 ; CHECK-NOT foo.coefficient1

Modified: llvm/trunk/test/Transforms/LICM/strlen.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/strlen.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LICM/strlen.ll (original)
+++ llvm/trunk/test/Transforms/LICM/strlen.ll Mon Jul  8 08:57:56 2019
@@ -13,7 +13,7 @@ loop:
 }
 
 ; CHECK: declare i64 @strlen(i8* nocapture) #0
-; CHECK: attributes #0 = { argmemonly nounwind readonly }
+; CHECK: attributes #0 = { argmemonly nofree nounwind readonly }
 declare i64 @strlen(i8*)
 
 

Modified: llvm/trunk/test/Transforms/LoopIdiom/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopIdiom/basic.ll?rev=365336&r1=365335&r2=365336&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopIdiom/basic.ll (original)
+++ llvm/trunk/test/Transforms/LoopIdiom/basic.ll Mon Jul  8 08:57:56 2019
@@ -709,4 +709,4 @@ exit:
 
 ; Validate that "memset_pattern" has the proper attributes.
 ; CHECK: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[ATTRS:#[0-9]+]]
-; CHECK: [[ATTRS]] = { argmemonly }
+; CHECK: [[ATTRS]] = { argmemonly nofree }




More information about the llvm-commits mailing list