[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 14:46:37 PST 2016
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?
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160112/f0ead213/attachment-0001.html>
More information about the llvm-commits
mailing list