[llvm] r256466 - [attrs] Extract the pure inference of function attributes into

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 12 15:04:48 PST 2016


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.


>
>
>> 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/6f6b27f7/attachment-0001.html>


More information about the llvm-commits mailing list