[llvm] r256466 - [attrs] Extract the pure inference of function attributes into
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 12 15:52:02 PST 2016
On Tue, Jan 12, 2016 at 3:04 PM, Chandler Carruth <chandlerc at gmail.com>
wrote:
> On Tue, Jan 12, 2016 at 2:46 PM David Blaikie via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> On Sun, Dec 27, 2015 at 12:41 AM, Chandler Carruth via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>>
>>> Author: chandlerc
>>> Date: Sun Dec 27 02:41:34 2015
>>> New Revision: 256466
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=256466&view=rev
>>> Log:
>>> [attrs] Extract the pure inference of function attributes into
>>> a standalone pass.
>>>
>>> There is no call graph or even interesting analysis for this part of
>>> function attributes -- it is literally inferring attributes based on the
>>> target library identification. As such, we can do it using a much
>>> simpler module pass that just walks the declarations.
>>
>>
>> Just for my own curiosity - why would this be a module pass rather than a
>> function pass? (I assumed that you want the smallest scope pass possible
>> (less power for the pass, more versatility for the pass manager in
>> scheduling, etc) & it doesn't look like this does anything interprocedural,
>> as far as I understand)
>>
>> Maybe it's just an ordering constraint in the current/legacy pass manager
>> that won't be present in the new one?
>>
>
> Function passes don't run over declarations, they run over definitions.
>
> More-over, a function pass could process definition of function A and use
> attributes on the declaration of function B to do so. Function attributes
> are the only part of other functions that a function pass is allowed to
> use, but that means we can't mutate the attributes from within a function
> pass.
>
Ah, right. Thanks for the explanation!
- Dave
>
>
>>
>>
>>> This can also
>>> happen much earlier in the pass pipeline which has benefits for any
>>> number of other passes.
>>>
>>> In the process, I've cleaned up one particular aspect of the logic which
>>> was necessary in order to separate the two passes cleanly. It now counts
>>> inferred attributes independently rather than just counting all the
>>> inferred attributes as one, and the counts are more clearly explained.
>>>
>>> The two test cases we had for this code path are both ... woefully
>>> inadequate and copies of each other. I've kept the superset test and
>>> updated it. We need more testing here, but I had to pick somewhere to
>>> stop fixing everything broken I saw here.
>>>
>>> Differential Revision: http://reviews.llvm.org/D15676
>>>
>>> Added:
>>> llvm/trunk/include/llvm/Transforms/IPO/InferFunctionAttrs.h
>>> llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp
>>> llvm/trunk/test/Transforms/InferFunctionAttrs/
>>> llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll
>>> - copied, changed from r256465,
>>> llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll
>>> Removed:
>>> llvm/trunk/test/Transforms/FunctionAttrs/2009-01-04-Annotate.ll
>>> llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll
>>> Modified:
>>> llvm/trunk/include/llvm/InitializePasses.h
>>> llvm/trunk/lib/Passes/PassBuilder.cpp
>>> llvm/trunk/lib/Passes/PassRegistry.def
>>> llvm/trunk/lib/Transforms/IPO/CMakeLists.txt
>>> llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
>>> llvm/trunk/lib/Transforms/IPO/IPO.cpp
>>> llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
>>> llvm/trunk/test/Transforms/InstCombine/strto-1.ll
>>>
>>> Modified: llvm/trunk/include/llvm/InitializePasses.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/InitializePasses.h (original)
>>> +++ llvm/trunk/include/llvm/InitializePasses.h Sun Dec 27 02:41:34 2015
>>> @@ -145,6 +145,7 @@ void initializeIVUsersPass(PassRegistry&
>>> void initializeIfConverterPass(PassRegistry&);
>>> void initializeInductiveRangeCheckEliminationPass(PassRegistry&);
>>> void initializeIndVarSimplifyPass(PassRegistry&);
>>> +void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&);
>>> void initializeInlineCostAnalysisPass(PassRegistry&);
>>> void initializeInstructionCombiningPassPass(PassRegistry&);
>>> void initializeInstCountPass(PassRegistry&);
>>>
>>> Added: llvm/trunk/include/llvm/Transforms/IPO/InferFunctionAttrs.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/InferFunctionAttrs.h?rev=256466&view=auto
>>>
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/Transforms/IPO/InferFunctionAttrs.h (added)
>>> +++ llvm/trunk/include/llvm/Transforms/IPO/InferFunctionAttrs.h Sun Dec
>>> 27 02:41:34 2015
>>> @@ -0,0 +1,38 @@
>>> +//===-- InferFunctionAttrs.h - Infer implicit function attributes
>>> ---------===//
>>> +//
>>> +// The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is distributed under the University of Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +///
>>> +/// \file
>>> +/// Interfaces for passes which infer implicit function attributes from
>>> the
>>> +/// name and signature of function declarations.
>>> +///
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#ifndef LLVM_TRANSFORMS_IPO_INFERFUNCTIONATTRS_H
>>> +#define LLVM_TRANSFORMS_IPO_INFERFUNCTIONATTRS_H
>>> +
>>> +#include "llvm/IR/Module.h"
>>> +#include "llvm/IR/PassManager.h"
>>> +
>>> +namespace llvm {
>>> +
>>> +/// A pass which infers function attributes from the names and
>>> signatures of
>>> +/// function declarations in a module.
>>> +class InferFunctionAttrsPass {
>>> +public:
>>> + static StringRef name() { return "InferFunctionAttrsPass"; }
>>> + PreservedAnalyses run(Module &M, AnalysisManager<Module> *AM);
>>> +};
>>> +
>>> +/// Create a legacy pass manager instance of a pass to infer function
>>> +/// attributes.
>>> +Pass *createInferFunctionAttrsLegacyPass();
>>> +
>>> +}
>>> +
>>> +#endif // LLVM_TRANSFORMS_IPO_INFERFUNCTIONATTRS_H
>>>
>>> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
>>> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Sun Dec 27 02:41:34 2015
>>> @@ -30,6 +30,7 @@
>>> #include "llvm/Support/Debug.h"
>>> #include "llvm/Target/TargetMachine.h"
>>> #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
>>> +#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
>>> #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
>>> #include "llvm/Transforms/InstCombine/InstCombine.h"
>>> #include "llvm/Transforms/Scalar/ADCE.h"
>>>
>>> Modified: llvm/trunk/lib/Passes/PassRegistry.def
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Passes/PassRegistry.def (original)
>>> +++ llvm/trunk/lib/Passes/PassRegistry.def Sun Dec 27 02:41:34 2015
>>> @@ -28,6 +28,7 @@ MODULE_ANALYSIS("targetlibinfo", TargetL
>>> #define MODULE_PASS(NAME, CREATE_PASS)
>>> #endif
>>> MODULE_PASS("forceattrs", ForceFunctionAttrsPass())
>>> +MODULE_PASS("inferattrs", InferFunctionAttrsPass())
>>> MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass())
>>> MODULE_PASS("no-op-module", NoOpModulePass())
>>> MODULE_PASS("print", PrintModulePass(dbgs()))
>>>
>>> Modified: llvm/trunk/lib/Transforms/IPO/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/CMakeLists.txt?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Transforms/IPO/CMakeLists.txt (original)
>>> +++ llvm/trunk/lib/Transforms/IPO/CMakeLists.txt Sun Dec 27 02:41:34 2015
>>> @@ -13,6 +13,7 @@ add_llvm_library(LLVMipo
>>> GlobalOpt.cpp
>>> IPConstantPropagation.cpp
>>> IPO.cpp
>>> + InferFunctionAttrs.cpp
>>> InlineAlways.cpp
>>> InlineSimple.cpp
>>> Inliner.cpp
>>>
>>> Modified: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp Sun Dec 27 02:41:34
>>> 2015
>>> @@ -50,7 +50,6 @@ STATISTIC(NumReadNoneArg, "Number of arg
>>> STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly");
>>> STATISTIC(NumNoAlias, "Number of function returns marked noalias");
>>> STATISTIC(NumNonNullReturn, "Number of function returns marked
>>> nonnull");
>>> -STATISTIC(NumAnnotated, "Number of attributes added to library
>>> functions");
>>> STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
>>>
>>> namespace {
>>> @@ -942,48 +941,6 @@ static bool addNonNullAttrs(const SCCNod
>>> return MadeChange;
>>> }
>>>
>>> -static void setDoesNotAccessMemory(Function &F) {
>>> - if (!F.doesNotAccessMemory()) {
>>> - F.setDoesNotAccessMemory();
>>> - ++NumAnnotated;
>>> - }
>>> -}
>>> -
>>> -static void setOnlyReadsMemory(Function &F) {
>>> - if (!F.onlyReadsMemory()) {
>>> - F.setOnlyReadsMemory();
>>> - ++NumAnnotated;
>>> - }
>>> -}
>>> -
>>> -static void setDoesNotThrow(Function &F) {
>>> - if (!F.doesNotThrow()) {
>>> - F.setDoesNotThrow();
>>> - ++NumAnnotated;
>>> - }
>>> -}
>>> -
>>> -static void setDoesNotCapture(Function &F, unsigned n) {
>>> - if (!F.doesNotCapture(n)) {
>>> - F.setDoesNotCapture(n);
>>> - ++NumAnnotated;
>>> - }
>>> -}
>>> -
>>> -static void setOnlyReadsMemory(Function &F, unsigned n) {
>>> - if (!F.onlyReadsMemory(n)) {
>>> - F.setOnlyReadsMemory(n);
>>> - ++NumAnnotated;
>>> - }
>>> -}
>>> -
>>> -static void setDoesNotAlias(Function &F, unsigned n) {
>>> - if (!F.doesNotAlias(n)) {
>>> - F.setDoesNotAlias(n);
>>> - ++NumAnnotated;
>>> - }
>>> -}
>>> -
>>> static bool setDoesNotRecurse(Function &F) {
>>> if (F.doesNotRecurse())
>>> return false;
>>> @@ -992,809 +949,6 @@ static bool setDoesNotRecurse(Function &
>>> return true;
>>> }
>>>
>>> -/// Analyze the name and prototype of the given function and set any
>>> applicable
>>> -/// attributes.
>>> -///
>>> -/// Returns true if any attributes were set and false otherwise.
>>> -static bool inferPrototypeAttributes(Function &F, const
>>> TargetLibraryInfo &TLI) {
>>> - if (F.hasFnAttribute(Attribute::OptimizeNone))
>>> - return false;
>>> -
>>> - FunctionType *FTy = F.getFunctionType();
>>> - LibFunc::Func TheLibFunc;
>>> - if (!(TLI.getLibFunc(F.getName(), TheLibFunc) && TLI.has(TheLibFunc)))
>>> - return false;
>>> -
>>> - switch (TheLibFunc) {
>>> - case LibFunc::strlen:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::strchr:
>>> - case LibFunc::strrchr:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isIntegerTy())
>>> - return false;
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotThrow(F);
>>> - break;
>>> - case LibFunc::strtol:
>>> - case LibFunc::strtod:
>>> - case LibFunc::strtof:
>>> - case LibFunc::strtoul:
>>> - case LibFunc::strtoll:
>>> - case LibFunc::strtold:
>>> - case LibFunc::strtoull:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::strcpy:
>>> - case LibFunc::stpcpy:
>>> - case LibFunc::strcat:
>>> - case LibFunc::strncat:
>>> - case LibFunc::strncpy:
>>> - case LibFunc::stpncpy:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::strxfrm:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::strcmp: // 0,1
>>> - case LibFunc::strspn: // 0,1
>>> - case LibFunc::strncmp: // 0,1
>>> - case LibFunc::strcspn: // 0,1
>>> - case LibFunc::strcoll: // 0,1
>>> - case LibFunc::strcasecmp: // 0,1
>>> - case LibFunc::strncasecmp: //
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::strstr:
>>> - case LibFunc::strpbrk:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::strtok:
>>> - case LibFunc::strtok_r:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::scanf:
>>> - if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::setbuf:
>>> - case LibFunc::setvbuf:
>>> - if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::strdup:
>>> - case LibFunc::strndup:
>>> - if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy()
>>> ||
>>> - !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::stat:
>>> - case LibFunc::statvfs:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::sscanf:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::sprintf:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::snprintf:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(2)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 3);
>>> - setOnlyReadsMemory(F, 3);
>>> - break;
>>> - case LibFunc::setitimer:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy() ||
>>> - !FTy->getParamType(2)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - setDoesNotCapture(F, 3);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::system:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - // May throw; "system" is a valid pthread cancellation point.
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::malloc:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getReturnType()->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - break;
>>> - case LibFunc::memcmp:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::memchr:
>>> - case LibFunc::memrchr:
>>> - if (FTy->getNumParams() != 3)
>>> - return false;
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotThrow(F);
>>> - break;
>>> - case LibFunc::modf:
>>> - case LibFunc::modff:
>>> - case LibFunc::modfl:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::memcpy:
>>> - case LibFunc::memccpy:
>>> - case LibFunc::memmove:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::memalign:
>>> - if (!FTy->getReturnType()->isPointerTy())
>>> - return false;
>>> - setDoesNotAlias(F, 0);
>>> - break;
>>> - case LibFunc::mkdir:
>>> - if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::mktime:
>>> - if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::realloc:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getReturnType()->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::read:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - // May throw; "read" is a valid pthread cancellation point.
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::rewind:
>>> - if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::rmdir:
>>> - case LibFunc::remove:
>>> - case LibFunc::realpath:
>>> - if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::rename:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::readlink:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::write:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - // May throw; "write" is a valid pthread cancellation point.
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::bcopy:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::bcmp:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::bzero:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::calloc:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - break;
>>> - case LibFunc::chmod:
>>> - case LibFunc::chown:
>>> - if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::ctermid:
>>> - case LibFunc::clearerr:
>>> - case LibFunc::closedir:
>>> - if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::atoi:
>>> - case LibFunc::atol:
>>> - case LibFunc::atof:
>>> - case LibFunc::atoll:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::access:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::fopen:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> - !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::fdopen:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::feof:
>>> - case LibFunc::free:
>>> - case LibFunc::fseek:
>>> - case LibFunc::ftell:
>>> - case LibFunc::fgetc:
>>> - case LibFunc::fseeko:
>>> - case LibFunc::ftello:
>>> - case LibFunc::fileno:
>>> - case LibFunc::fflush:
>>> - case LibFunc::fclose:
>>> - case LibFunc::fsetpos:
>>> - case LibFunc::flockfile:
>>> - case LibFunc::funlockfile:
>>> - case LibFunc::ftrylockfile:
>>> - if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::ferror:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F);
>>> - break;
>>> - case LibFunc::fputc:
>>> - case LibFunc::fstat:
>>> - case LibFunc::frexp:
>>> - case LibFunc::frexpf:
>>> - case LibFunc::frexpl:
>>> - case LibFunc::fstatvfs:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::fgets:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(2)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 3);
>>> - break;
>>> - case LibFunc::fread:
>>> - if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(3)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 4);
>>> - break;
>>> - case LibFunc::fwrite:
>>> - if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(3)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 4);
>>> - break;
>>> - case LibFunc::fputs:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::fscanf:
>>> - case LibFunc::fprintf:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::fgetpos:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::getc:
>>> - case LibFunc::getlogin_r:
>>> - case LibFunc::getc_unlocked:
>>> - if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::getenv:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setOnlyReadsMemory(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::gets:
>>> - case LibFunc::getchar:
>>> - setDoesNotThrow(F);
>>> - break;
>>> - case LibFunc::getitimer:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::getpwnam:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::ungetc:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::uname:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::unlink:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::unsetenv:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::utime:
>>> - case LibFunc::utimes:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::putc:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::puts:
>>> - case LibFunc::printf:
>>> - case LibFunc::perror:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::pread:
>>> - if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - // May throw; "pread" is a valid pthread cancellation point.
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::pwrite:
>>> - if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - // May throw; "pwrite" is a valid pthread cancellation point.
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::putchar:
>>> - setDoesNotThrow(F);
>>> - break;
>>> - case LibFunc::popen:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> - !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::pclose:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::vscanf:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::vsscanf:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy() ||
>>> - !FTy->getParamType(2)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::vfscanf:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy() ||
>>> - !FTy->getParamType(2)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::valloc:
>>> - if (!FTy->getReturnType()->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - break;
>>> - case LibFunc::vprintf:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::vfprintf:
>>> - case LibFunc::vsprintf:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::vsnprintf:
>>> - if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(2)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 3);
>>> - setOnlyReadsMemory(F, 3);
>>> - break;
>>> - case LibFunc::open:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - // May throw; "open" is a valid pthread cancellation point.
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::opendir:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> - !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::tmpfile:
>>> - if (!FTy->getReturnType()->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - break;
>>> - case LibFunc::times:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::htonl:
>>> - case LibFunc::htons:
>>> - case LibFunc::ntohl:
>>> - case LibFunc::ntohs:
>>> - setDoesNotThrow(F);
>>> - setDoesNotAccessMemory(F);
>>> - break;
>>> - case LibFunc::lstat:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::lchown:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::qsort:
>>> - if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(3)->isPointerTy())
>>> - return false;
>>> - // May throw; places call through function pointer.
>>> - setDoesNotCapture(F, 4);
>>> - break;
>>> - case LibFunc::dunder_strdup:
>>> - case LibFunc::dunder_strndup:
>>> - if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy()
>>> ||
>>> - !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::dunder_strtok_r:
>>> - if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::under_IO_getc:
>>> - if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::under_IO_putc:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::dunder_isoc99_scanf:
>>> - if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::stat64:
>>> - case LibFunc::lstat64:
>>> - case LibFunc::statvfs64:
>>> - if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::dunder_isoc99_sscanf:
>>> - if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::fopen64:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> - !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - setOnlyReadsMemory(F, 1);
>>> - setOnlyReadsMemory(F, 2);
>>> - break;
>>> - case LibFunc::fseeko64:
>>> - case LibFunc::ftello64:
>>> - if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - break;
>>> - case LibFunc::tmpfile64:
>>> - if (!FTy->getReturnType()->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotAlias(F, 0);
>>> - break;
>>> - case LibFunc::fstat64:
>>> - case LibFunc::fstatvfs64:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - case LibFunc::open64:
>>> - if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
>>> - return false;
>>> - // May throw; "open" is a valid pthread cancellation point.
>>> - setDoesNotCapture(F, 1);
>>> - setOnlyReadsMemory(F, 1);
>>> - break;
>>> - case LibFunc::gettimeofday:
>>> - if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> - !FTy->getParamType(1)->isPointerTy())
>>> - return false;
>>> - // Currently some platforms have the restrict keyword on the
>>> arguments to
>>> - // gettimeofday. To be conservative, do not add noalias to
>>> gettimeofday's
>>> - // arguments.
>>> - setDoesNotThrow(F);
>>> - setDoesNotCapture(F, 1);
>>> - setDoesNotCapture(F, 2);
>>> - break;
>>> - default:
>>> - // Didn't mark any attributes.
>>> - return false;
>>> - }
>>> -
>>> - return true;
>>> -}
>>> -
>>> static bool addNoRecurseAttrs(const CallGraphSCC &SCC,
>>> SmallVectorImpl<WeakVH> &Revisit) {
>>> // Try and identify functions that do not recurse.
>>> @@ -1874,18 +1028,13 @@ bool FunctionAttrs::runOnSCC(CallGraphSC
>>> continue;
>>> }
>>>
>>> - // When initially processing functions, also infer their prototype
>>> - // attributes if they are declarations.
>>> - if (F->isDeclaration())
>>> - Changed |= inferPrototypeAttributes(*F, *TLI);
>>> -
>>> SCCNodes.insert(F);
>>> }
>>>
>>> Changed |= addReadAttrs(SCCNodes, AARGetter);
>>> Changed |= addArgumentAttrs(SCCNodes);
>>>
>>> - // If we have no external nodes participating in the SCC, we can
>>> infer some
>>> + // If we have no external nodes participating in the SCC, we can
>>> deduce some
>>> // more precise attributes as well.
>>> if (!ExternalNode) {
>>> Changed |= addNoAliasAttrs(SCCNodes);
>>>
>>> Modified: llvm/trunk/lib/Transforms/IPO/IPO.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPO.cpp?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Transforms/IPO/IPO.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/IPO/IPO.cpp Sun Dec 27 02:41:34 2015
>>> @@ -34,6 +34,7 @@ void llvm::initializeIPO(PassRegistry &R
>>> initializeIPCPPass(Registry);
>>> initializeAlwaysInlinerPass(Registry);
>>> initializeSimpleInlinerPass(Registry);
>>> + initializeInferFunctionAttrsLegacyPassPass(Registry);
>>> initializeInternalizePassPass(Registry);
>>> initializeLoopExtractorPass(Registry);
>>> initializeBlockExtractorPassPass(Registry);
>>>
>>> Added: llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp?rev=256466&view=auto
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp (added)
>>> +++ llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp Sun Dec 27
>>> 02:41:34 2015
>>> @@ -0,0 +1,937 @@
>>> +//===- InferFunctionAttrs.cpp - Infer implicit function attributes
>>> --------===//
>>> +//
>>> +// The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is distributed under the University of Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
>>> +#include "llvm/ADT/Statistic.h"
>>> +#include "llvm/Analysis/TargetLibraryInfo.h"
>>> +#include "llvm/IR/Function.h"
>>> +#include "llvm/IR/LLVMContext.h"
>>> +#include "llvm/IR/Module.h"
>>> +#include "llvm/Support/Debug.h"
>>> +#include "llvm/Support/raw_ostream.h"
>>> +using namespace llvm;
>>> +
>>> +#define DEBUG_TYPE "inferattrs"
>>> +
>>> +STATISTIC(NumReadNone, "Number of functions inferred as readnone");
>>> +STATISTIC(NumReadOnly, "Number of functions inferred as readonly");
>>> +STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
>>> +STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
>>> +STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly");
>>> +STATISTIC(NumNoAlias, "Number of function returns inferred as noalias");
>>> +
>>> +static bool setDoesNotAccessMemory(Function &F) {
>>> + if (F.doesNotAccessMemory())
>>> + return false;
>>> + F.setDoesNotAccessMemory();
>>> + ++NumReadNone;
>>> + return true;
>>> +}
>>> +
>>> +static bool setOnlyReadsMemory(Function &F) {
>>> + if (F.onlyReadsMemory())
>>> + return false;
>>> + F.setOnlyReadsMemory();
>>> + ++NumReadOnly;
>>> + return true;
>>> +}
>>> +
>>> +static bool setDoesNotThrow(Function &F) {
>>> + if (F.doesNotThrow())
>>> + return false;
>>> + F.setDoesNotThrow();
>>> + ++NumNoUnwind;
>>> + return true;
>>> +}
>>> +
>>> +static bool setDoesNotCapture(Function &F, unsigned n) {
>>> + if (F.doesNotCapture(n))
>>> + return false;
>>> + F.setDoesNotCapture(n);
>>> + ++NumNoCapture;
>>> + return true;
>>> +}
>>> +
>>> +static bool setOnlyReadsMemory(Function &F, unsigned n) {
>>> + if (F.onlyReadsMemory(n))
>>> + return false;
>>> + F.setOnlyReadsMemory(n);
>>> + ++NumReadOnlyArg;
>>> + return true;
>>> +}
>>> +
>>> +static bool setDoesNotAlias(Function &F, unsigned n) {
>>> + if (F.doesNotAlias(n))
>>> + return false;
>>> + F.setDoesNotAlias(n);
>>> + ++NumNoAlias;
>>> + return true;
>>> +}
>>> +
>>> +/// Analyze the name and prototype of the given function and set any
>>> applicable
>>> +/// attributes.
>>> +///
>>> +/// Returns true if any attributes were set and false otherwise.
>>> +static bool inferPrototypeAttributes(Function &F,
>>> + const TargetLibraryInfo &TLI) {
>>> + if (F.hasFnAttribute(Attribute::OptimizeNone))
>>> + return false;
>>> +
>>> + FunctionType *FTy = F.getFunctionType();
>>> + LibFunc::Func TheLibFunc;
>>> + if (!(TLI.getLibFunc(F.getName(), TheLibFunc) && TLI.has(TheLibFunc)))
>>> + return false;
>>> +
>>> + bool Changed = false;
>>> +
>>> + switch (TheLibFunc) {
>>> + case LibFunc::strlen:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::strchr:
>>> + case LibFunc::strrchr:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isIntegerTy())
>>> + return false;
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotThrow(F);
>>> + return Changed;
>>> + case LibFunc::strtol:
>>> + case LibFunc::strtod:
>>> + case LibFunc::strtof:
>>> + case LibFunc::strtoul:
>>> + case LibFunc::strtoll:
>>> + case LibFunc::strtold:
>>> + case LibFunc::strtoull:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::strcpy:
>>> + case LibFunc::stpcpy:
>>> + case LibFunc::strcat:
>>> + case LibFunc::strncat:
>>> + case LibFunc::strncpy:
>>> + case LibFunc::stpncpy:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::strxfrm:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::strcmp: // 0,1
>>> + case LibFunc::strspn: // 0,1
>>> + case LibFunc::strncmp: // 0,1
>>> + case LibFunc::strcspn: // 0,1
>>> + case LibFunc::strcoll: // 0,1
>>> + case LibFunc::strcasecmp: // 0,1
>>> + case LibFunc::strncasecmp: //
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::strstr:
>>> + case LibFunc::strpbrk:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::strtok:
>>> + case LibFunc::strtok_r:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::scanf:
>>> + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::setbuf:
>>> + case LibFunc::setvbuf:
>>> + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::strdup:
>>> + case LibFunc::strndup:
>>> + if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy()
>>> ||
>>> + !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::stat:
>>> + case LibFunc::statvfs:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::sscanf:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::sprintf:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::snprintf:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(2)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 3);
>>> + Changed |= setOnlyReadsMemory(F, 3);
>>> + return Changed;
>>> + case LibFunc::setitimer:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy() ||
>>> + !FTy->getParamType(2)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setDoesNotCapture(F, 3);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::system:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + // May throw; "system" is a valid pthread cancellation point.
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::malloc:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getReturnType()->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + return Changed;
>>> + case LibFunc::memcmp:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::memchr:
>>> + case LibFunc::memrchr:
>>> + if (FTy->getNumParams() != 3)
>>> + return false;
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotThrow(F);
>>> + return Changed;
>>> + case LibFunc::modf:
>>> + case LibFunc::modff:
>>> + case LibFunc::modfl:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::memcpy:
>>> + case LibFunc::memccpy:
>>> + case LibFunc::memmove:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::memalign:
>>> + if (!FTy->getReturnType()->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + return Changed;
>>> + case LibFunc::mkdir:
>>> + if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::mktime:
>>> + if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::realloc:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getReturnType()->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::read:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + // May throw; "read" is a valid pthread cancellation point.
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::rewind:
>>> + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::rmdir:
>>> + case LibFunc::remove:
>>> + case LibFunc::realpath:
>>> + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::rename:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::readlink:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::write:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + // May throw; "write" is a valid pthread cancellation point.
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::bcopy:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::bcmp:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::bzero:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::calloc:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + return Changed;
>>> + case LibFunc::chmod:
>>> + case LibFunc::chown:
>>> + if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::ctermid:
>>> + case LibFunc::clearerr:
>>> + case LibFunc::closedir:
>>> + if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::atoi:
>>> + case LibFunc::atol:
>>> + case LibFunc::atof:
>>> + case LibFunc::atoll:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::access:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::fopen:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> + !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::fdopen:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::feof:
>>> + case LibFunc::free:
>>> + case LibFunc::fseek:
>>> + case LibFunc::ftell:
>>> + case LibFunc::fgetc:
>>> + case LibFunc::fseeko:
>>> + case LibFunc::ftello:
>>> + case LibFunc::fileno:
>>> + case LibFunc::fflush:
>>> + case LibFunc::fclose:
>>> + case LibFunc::fsetpos:
>>> + case LibFunc::flockfile:
>>> + case LibFunc::funlockfile:
>>> + case LibFunc::ftrylockfile:
>>> + if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::ferror:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F);
>>> + return Changed;
>>> + case LibFunc::fputc:
>>> + case LibFunc::fstat:
>>> + case LibFunc::frexp:
>>> + case LibFunc::frexpf:
>>> + case LibFunc::frexpl:
>>> + case LibFunc::fstatvfs:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::fgets:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(2)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 3);
>>> + return Changed;
>>> + case LibFunc::fread:
>>> + if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(3)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 4);
>>> + return Changed;
>>> + case LibFunc::fwrite:
>>> + if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(3)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 4);
>>> + return Changed;
>>> + case LibFunc::fputs:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::fscanf:
>>> + case LibFunc::fprintf:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::fgetpos:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::getc:
>>> + case LibFunc::getlogin_r:
>>> + case LibFunc::getc_unlocked:
>>> + if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::getenv:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setOnlyReadsMemory(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::gets:
>>> + case LibFunc::getchar:
>>> + Changed |= setDoesNotThrow(F);
>>> + return Changed;
>>> + case LibFunc::getitimer:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::getpwnam:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::ungetc:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::uname:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::unlink:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::unsetenv:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::utime:
>>> + case LibFunc::utimes:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::putc:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::puts:
>>> + case LibFunc::printf:
>>> + case LibFunc::perror:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::pread:
>>> + if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + // May throw; "pread" is a valid pthread cancellation point.
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::pwrite:
>>> + if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + // May throw; "pwrite" is a valid pthread cancellation point.
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::putchar:
>>> + Changed |= setDoesNotThrow(F);
>>> + return Changed;
>>> + case LibFunc::popen:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> + !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::pclose:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::vscanf:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::vsscanf:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy() ||
>>> + !FTy->getParamType(2)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::vfscanf:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy() ||
>>> + !FTy->getParamType(2)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::valloc:
>>> + if (!FTy->getReturnType()->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + return Changed;
>>> + case LibFunc::vprintf:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::vfprintf:
>>> + case LibFunc::vsprintf:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::vsnprintf:
>>> + if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(2)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 3);
>>> + Changed |= setOnlyReadsMemory(F, 3);
>>> + return Changed;
>>> + case LibFunc::open:
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + // May throw; "open" is a valid pthread cancellation point.
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::opendir:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> + !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::tmpfile:
>>> + if (!FTy->getReturnType()->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + return Changed;
>>> + case LibFunc::times:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::htonl:
>>> + case LibFunc::htons:
>>> + case LibFunc::ntohl:
>>> + case LibFunc::ntohs:
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAccessMemory(F);
>>> + return Changed;
>>> + case LibFunc::lstat:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::lchown:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::qsort:
>>> + if (FTy->getNumParams() != 4 ||
>>> !FTy->getParamType(3)->isPointerTy())
>>> + return false;
>>> + // May throw; places call through function pointer.
>>> + Changed |= setDoesNotCapture(F, 4);
>>> + return Changed;
>>> + case LibFunc::dunder_strdup:
>>> + case LibFunc::dunder_strndup:
>>> + if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy()
>>> ||
>>> + !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::dunder_strtok_r:
>>> + if (FTy->getNumParams() != 3 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::under_IO_getc:
>>> + if (FTy->getNumParams() != 1 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::under_IO_putc:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> + case LibFunc::dunder_isoc99_scanf:
>>> + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::stat64:
>>> + case LibFunc::lstat64:
>>> + case LibFunc::statvfs64:
>>> + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>> + case LibFunc::dunder_isoc99_sscanf:
>>> + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy()
>>> ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::fopen64:
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getReturnType()->isPointerTy() ||
>>> + !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 2);
>>> + return Changed;
>>> + case LibFunc::fseeko64:
>>> + case LibFunc::ftello64:
>>> + if (FTy->getNumParams() == 0 ||
>>> !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + return Changed;
>>> + case LibFunc::tmpfile64:
>>> + if (!FTy->getReturnType()->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotAlias(F, 0);
>>> + return Changed;
>>> + case LibFunc::fstat64:
>>>
>> + case LibFunc::fstatvfs64:
>>
>>
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>>
>> + case LibFunc::open64:
>>
>>
>>> + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
>>> + return false;
>>> + // May throw; "open" is a valid pthread cancellation point.
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setOnlyReadsMemory(F, 1);
>>> + return Changed;
>>>
>> + case LibFunc::gettimeofday:
>>
>>
>>> + if (FTy->getNumParams() != 2 ||
>>> !FTy->getParamType(0)->isPointerTy() ||
>>> + !FTy->getParamType(1)->isPointerTy())
>>> + return false;
>>>
>> + // Currently some platforms have the restrict keyword on the
>>> arguments to
>>> + // gettimeofday. To be conservative, do not add noalias to
>>> gettimeofday's
>>> + // arguments.
>>
>>
>>> + Changed |= setDoesNotThrow(F);
>>> + Changed |= setDoesNotCapture(F, 1);
>>> + Changed |= setDoesNotCapture(F, 2);
>>> + return Changed;
>>> +
>>>
>> + default:
>>> + // FIXME: It'd be really nice to cover all the library functions
>>> we're
>>> + // aware of here.
>>
>>
>>> + return false;
>>> + }
>>> +}
>>>
>> +
>>> +static bool inferAllPrototypeAttributes(Module &M,
>>> + const TargetLibraryInfo &TLI) {
>>
>>
>>> + bool Changed = false;
>>> +
>>>
>> + for (Function &F : M.functions())
>>> + // We only infer things using the prototype if the definition isn't
>>> around
>>> + // to analyze directly.
>>> + if (F.isDeclaration())
>>> + Changed |= inferPrototypeAttributes(F, TLI);
>>> +
>>> + return Changed;
>>> +}
>>> +
>>> +PreservedAnalyses InferFunctionAttrsPass::run(Module &M,
>>> + AnalysisManager<Module>
>>> *AM) {
>>> + auto &TLI = AM->getResult<TargetLibraryAnalysis>(M);
>>> +
>>> + if (!inferAllPrototypeAttributes(M, TLI))
>>> + // If we didn't infer anything, preserve all analyses.
>>> + return PreservedAnalyses::all();
>>> +
>>> + // Otherwise, we may have changed fundamental function attributes, so
>>> clear
>>> + // out all the passes.
>>> + return PreservedAnalyses::none();
>>> +}
>>> +
>>> +namespace {
>>> +struct InferFunctionAttrsLegacyPass : public ModulePass {
>>> + static char ID; // Pass identification, replacement for typeid
>>> + InferFunctionAttrsLegacyPass() : ModulePass(ID) {
>>> + initializeInferFunctionAttrsLegacyPassPass(
>>> + *PassRegistry::getPassRegistry());
>>> + }
>>> +
>>> + void getAnalysisUsage(AnalysisUsage &AU) const override {
>>> + AU.addRequired<TargetLibraryInfoWrapperPass>();
>>> + }
>>> +
>>> + bool runOnModule(Module &M) override {
>>> + auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
>>> + return inferAllPrototypeAttributes(M, TLI);
>>> + }
>>> +};
>>> +}
>>> +
>>> +char InferFunctionAttrsLegacyPass::ID = 0;
>>> +INITIALIZE_PASS_BEGIN(InferFunctionAttrsLegacyPass, "inferattrs",
>>> + "Infer set function attributes", false, false)
>>> +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
>>> +INITIALIZE_PASS_END(InferFunctionAttrsLegacyPass, "inferattrs",
>>> + "Infer set function attributes", false, false)
>>> +
>>> +Pass *llvm::createInferFunctionAttrsLegacyPass() {
>>> + return new InferFunctionAttrsLegacyPass();
>>> +}
>>>
>>> Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Sun Dec 27
>>> 02:41:34 2015
>>> @@ -12,26 +12,26 @@
>>> //
>>>
>>> //===----------------------------------------------------------------------===//
>>>
>>> -
>>> #include "llvm/Transforms/IPO/PassManagerBuilder.h"
>>> #include "llvm-c/Transforms/PassManagerBuilder.h"
>>> #include "llvm/ADT/SmallVector.h"
>>> -#include "llvm/Analysis/Passes.h"
>>> -#include "llvm/IR/DataLayout.h"
>>> -#include "llvm/IR/FunctionInfo.h"
>>> -#include "llvm/IR/Verifier.h"
>>> -#include "llvm/IR/LegacyPassManager.h"
>>> -#include "llvm/Support/CommandLine.h"
>>> -#include "llvm/Support/ManagedStatic.h"
>>> #include "llvm/Analysis/BasicAliasAnalysis.h"
>>> #include "llvm/Analysis/CFLAliasAnalysis.h"
>>> #include "llvm/Analysis/GlobalsModRef.h"
>>> +#include "llvm/Analysis/Passes.h"
>>> #include "llvm/Analysis/ScopedNoAliasAA.h"
>>> #include "llvm/Analysis/TargetLibraryInfo.h"
>>> #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
>>> +#include "llvm/IR/DataLayout.h"
>>> +#include "llvm/IR/FunctionInfo.h"
>>> +#include "llvm/IR/LegacyPassManager.h"
>>> +#include "llvm/IR/Verifier.h"
>>> +#include "llvm/Support/CommandLine.h"
>>> +#include "llvm/Support/ManagedStatic.h"
>>> #include "llvm/Target/TargetMachine.h"
>>> #include "llvm/Transforms/IPO.h"
>>> #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
>>> +#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
>>> #include "llvm/Transforms/Scalar.h"
>>> #include "llvm/Transforms/Vectorize.h"
>>>
>>> @@ -220,6 +220,9 @@ void PassManagerBuilder::populateModuleP
>>> addInitialAliasAnalysisPasses(MPM);
>>>
>>> if (!DisableUnitAtATime) {
>>> + // Infer attributes about declarations if possible.
>>> + MPM.add(createInferFunctionAttrsLegacyPass());
>>> +
>>> addExtensionsToPM(EP_ModuleOptimizerEarly, MPM);
>>>
>>> MPM.add(createIPSCCPPass()); // IP SCCP
>>> @@ -490,6 +493,9 @@ void PassManagerBuilder::addLTOOptimizat
>>> // Allow forcing function attributes as a debugging and tuning aid.
>>> PM.add(createForceFunctionAttrsLegacyPass());
>>>
>>> + // Infer attributes about declarations if possible.
>>> + PM.add(createInferFunctionAttrsLegacyPass());
>>> +
>>> // Propagate constants at call sites into the functions they call.
>>> This
>>> // opens opportunities for globalopt (and inlining) by substituting
>>> function
>>> // pointers passed as arguments to direct uses of functions.
>>>
>>> Removed: llvm/trunk/test/Transforms/FunctionAttrs/2009-01-04-Annotate.ll
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2009-01-04-Annotate.ll?rev=256465&view=auto
>>>
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/FunctionAttrs/2009-01-04-Annotate.ll
>>> (original)
>>> +++ llvm/trunk/test/Transforms/FunctionAttrs/2009-01-04-Annotate.ll
>>> (removed)
>>> @@ -1,21 +0,0 @@
>>> -; RUN: opt < %s -functionattrs -S | FileCheck %s
>>> -
>>> -; CHECK: declare noalias i8* @fopen(i8* nocapture readonly, i8*
>>> nocapture readonly) #0
>>> -declare i8* @fopen(i8*, i8*)
>>> -
>>> -; CHECK: declare i8 @strlen(i8* nocapture) #1
>>> -declare i8 @strlen(i8*)
>>> -
>>> -; CHECK: declare noalias i32* @realloc(i32* nocapture, i32) #0
>>> -declare i32* @realloc(i32*, i32)
>>> -
>>> -; Test deliberately wrong declaration
>>> -declare i32 @strcpy(...)
>>> -
>>> -; CHECK-NOT: strcpy{{.*}}noalias
>>> -; CHECK-NOT: strcpy{{.*}}nocapture
>>> -; CHECK-NOT: strcpy{{.*}}nounwind
>>> -; CHECK-NOT: strcpy{{.*}}readonly
>>> -
>>> -; CHECK: attributes #0 = { nounwind }
>>> -; CHECK: attributes #1 = { nounwind readonly }
>>>
>>> Removed: llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll?rev=256465&view=auto
>>>
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll (original)
>>> +++ llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll (removed)
>>> @@ -1,23 +0,0 @@
>>> -; RUN: opt < %s -functionattrs -S | FileCheck %s
>>> -; RUN: opt < %s -mtriple=x86_64-apple-macosx10.8.0 -functionattrs -S |
>>> FileCheck -check-prefix=CHECK-POSIX %s
>>> -
>>> -declare i8* @fopen(i8*, i8*)
>>> -; CHECK: declare noalias i8* @fopen(i8* nocapture readonly, i8*
>>> nocapture readonly) [[G0:#[0-9]]]
>>> -
>>> -declare i8 @strlen(i8*)
>>> -; CHECK: declare i8 @strlen(i8* nocapture) [[G1:#[0-9]]]
>>> -
>>> -declare i32* @realloc(i32*, i32)
>>> -; CHECK: declare noalias i32* @realloc(i32* nocapture, i32) [[G0]]
>>> -
>>> -; Test deliberately wrong declaration
>>> -
>>> -declare i32 @strcpy(...)
>>> -; CHECK: declare i32 @strcpy(...)
>>> -
>>> -declare i32 @gettimeofday(i8*, i8*)
>>> -; CHECK-POSIX: declare i32 @gettimeofday(i8* nocapture, i8* nocapture)
>>> [[G0:#[0-9]+]]
>>> -
>>> -; CHECK: attributes [[G0]] = { nounwind }
>>> -; CHECK: attributes [[G1]] = { nounwind readonly }
>>> -; CHECK-POSIX: attributes [[G0]] = { nounwind }
>>>
>>> Copied: llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll (from
>>> r256465, llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll)
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll?p2=llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll&p1=llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll&r1=256465&r2=256466&rev=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/FunctionAttrs/annotate-1.ll (original)
>>> +++ llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll Sun Dec 27
>>> 02:41:34 2015
>>> @@ -1,5 +1,6 @@
>>> -; RUN: opt < %s -functionattrs -S | FileCheck %s
>>> -; RUN: opt < %s -mtriple=x86_64-apple-macosx10.8.0 -functionattrs -S |
>>> FileCheck -check-prefix=CHECK-POSIX %s
>>> +; RUN: opt < %s -inferattrs -S | FileCheck %s
>>> +; RUN: opt < %s -passes=inferattrs -S | FileCheck %s
>>> +; RUN: opt < %s -mtriple=x86_64-apple-macosx10.8.0 -inferattrs -S |
>>> FileCheck -check-prefix=CHECK-POSIX %s
>>>
>>> declare i8* @fopen(i8*, i8*)
>>> ; CHECK: declare noalias i8* @fopen(i8* nocapture readonly, i8*
>>> nocapture readonly) [[G0:#[0-9]]]
>>>
>>> Modified: llvm/trunk/test/Transforms/InstCombine/strto-1.ll
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/strto-1.ll?rev=256466&r1=256465&r2=256466&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/InstCombine/strto-1.ll (original)
>>> +++ llvm/trunk/test/Transforms/InstCombine/strto-1.ll Sun Dec 27
>>> 02:41:34 2015
>>> @@ -1,6 +1,6 @@
>>> ; Test that the strto* library call simplifiers works correctly.
>>> ;
>>> -; RUN: opt < %s -instcombine -functionattrs -S | FileCheck %s
>>> +; RUN: opt < %s -instcombine -inferattrs -S | FileCheck %s
>>>
>>> target datalayout =
>>> "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
>>>
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160112/d46483e6/attachment-0001.html>
More information about the llvm-commits
mailing list