diff options
author | Brian Homerding <homerdin@gmail.com> | 2019-07-08 15:57:56 +0000 |
---|---|---|
committer | Brian Homerding <homerdin@gmail.com> | 2019-07-08 15:57:56 +0000 |
commit | b4b21d807e4f47f1f87b05fddf6bb3167b14476e (patch) | |
tree | 2ca1fdfcf72d73e5d6245cbd845c3f372e0a9dc9 | |
parent | b52a0c0cc88f0d66ae8ea770f92ed3448aee88a7 (diff) | |
download | bcm5719-llvm-b4b21d807e4f47f1f87b05fddf6bb3167b14476e.tar.gz bcm5719-llvm-b4b21d807e4f47f1f87b05fddf6bb3167b14476e.zip |
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
llvm-svn: 365336
30 files changed, 593 insertions, 331 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 8325e08e180..ae266629a64 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -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`` diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index 9a5c77d2c1b..49f9e58ffad 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -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 *V, const TargetLibraryInfo *TLI, 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 *I, const TargetLibraryInfo *TLI) { // 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); diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def index bbccca4ca66..afed404f04c 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -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) diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 5f3f7b1bd37..3ec0b383d54 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -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 { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 96dd915bca0..694a23a8045 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -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">; diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index b93541cbb16..7fa61e12f43 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -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 { diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 08254266482..d73419fad6a 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -263,6 +263,19 @@ bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, 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(const Value *I, 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 Value *I, const TargetLibraryInfo *TLI) { 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. // diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index a23afac27b7..5bc628dac1f 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -650,6 +650,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(nobuiltin); KEYWORD(nocapture); KEYWORD(noduplicate); + KEYWORD(nofree); KEYWORD(noimplicitfloat); KEYWORD(noinline); KEYWORD(norecurse); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 085f3bd2999..1256e632551 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1280,6 +1280,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, 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; diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 8b0118e6942..a6a81865cb7 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -195,6 +195,7 @@ enum Kind { kw_nobuiltin, kw_nocapture, kw_noduplicate, + kw_nofree, kw_noimplicitfloat, kw_noinline, kw_norecurse, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index a339f6eb710..0ba76f0f371 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1278,6 +1278,8 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) { 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 getAttrFromCode(uint64_t Code) { 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: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 547889f82c7..65b9e0bb6a1 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -639,6 +639,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { 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: diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 99fc447c5af..0073eda0838 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -321,6 +321,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "nocapture"; if (hasAttribute(Attribute::NoDuplicate)) return "noduplicate"; + if (hasAttribute(Attribute::NoFree)) + return "nofree"; if (hasAttribute(Attribute::NoImplicitFloat)) return "noimplicitfloat"; if (hasAttribute(Attribute::NoInline)) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index b0464346557..2655e3ce81e 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1497,6 +1497,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) { case Attribute::NoCfCheck: case Attribute::NoUnwind: case Attribute::NoInline: + case Attribute::NoFree: case Attribute::AlwaysInline: case Attribute::OptimizeForSize: case Attribute::StackProtect: diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 9e95e796da6..a3fb7d1d57a 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -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 function returns marked noalias"); 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> DisableNoUnwindInference( "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(Instruction &I, const SCCNodeSet &SCCNodes) { 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(const SCCNodeSet &SCCNodes) { }, /* 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 SCCNodeSet &SCCNodes) { } 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 PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C, 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 & { diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index d486d915998..27f110e24f9 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -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(Function &F, const TargetLibraryInfo &TLI) { bool Changed = false; + if(!isLibFreeFunction(&F, TheLibFunc) && !isReallocLikeFn(&F, &TLI)) + Changed |= setDoesNotFreeMemory(F); + if (F.getParent() != nullptr && F.getParent()->getRtLibUseGOT()) Changed |= setNonLazyBind(F); diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 23a404c11a6..c9e9033d9c1 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -814,6 +814,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::InlineHint: case Attribute::MinSize: case Attribute::NoDuplicate: + case Attribute::NoFree: case Attribute::NoImplicitFloat: case Attribute::NoInline: case Attribute::NonLazyBind: diff --git a/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll b/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll index e2b7c971dd8..63df6bd8400 100644 --- a/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll +++ b/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll @@ -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. diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll index 3aac9ee64ce..84630cd4bf8 100644 --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -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 } diff --git a/llvm/test/CodeGen/AMDGPU/inline-attr.ll b/llvm/test/CodeGen/AMDGPU/inline-attr.ll index 6f6b5f4c0b0..b44138d107a 100644 --- a/llvm/test/CodeGen/AMDGPU/inline-attr.ll +++ b/llvm/test/CodeGen/AMDGPU/inline-attr.ll @@ -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: diff --git a/llvm/test/CodeGen/X86/no-plt-libcalls.ll b/llvm/test/CodeGen/X86/no-plt-libcalls.ll index 795ad57f9a5..876c8f10e42 100644 --- a/llvm/test/CodeGen/X86/no-plt-libcalls.ll +++ b/llvm/test/CodeGen/X86/no-plt-libcalls.ll @@ -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} diff --git a/llvm/test/Feature/OperandBundles/function-attrs.ll b/llvm/test/Feature/OperandBundles/function-attrs.ll index 808f396fed8..6e1b2550399 100644 --- a/llvm/test/Feature/OperandBundles/function-attrs.ll +++ b/llvm/test/Feature/OperandBundles/function-attrs.ll @@ -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 } + diff --git a/llvm/test/Transforms/FunctionAttrs/atomic.ll b/llvm/test/Transforms/FunctionAttrs/atomic.ll index af87a28770e..35de0ce800d 100644 --- a/llvm/test/Transforms/FunctionAttrs/atomic.ll +++ b/llvm/test/Transforms/FunctionAttrs/atomic.ll @@ -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 } diff --git a/llvm/test/Transforms/FunctionAttrs/nofree.ll b/llvm/test/Transforms/FunctionAttrs/nofree.ll new file mode 100644 index 00000000000..e72ff2f5325 --- /dev/null +++ b/llvm/test/Transforms/FunctionAttrs/nofree.ll @@ -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 } + diff --git a/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll b/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll index 69808a83c6d..4ad195ea2b5 100644 --- a/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll +++ b/llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll @@ -14,4 +14,4 @@ define void @g() { } -; CHECK: attributes #0 = { nounwind } +; CHECK: attributes #0 = { nofree nounwind } diff --git a/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll b/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll index 0828db35fd2..be190b7c4d3 100644 --- a/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ b/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -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: ; preds = %if.end, %if.then 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: ; preds = %if.end, %if.then 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: ; preds = %if.end, %if.then 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: ; preds = %if.end, %if.then 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 # diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll index 02278161345..cb446476400 100644 --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -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 } diff --git a/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll b/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll index 575bbac5e5a..8ac037a7799 100644 --- a/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll @@ -52,5 +52,5 @@ attributes #1 = { nounwind readnone speculatable } !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 diff --git a/llvm/test/Transforms/LICM/strlen.ll b/llvm/test/Transforms/LICM/strlen.ll index 27d51c8394d..82b3374184d 100644 --- a/llvm/test/Transforms/LICM/strlen.ll +++ b/llvm/test/Transforms/LICM/strlen.ll @@ -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*) diff --git a/llvm/test/Transforms/LoopIdiom/basic.ll b/llvm/test/Transforms/LoopIdiom/basic.ll index 076e0224b81..89d8dab0d68 100644 --- a/llvm/test/Transforms/LoopIdiom/basic.ll +++ b/llvm/test/Transforms/LoopIdiom/basic.ll @@ -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 } |