summaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2011-02-26 22:03:50 +0000
committerdim <dim@FreeBSD.org>2011-02-26 22:03:50 +0000
commitc80ac9d286b8fcc6d1ee5d76048134cf80aa9edc (patch)
treeddf53b8bd9235bcb0b8aae16c5e22310dcdad665 /lib/Transforms
parentcbb70ce070d220642b038ea101d9c0f9fbf860d6 (diff)
downloadFreeBSD-src-c80ac9d286b8fcc6d1ee5d76048134cf80aa9edc.zip
FreeBSD-src-c80ac9d286b8fcc6d1ee5d76048134cf80aa9edc.tar.gz
Vendor import of llvm trunk r126547:
http://llvm.org/svn/llvm-project/llvm/trunk@126547
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp33
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp20
-rw-r--r--lib/Transforms/Scalar/LoopDeletion.cpp23
-rw-r--r--lib/Transforms/Scalar/LoopIdiomRecognize.cpp18
-rw-r--r--lib/Transforms/Scalar/SimplifyLibCalls.cpp1343
-rw-r--r--lib/Transforms/Utils/Local.cpp42
-rw-r--r--lib/Transforms/Utils/PromoteMemoryToRegister.cpp13
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp5
8 files changed, 768 insertions, 729 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b6b6b84..7986d1a 100644
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1897,6 +1897,39 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
return BinaryOperator::CreateNot(And);
}
+ // Canonicalize xor to the RHS.
+ if (match(Op0, m_Xor(m_Value(), m_Value())))
+ std::swap(Op0, Op1);
+
+ // A | ( A ^ B) -> A | B
+ // A | (~A ^ B) -> A | ~B
+ if (match(Op1, m_Xor(m_Value(A), m_Value(B)))) {
+ if (Op0 == A || Op0 == B)
+ return BinaryOperator::CreateOr(A, B);
+
+ if (Op1->hasOneUse() && match(A, m_Not(m_Specific(Op0)))) {
+ Value *Not = Builder->CreateNot(B, B->getName()+".not");
+ return BinaryOperator::CreateOr(Not, Op0);
+ }
+ if (Op1->hasOneUse() && match(B, m_Not(m_Specific(Op0)))) {
+ Value *Not = Builder->CreateNot(A, A->getName()+".not");
+ return BinaryOperator::CreateOr(Not, Op0);
+ }
+ }
+
+ // A | ~(A | B) -> A | ~B
+ // A | ~(A ^ B) -> A | ~B
+ if (match(Op1, m_Not(m_Value(A))))
+ if (BinaryOperator *B = dyn_cast<BinaryOperator>(A))
+ if ((Op0 == B->getOperand(0) || Op0 == B->getOperand(1)) &&
+ Op1->hasOneUse() && (B->getOpcode() == Instruction::Or ||
+ B->getOpcode() == Instruction::Xor)) {
+ Value *NotOp = Op0 == B->getOperand(0) ? B->getOperand(1) :
+ B->getOperand(0);
+ Value *Not = Builder->CreateNot(NotOp, NotOp->getName()+".not");
+ return BinaryOperator::CreateOr(Not, Op0);
+ }
+
if (ICmpInst *RHS = dyn_cast<ICmpInst>(I.getOperand(1)))
if (ICmpInst *LHS = dyn_cast<ICmpInst>(I.getOperand(0)))
if (Value *Res = FoldOrOfICmps(LHS, RHS))
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 8449f7b..0e46450 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -953,10 +953,19 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
if (Callee->isDeclaration() && !isConvertible) return false;
}
- if (FT->getNumParams() < NumActualArgs && !FT->isVarArg() &&
- Callee->isDeclaration())
- return false; // Do not delete arguments unless we have a function body.
-
+ if (Callee->isDeclaration()) {
+ // Do not delete arguments unless we have a function body.
+ if (FT->getNumParams() < NumActualArgs && !FT->isVarArg())
+ return false;
+
+ // If the callee is just a declaration, don't change the varargsness of the
+ // call. We don't want to introduce a varargs call where one doesn't
+ // already exist.
+ const PointerType *APTy = cast<PointerType>(CS.getCalledValue()->getType());
+ if (FT->isVarArg()!=cast<FunctionType>(APTy->getElementType())->isVarArg())
+ return false;
+ }
+
if (FT->getNumParams() < NumActualArgs && FT->isVarArg() &&
!CallerPAL.isEmpty())
// In this case we have more arguments than the new function type, but we
@@ -970,8 +979,9 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
return false;
}
+
// Okay, we decided that this is a safe thing to do: go ahead and start
- // inserting cast instructions as necessary...
+ // inserting cast instructions as necessary.
std::vector<Value*> Args;
Args.reserve(NumActualArgs);
SmallVector<AttributeWithIndex, 8> attrVec;
diff --git a/lib/Transforms/Scalar/LoopDeletion.cpp b/lib/Transforms/Scalar/LoopDeletion.cpp
index 6d1d344..753a558 100644
--- a/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -78,7 +78,6 @@ bool LoopDeletion::IsLoopDead(Loop* L,
SmallVector<BasicBlock*, 4>& exitingBlocks,
SmallVector<BasicBlock*, 4>& exitBlocks,
bool &Changed, BasicBlock *Preheader) {
- BasicBlock* exitingBlock = exitingBlocks[0];
BasicBlock* exitBlock = exitBlocks[0];
// Make sure that all PHI entries coming from the loop are loop invariant.
@@ -88,11 +87,21 @@ bool LoopDeletion::IsLoopDead(Loop* L,
// of the loop.
BasicBlock::iterator BI = exitBlock->begin();
while (PHINode* P = dyn_cast<PHINode>(BI)) {
- Value* incoming = P->getIncomingValueForBlock(exitingBlock);
+ Value* incoming = P->getIncomingValueForBlock(exitingBlocks[0]);
+
+ // Make sure all exiting blocks produce the same incoming value for the exit
+ // block. If there are different incoming values for different exiting
+ // blocks, then it is impossible to statically determine which value should
+ // be used.
+ for (unsigned i = 1; i < exitingBlocks.size(); ++i) {
+ if (incoming != P->getIncomingValueForBlock(exitingBlocks[i]))
+ return false;
+ }
+
if (Instruction* I = dyn_cast<Instruction>(incoming))
if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator()))
return false;
-
+
++BI;
}
@@ -147,10 +156,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) {
if (exitBlocks.size() != 1)
return false;
- // Loops with multiple exits are too complicated to handle correctly.
- if (exitingBlocks.size() != 1)
- return false;
-
// Finally, we have to check that the loop really is dead.
bool Changed = false;
if (!IsLoopDead(L, exitingBlocks, exitBlocks, Changed, preheader))
@@ -166,7 +171,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) {
// Now that we know the removal is safe, remove the loop by changing the
// branch from the preheader to go to the single exit block.
BasicBlock* exitBlock = exitBlocks[0];
- BasicBlock* exitingBlock = exitingBlocks[0];
// Because we're deleting a large chunk of code at once, the sequence in which
// we remove things is very important to avoid invalidation issues. Don't
@@ -183,9 +187,12 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) {
// Rewrite phis in the exit block to get their inputs from
// the preheader instead of the exiting block.
+ BasicBlock* exitingBlock = exitingBlocks[0];
BasicBlock::iterator BI = exitBlock->begin();
while (PHINode* P = dyn_cast<PHINode>(BI)) {
P->replaceUsesOfWith(exitingBlock, preheader);
+ for (unsigned i = 1; i < exitingBlocks.size(); ++i)
+ P->removeIncomingValue(exitingBlocks[i]);
++BI;
}
diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index d7fa149..f8ce214 100644
--- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -31,6 +31,11 @@
// void foo(_Complex float *P)
// for (i) { __real__(*P) = 0; __imag__(*P) = 0; }
//
+// We should enhance this to handle negative strides through memory.
+// Alternatively (and perhaps better) we could rely on an earlier pass to force
+// forward iteration through memory, which is generally better for cache
+// behavior. Negative strides *do* happen for memset/memcpy loops.
+//
// This could recognize common matrix multiplies and dot product idioms and
// replace them with calls to BLAS (if linked in??).
//
@@ -272,10 +277,17 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) {
unsigned StoreSize = (unsigned)SizeInBits >> 3;
const SCEVConstant *Stride = dyn_cast<SCEVConstant>(StoreEv->getOperand(1));
- // TODO: Could also handle negative stride here someday, that will require the
- // validity check in mayLoopAccessLocation to be updated though.
- if (Stride == 0 || StoreSize != Stride->getValue()->getValue())
+ if (Stride == 0 || StoreSize != Stride->getValue()->getValue()) {
+ // TODO: Could also handle negative stride here someday, that will require
+ // the validity check in mayLoopAccessLocation to be updated though.
+ // Enable this to print exact negative strides.
+ if (0 && Stride && StoreSize == -Stride->getValue()->getValue()) {
+ dbgs() << "NEGATIVE STRIDE: " << *SI << "\n";
+ dbgs() << "BB: " << *SI->getParent();
+ }
+
return false;
+ }
// See if we can optimize just this store in isolation.
if (processLoopStridedStore(StorePtr, StoreSize, SI->getAlignment(),
diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index ec45b71..9f136d4 100644
--- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -25,13 +25,14 @@
#include "llvm/Support/IRBuilder.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Config/config.h"
+#include "llvm/Config/config.h" // FIXME: Shouldn't depend on host!
using namespace llvm;
STATISTIC(NumSimplified, "Number of library calls simplified");
@@ -1369,6 +1370,8 @@ namespace {
/// This pass optimizes well known library functions from libc and libm.
///
class SimplifyLibCalls : public FunctionPass {
+ TargetLibraryInfo *TLI;
+
StringMap<LibCallOptimization*> Optimizations;
// String and Memory LibCall Optimizations
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr;
@@ -1385,7 +1388,7 @@ namespace {
SPrintFOpt SPrintF; PrintFOpt PrintF;
FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF;
PutsOpt Puts;
-
+
bool Modified; // This is only used by doInitialization.
public:
static char ID; // Pass identification
@@ -1402,14 +1405,20 @@ namespace {
void setDoesNotAlias(Function &F, unsigned n);
bool doInitialization(Module &M);
+ void inferPrototypeAttributes(Function &F);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetLibraryInfo>();
}
};
- char SimplifyLibCalls::ID = 0;
} // end anonymous namespace.
-INITIALIZE_PASS(SimplifyLibCalls, "simplify-libcalls",
- "Simplify well-known library calls", false, false)
+char SimplifyLibCalls::ID = 0;
+
+INITIALIZE_PASS_BEGIN(SimplifyLibCalls, "simplify-libcalls",
+ "Simplify well-known library calls", false, false)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
+INITIALIZE_PASS_END(SimplifyLibCalls, "simplify-libcalls",
+ "Simplify well-known library calls", false, false)
// Public interface to the Simplify LibCalls pass.
FunctionPass *llvm::createSimplifyLibCallsPass() {
@@ -1441,9 +1450,9 @@ void SimplifyLibCalls::InitOptimizations() {
Optimizations["strcspn"] = &StrCSpn;
Optimizations["strstr"] = &StrStr;
Optimizations["memcmp"] = &MemCmp;
- Optimizations["memcpy"] = &MemCpy;
+ if (TLI->has(LibFunc::memcpy)) Optimizations["memcpy"] = &MemCpy;
Optimizations["memmove"] = &MemMove;
- Optimizations["memset"] = &MemSet;
+ if (TLI->has(LibFunc::memset)) Optimizations["memset"] = &MemSet;
// _chk variants of String and Memory LibCall Optimizations.
Optimizations["__strcpy_chk"] = &StrCpyChk;
@@ -1506,6 +1515,8 @@ void SimplifyLibCalls::InitOptimizations() {
/// runOnFunction - Top level algorithm.
///
bool SimplifyLibCalls::runOnFunction(Function &F) {
+ TLI = &getAnalysis<TargetLibraryInfo>();
+
if (Optimizations.empty())
InitOptimizations();
@@ -1597,688 +1608,654 @@ void SimplifyLibCalls::setDoesNotAlias(Function &F, unsigned n) {
}
}
+
+void SimplifyLibCalls::inferPrototypeAttributes(Function &F) {
+ const FunctionType *FTy = F.getFunctionType();
+
+ StringRef Name = F.getName();
+ switch (Name[0]) {
+ case 's':
+ if (Name == "strlen") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "strchr" ||
+ Name == "strrchr") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isIntegerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ } else if (Name == "strcpy" ||
+ Name == "stpcpy" ||
+ Name == "strcat" ||
+ Name == "strtol" ||
+ Name == "strtod" ||
+ Name == "strtof" ||
+ Name == "strtoul" ||
+ Name == "strtoll" ||
+ Name == "strtold" ||
+ Name == "strncat" ||
+ Name == "strncpy" ||
+ Name == "strtoull") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strxfrm") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strcmp" ||
+ Name == "strspn" ||
+ Name == "strncmp" ||
+ Name == "strcspn" ||
+ Name == "strcoll" ||
+ Name == "strcasecmp" ||
+ Name == "strncasecmp") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strstr" ||
+ Name == "strpbrk") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "strtok" ||
+ Name == "strtok_r") {
+ if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "scanf" ||
+ Name == "setbuf" ||
+ Name == "setvbuf") {
+ if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "strdup" ||
+ Name == "strndup") {
+ if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "stat" ||
+ Name == "sscanf" ||
+ Name == "sprintf" ||
+ Name == "statvfs") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "snprintf") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 3);
+ } else if (Name == "setitimer") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ setDoesNotCapture(F, 3);
+ } else if (Name == "system") {
+ if (FTy->getNumParams() != 1 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ // May throw; "system" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'm':
+ if (Name == "malloc") {
+ if (FTy->getNumParams() != 1 ||
+ !FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "memcmp") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "memchr" ||
+ Name == "memrchr") {
+ if (FTy->getNumParams() != 3)
+ return;
+ setOnlyReadsMemory(F);
+ setDoesNotThrow(F);
+ } else if (Name == "modf" ||
+ Name == "modff" ||
+ Name == "modfl" ||
+ Name == "memcpy" ||
+ Name == "memccpy" ||
+ Name == "memmove") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "memalign") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotAlias(F, 0);
+ } else if (Name == "mkdir" ||
+ Name == "mktime") {
+ if (FTy->getNumParams() == 0 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'r':
+ if (Name == "realloc") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "read") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ // May throw; "read" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 2);
+ } else if (Name == "rmdir" ||
+ Name == "rewind" ||
+ Name == "remove" ||
+ Name == "realpath") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "rename" ||
+ Name == "readlink") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'w':
+ if (Name == "write") {
+ if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ // May throw; "write" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'b':
+ if (Name == "bcopy") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "bcmp") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setOnlyReadsMemory(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "bzero") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'c':
+ if (Name == "calloc") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "chmod" ||
+ Name == "chown" ||
+ Name == "ctermid" ||
+ Name == "clearerr" ||
+ Name == "closedir") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'a':
+ if (Name == "atoi" ||
+ Name == "atol" ||
+ Name == "atof" ||
+ Name == "atoll") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setOnlyReadsMemory(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "access") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'f':
+ if (Name == "fopen") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "fdopen") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "feof" ||
+ Name == "free" ||
+ Name == "fseek" ||
+ Name == "ftell" ||
+ Name == "fgetc" ||
+ Name == "fseeko" ||
+ Name == "ftello" ||
+ Name == "fileno" ||
+ Name == "fflush" ||
+ Name == "fclose" ||
+ Name == "fsetpos" ||
+ Name == "flockfile" ||
+ Name == "funlockfile" ||
+ Name == "ftrylockfile") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "ferror") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setOnlyReadsMemory(F);
+ } else if (Name == "fputc" ||
+ Name == "fstat" ||
+ Name == "frexp" ||
+ Name == "frexpf" ||
+ Name == "frexpl" ||
+ Name == "fstatvfs") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "fgets") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 3);
+ } else if (Name == "fread" ||
+ Name == "fwrite") {
+ if (FTy->getNumParams() != 4 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(3)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 4);
+ } else if (Name == "fputs" ||
+ Name == "fscanf" ||
+ Name == "fprintf" ||
+ Name == "fgetpos") {
+ if (FTy->getNumParams() < 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'g':
+ if (Name == "getc" ||
+ Name == "getlogin_r" ||
+ Name == "getc_unlocked") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "getenv") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setOnlyReadsMemory(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "gets" ||
+ Name == "getchar") {
+ setDoesNotThrow(F);
+ } else if (Name == "getitimer") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "getpwnam") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'u':
+ if (Name == "ungetc") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "uname" ||
+ Name == "unlink" ||
+ Name == "unsetenv") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "utime" ||
+ Name == "utimes") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 'p':
+ if (Name == "putc") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "puts" ||
+ Name == "printf" ||
+ Name == "perror") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "pread" ||
+ Name == "pwrite") {
+ if (FTy->getNumParams() != 4 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ // May throw; these are valid pthread cancellation points.
+ setDoesNotCapture(F, 2);
+ } else if (Name == "putchar") {
+ setDoesNotThrow(F);
+ } else if (Name == "popen") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "pclose") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'v':
+ if (Name == "vscanf") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "vsscanf" ||
+ Name == "vfscanf") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "valloc") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "vprintf") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "vfprintf" ||
+ Name == "vsprintf") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "vsnprintf") {
+ if (FTy->getNumParams() != 4 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(2)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 3);
+ }
+ break;
+ case 'o':
+ if (Name == "open") {
+ if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ // May throw; "open" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 1);
+ } else if (Name == "opendir") {
+ if (FTy->getNumParams() != 1 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 't':
+ if (Name == "tmpfile") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "times") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'h':
+ if (Name == "htonl" ||
+ Name == "htons") {
+ setDoesNotThrow(F);
+ setDoesNotAccessMemory(F);
+ }
+ break;
+ case 'n':
+ if (Name == "ntohl" ||
+ Name == "ntohs") {
+ setDoesNotThrow(F);
+ setDoesNotAccessMemory(F);
+ }
+ break;
+ case 'l':
+ if (Name == "lstat") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "lchown") {
+ if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ case 'q':
+ if (Name == "qsort") {
+ if (FTy->getNumParams() != 4 || !FTy->getParamType(3)->isPointerTy())
+ return;
+ // May throw; places call through function pointer.
+ setDoesNotCapture(F, 4);
+ }
+ break;
+ case '_':
+ if (Name == "__strdup" ||
+ Name == "__strndup") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "__strtok_r") {
+ if (FTy->getNumParams() != 3 ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "_IO_getc") {
+ if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "_IO_putc") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ }
+ break;
+ case 1:
+ if (Name == "\1__isoc99_scanf") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "\1stat64" ||
+ Name == "\1lstat64" ||
+ Name == "\1statvfs64" ||
+ Name == "\1__isoc99_sscanf") {
+ if (FTy->getNumParams() < 1 ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "\1fopen64") {
+ if (FTy->getNumParams() != 2 ||
+ !FTy->getReturnType()->isPointerTy() ||
+ !FTy->getParamType(0)->isPointerTy() ||
+ !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ setDoesNotCapture(F, 1);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "\1fseeko64" ||
+ Name == "\1ftello64") {
+ if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 1);
+ } else if (Name == "\1tmpfile64") {
+ if (!FTy->getReturnType()->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotAlias(F, 0);
+ } else if (Name == "\1fstat64" ||
+ Name == "\1fstatvfs64") {
+ if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
+ return;
+ setDoesNotThrow(F);
+ setDoesNotCapture(F, 2);
+ } else if (Name == "\1open64") {
+ if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
+ return;
+ // May throw; "open" is a valid pthread cancellation point.
+ setDoesNotCapture(F, 1);
+ }
+ break;
+ }
+}
+
/// doInitialization - Add attributes to well-known functions.
///
bool SimplifyLibCalls::doInitialization(Module &M) {
Modified = false;
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
Function &F = *I;
- if (!F.isDeclaration())
- continue;
-
- if (!F.hasName())
- continue;
-
- const FunctionType *FTy = F.getFunctionType();
-
- StringRef Name = F.getName();
- switch (Name[0]) {
- case 's':
- if (Name == "strlen") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "strchr" ||
- Name == "strrchr") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isIntegerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- } else if (Name == "strcpy" ||
- Name == "stpcpy" ||
- Name == "strcat" ||
- Name == "strtol" ||
- Name == "strtod" ||
- Name == "strtof" ||
- Name == "strtoul" ||
- Name == "strtoll" ||
- Name == "strtold" ||
- Name == "strncat" ||
- Name == "strncpy" ||
- Name == "strtoull") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "strxfrm") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "strcmp" ||
- Name == "strspn" ||
- Name == "strncmp" ||
- Name == "strcspn" ||
- Name == "strcoll" ||
- Name == "strcasecmp" ||
- Name == "strncasecmp") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "strstr" ||
- Name == "strpbrk") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "strtok" ||
- Name == "strtok_r") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "scanf" ||
- Name == "setbuf" ||
- Name == "setvbuf") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "strdup" ||
- Name == "strndup") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- } else if (Name == "stat" ||
- Name == "sscanf" ||
- Name == "sprintf" ||
- Name == "statvfs") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "snprintf") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 3);
- } else if (Name == "setitimer") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- setDoesNotCapture(F, 3);
- } else if (Name == "system") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- // May throw; "system" is a valid pthread cancellation point.
- setDoesNotCapture(F, 1);
- }
- break;
- case 'm':
- if (Name == "malloc") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "memcmp") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "memchr" ||
- Name == "memrchr") {
- if (FTy->getNumParams() != 3)
- continue;
- setOnlyReadsMemory(F);
- setDoesNotThrow(F);
- } else if (Name == "modf" ||
- Name == "modff" ||
- Name == "modfl" ||
- Name == "memcpy" ||
- Name == "memccpy" ||
- Name == "memmove") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "memalign") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotAlias(F, 0);
- } else if (Name == "mkdir" ||
- Name == "mktime") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'r':
- if (Name == "realloc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- } else if (Name == "read") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- // May throw; "read" is a valid pthread cancellation point.
- setDoesNotCapture(F, 2);
- } else if (Name == "rmdir" ||
- Name == "rewind" ||
- Name == "remove" ||
- Name == "realpath") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "rename" ||
- Name == "readlink") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- }
- break;
- case 'w':
- if (Name == "write") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- // May throw; "write" is a valid pthread cancellation point.
- setDoesNotCapture(F, 2);
- }
- break;
- case 'b':
- if (Name == "bcopy") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "bcmp") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setOnlyReadsMemory(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "bzero") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'c':
- if (Name == "calloc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "chmod" ||
- Name == "chown" ||
- Name == "ctermid" ||
- Name == "clearerr" ||
- Name == "closedir") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'a':
- if (Name == "atoi" ||
- Name == "atol" ||
- Name == "atof" ||
- Name == "atoll") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setOnlyReadsMemory(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "access") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'f':
- if (Name == "fopen") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "fdopen") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 2);
- } else if (Name == "feof" ||
- Name == "free" ||
- Name == "fseek" ||
- Name == "ftell" ||
- Name == "fgetc" ||
- Name == "fseeko" ||
- Name == "ftello" ||
- Name == "fileno" ||
- Name == "fflush" ||
- Name == "fclose" ||
- Name == "fsetpos" ||
- Name == "flockfile" ||
- Name == "funlockfile" ||
- Name == "ftrylockfile") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "ferror") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setOnlyReadsMemory(F);
- } else if (Name == "fputc" ||
- Name == "fstat" ||
- Name == "frexp" ||
- Name == "frexpf" ||
- Name == "frexpl" ||
- Name == "fstatvfs") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "fgets") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 3);
- } else if (Name == "fread" ||
- Name == "fwrite") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(3)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 4);
- } else if (Name == "fputs" ||
- Name == "fscanf" ||
- Name == "fprintf" ||
- Name == "fgetpos") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- }
- break;
- case 'g':
- if (Name == "getc" ||
- Name == "getlogin_r" ||
- Name == "getc_unlocked") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "getenv") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setOnlyReadsMemory(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "gets" ||
- Name == "getchar") {
- setDoesNotThrow(F);
- } else if (Name == "getitimer") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "getpwnam") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'u':
- if (Name == "ungetc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "uname" ||
- Name == "unlink" ||
- Name == "unsetenv") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "utime" ||
- Name == "utimes") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- }
- break;
- case 'p':
- if (Name == "putc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "puts" ||
- Name == "printf" ||
- Name == "perror") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "pread" ||
- Name == "pwrite") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- // May throw; these are valid pthread cancellation points.
- setDoesNotCapture(F, 2);
- } else if (Name == "putchar") {
- setDoesNotThrow(F);
- } else if (Name == "popen") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "pclose") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'v':
- if (Name == "vscanf") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "vsscanf" ||
- Name == "vfscanf") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "valloc") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "vprintf") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "vfprintf" ||
- Name == "vsprintf") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "vsnprintf") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(2)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 3);
- }
- break;
- case 'o':
- if (Name == "open") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- // May throw; "open" is a valid pthread cancellation point.
- setDoesNotCapture(F, 1);
- } else if (Name == "opendir") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- }
- break;
- case 't':
- if (Name == "tmpfile") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "times") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'h':
- if (Name == "htonl" ||
- Name == "htons") {
- setDoesNotThrow(F);
- setDoesNotAccessMemory(F);
- }
- break;
- case 'n':
- if (Name == "ntohl" ||
- Name == "ntohs") {
- setDoesNotThrow(F);
- setDoesNotAccessMemory(F);
- }
- break;
- case 'l':
- if (Name == "lstat") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "lchown") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- }
- break;
- case 'q':
- if (Name == "qsort") {
- if (FTy->getNumParams() != 4 ||
- !FTy->getParamType(3)->isPointerTy())
- continue;
- // May throw; places call through function pointer.
- setDoesNotCapture(F, 4);
- }
- break;
- case '_':
- if (Name == "__strdup" ||
- Name == "__strndup") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- } else if (Name == "__strtok_r") {
- if (FTy->getNumParams() != 3 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "_IO_getc") {
- if (FTy->getNumParams() != 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "_IO_putc") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- }
- break;
- case 1:
- if (Name == "\1__isoc99_scanf") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "\1stat64" ||
- Name == "\1lstat64" ||
- Name == "\1statvfs64" ||
- Name == "\1__isoc99_sscanf") {
- if (FTy->getNumParams() < 1 ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "\1fopen64") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getReturnType()->isPointerTy() ||
- !FTy->getParamType(0)->isPointerTy() ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- setDoesNotCapture(F, 1);
- setDoesNotCapture(F, 2);
- } else if (Name == "\1fseeko64" ||
- Name == "\1ftello64") {
- if (FTy->getNumParams() == 0 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 1);
- } else if (Name == "\1tmpfile64") {
- if (!FTy->getReturnType()->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotAlias(F, 0);
- } else if (Name == "\1fstat64" ||
- Name == "\1fstatvfs64") {
- if (FTy->getNumParams() != 2 ||
- !FTy->getParamType(1)->isPointerTy())
- continue;
- setDoesNotThrow(F);
- setDoesNotCapture(F, 2);
- } else if (Name == "\1open64") {
- if (FTy->getNumParams() < 2 ||
- !FTy->getParamType(0)->isPointerTy())
- continue;
- // May throw; "open" is a valid pthread cancellation point.
- setDoesNotCapture(F, 1);
- }
- break;
- }
+ if (F.isDeclaration() && F.hasName())
+ inferPrototypeAttributes(F);
}
return Modified;
}
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp
index 063c76e..3f789fa 100644
--- a/lib/Transforms/Utils/Local.cpp
+++ b/lib/Transforms/Utils/Local.cpp
@@ -262,12 +262,13 @@ bool llvm::RecursivelyDeleteTriviallyDeadInstructions(Value *V) {
/// areAllUsesEqual - Check whether the uses of a value are all the same.
/// This is similar to Instruction::hasOneUse() except this will also return
-/// true when there are multiple uses that all refer to the same value.
+/// true when there are no uses or multiple uses that all refer to the same
+/// value.
static bool areAllUsesEqual(Instruction *I) {
Value::use_iterator UI = I->use_begin();
Value::use_iterator UE = I->use_end();
if (UI == UE)
- return false;
+ return true;
User *TheUse = *UI;
for (++UI; UI != UE; ++UI) {
@@ -281,31 +282,24 @@ static bool areAllUsesEqual(Instruction *I) {
/// dead PHI node, due to being a def-use chain of single-use nodes that
/// either forms a cycle or is terminated by a trivially dead instruction,
/// delete it. If that makes any of its operands trivially dead, delete them
-/// too, recursively. Return true if the PHI node is actually deleted.
+/// too, recursively. Return true if a change was made.
bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN) {
- // We can remove a PHI if it is on a cycle in the def-use graph
- // where each node in the cycle has degree one, i.e. only one use,
- // and is an instruction with no side effects.
- if (!areAllUsesEqual(PN))
- return false;
+ SmallPtrSet<Instruction*, 4> Visited;
+ for (Instruction *I = PN; areAllUsesEqual(I) && !I->mayHaveSideEffects();
+ I = cast<Instruction>(*I->use_begin())) {
+ if (I->use_empty())
+ return RecursivelyDeleteTriviallyDeadInstructions(I);
- bool Changed = false;
- SmallPtrSet<PHINode *, 4> PHIs;
- PHIs.insert(PN);
- for (Instruction *J = cast<Instruction>(*PN->use_begin());
- areAllUsesEqual(J) && !J->mayHaveSideEffects();
- J = cast<Instruction>(*J->use_begin()))
- // If we find a PHI more than once, we're on a cycle that
+ // If we find an instruction more than once, we're on a cycle that
// won't prove fruitful.
- if (PHINode *JP = dyn_cast<PHINode>(J))
- if (!PHIs.insert(JP)) {
- // Break the cycle and delete the PHI and its operands.
- JP->replaceAllUsesWith(UndefValue::get(JP->getType()));
- (void)RecursivelyDeleteTriviallyDeadInstructions(JP);
- Changed = true;
- break;
- }
- return Changed;
+ if (!Visited.insert(I)) {
+ // Break the cycle and delete the instruction and its operands.
+ I->replaceAllUsesWith(UndefValue::get(I->getType()));
+ (void)RecursivelyDeleteTriviallyDeadInstructions(I);
+ return true;
+ }
+ }
+ return false;
}
/// SimplifyInstructionsInBlock - Scan the specified basic block and try to
diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index e6a4373..7788857 100644
--- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -35,6 +35,7 @@
#include "llvm/Metadata.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Analysis/DIBuilder.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/ADT/DenseMap.h"
@@ -190,7 +191,7 @@ namespace {
///
std::vector<AllocaInst*> Allocas;
DominatorTree &DT;
- DIFactory *DIF;
+ DIBuilder *DIB;
/// AST - An AliasSetTracker object to update. If null, don't update it.
///
@@ -235,9 +236,9 @@ namespace {
public:
PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt,
AliasSetTracker *ast)
- : Allocas(A), DT(dt), DIF(0), AST(ast) {}
+ : Allocas(A), DT(dt), DIB(0), AST(ast) {}
~PromoteMem2Reg() {
- delete DIF;
+ delete DIB;
}
void run();
@@ -951,9 +952,9 @@ void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
if (!DIVar.Verify())
return;
- if (!DIF)
- DIF = new DIFactory(*SI->getParent()->getParent()->getParent());
- Instruction *DbgVal = DIF->InsertDbgValueIntrinsic(SI->getOperand(0), 0,
+ if (!DIB)
+ DIB = new DIBuilder(*SI->getParent()->getParent()->getParent());
+ Instruction *DbgVal = DIB->insertDbgValueIntrinsic(SI->getOperand(0), 0,
DIVar, SI);
// Propagate any debug metadata from the store onto the dbg.value.
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index fb660db..c670885 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -247,6 +247,11 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
if (PBB->getFirstNonPHIOrDbg() != I)
return false;
break;
+ case Instruction::GetElementPtr:
+ // GEPs are cheap if all indices are constant.
+ if (!cast<GetElementPtrInst>(I)->hasAllConstantIndices())
+ return false;
+ break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::And:
OpenPOWER on IntegriCloud