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