Newer
Older
return 0;
// Check for a fixed format string.
if (!GetConstantStringInfo(CI->getArgOperand(0), FormatStr))
// Empty format string -> noop.
if (FormatStr.empty()) // Tolerate printf's declared void.
return CI->use_empty() ? (Value*)CI :
Owen Anderson
committed
ConstantInt::get(CI->getType(), 0);
// printf("x") -> putchar('x'), even for '%'. Return the result of putchar
// in case there is an error writing to stdout.
if (FormatStr.size() == 1) {
Value *Res = EmitPutChar(ConstantInt::get(Type::getInt32Ty(*Context),
FormatStr[0]), B, TD);
if (CI->use_empty()) return CI;
return B.CreateIntCast(Res, CI->getType(), true);
// printf("foo\n") --> puts("foo")
if (FormatStr[FormatStr.size()-1] == '\n' &&
FormatStr.find('%') == std::string::npos) { // no format characters.
// Create a string literal with no \n on it. We expect the constant merge
// pass to be run after this pass, to merge duplicate strings.
FormatStr.erase(FormatStr.end()-1);
Constant *C = ConstantArray::get(*Context, FormatStr, true);
Owen Anderson
committed
C = new GlobalVariable(*Callee->getParent(), C->getType(), true,
GlobalVariable::InternalLinkage, C, "str");
EmitPutS(C, B, TD);
return CI->use_empty() ? (Value*)CI :
Owen Anderson
committed
ConstantInt::get(CI->getType(), FormatStr.size()+1);
// Optimize specific format strings.
if (FormatStr == "%c" && CI->getNumArgOperands() > 1 &&
CI->getArgOperand(1)->getType()->isIntegerTy()) {
Value *Res = EmitPutChar(CI->getArgOperand(1), B, TD);
if (CI->use_empty()) return CI;
return B.CreateIntCast(Res, CI->getType(), true);
// printf("%s\n", str) --> puts(str)
if (FormatStr == "%s\n" && CI->getNumArgOperands() > 1 &&
CI->use_empty()) {
return CI;
}
return 0;
}
};
//===---------------------------------------===//
// 'sprintf' Optimizations
struct SPrintFOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require two fixed pointer arguments and an integer result.
const FunctionType *FT = Callee->getFunctionType();
Duncan Sands
committed
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!FT->getReturnType()->isIntegerTy())
return 0;
// Check for a fixed format string.
if (!GetConstantStringInfo(CI->getArgOperand(1), FormatStr))
// If we just have a format string (nothing else crazy) transform it.
// Make sure there's no % in the constant array. We could try to handle
// %% -> % in the future if we cared.
for (unsigned i = 0, e = FormatStr.size(); i != e; ++i)
if (FormatStr[i] == '%')
return 0; // we found a format specifier, bail out.
// These optimizations require TargetData.
if (!TD) return 0;
// sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1)
EmitMemCpy(CI->getArgOperand(0), CI->getArgOperand(1), // Copy the
ConstantInt::get(TD->getIntPtrType(*Context), // nul byte.
FormatStr.size() + 1), 1, false, B, TD);
Owen Anderson
committed
return ConstantInt::get(CI->getType(), FormatStr.size());
// The remaining optimizations require the format string to be "%s" or "%c"
// and have an extra operand.
if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
CI->getNumArgOperands() < 3)
return 0;
// Decode the second character of the format string.
if (FormatStr[1] == 'c') {
// sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0
if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return 0;
Value *V = B.CreateTrunc(CI->getArgOperand(2),
Type::getInt8Ty(*Context), "char");
Ptr = B.CreateGEP(Ptr, ConstantInt::get(Type::getInt32Ty(*Context), 1),
"nul");
B.CreateStore(Constant::getNullValue(Type::getInt8Ty(*Context)), Ptr);
Owen Anderson
committed
return ConstantInt::get(CI->getType(), 1);
if (FormatStr[1] == 's') {
// These optimizations require TargetData.
if (!TD) return 0;
// sprintf(dest, "%s", str) -> llvm.memcpy(dest, str, strlen(str)+1, 1)
if (!CI->getArgOperand(2)->getType()->isPointerTy()) return 0;
Owen Anderson
committed
ConstantInt::get(Len->getType(), 1),
"leninc");
EmitMemCpy(CI->getArgOperand(0), CI->getArgOperand(2),
IncLen, 1, false, B, TD);
// The sprintf result is the unincremented number of bytes in the string.
return B.CreateIntCast(Len, CI->getType(), false);
}
return 0;
}
};
//===---------------------------------------===//
// 'fwrite' Optimizations
struct FWriteOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require a pointer, an integer, an integer, a pointer, returning integer.
const FunctionType *FT = Callee->getFunctionType();
Duncan Sands
committed
if (FT->getNumParams() != 4 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isIntegerTy() ||
!FT->getParamType(2)->isIntegerTy() ||
!FT->getParamType(3)->isPointerTy() ||
!FT->getReturnType()->isIntegerTy())
return 0;
// Get the element size and count.
ConstantInt *SizeC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
ConstantInt *CountC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
if (!SizeC || !CountC) return 0;
uint64_t Bytes = SizeC->getZExtValue()*CountC->getZExtValue();
// If this is writing zero records, remove the call (it's a noop).
if (Bytes == 0)
Owen Anderson
committed
return ConstantInt::get(CI->getType(), 0);
// If this is writing one byte, turn it into fputc.
if (Bytes == 1) { // fwrite(S,1,1,F) -> fputc(S[0],F)
Value *Char = B.CreateLoad(CastToCStr(CI->getArgOperand(0), B), "char");
EmitFPutC(Char, CI->getArgOperand(3), B, TD);
Owen Anderson
committed
return ConstantInt::get(CI->getType(), 1);
}
return 0;
}
};
//===---------------------------------------===//
// 'fputs' Optimizations
struct FPutsOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// These optimizations require TargetData.
if (!TD) return 0;
// Require two pointers. Also, we can't optimize if return value is used.
const FunctionType *FT = Callee->getFunctionType();
Duncan Sands
committed
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!CI->use_empty())
return 0;
// fputs(s,F) --> fwrite(s,1,strlen(s),F)
ConstantInt::get(TD->getIntPtrType(*Context), Len-1),
return CI; // Known to have no uses (see above).
}
};
//===---------------------------------------===//
// 'fprintf' Optimizations
struct FPrintFOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require two fixed paramters as pointers and integer result.
const FunctionType *FT = Callee->getFunctionType();
Duncan Sands
committed
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!FT->getReturnType()->isIntegerTy())
return 0;
// All the optimizations depend on the format string.
if (!GetConstantStringInfo(CI->getArgOperand(1), FormatStr))
// fprintf(F, "foo") --> fwrite("foo", 3, 1, F)
for (unsigned i = 0, e = FormatStr.size(); i != e; ++i)
if (FormatStr[i] == '%') // Could handle %% -> % if we cared.
// These optimizations require TargetData.
if (!TD) return 0;
ConstantInt::get(TD->getIntPtrType(*Context),
FormatStr.size()),
Owen Anderson
committed
return ConstantInt::get(CI->getType(), FormatStr.size());
// The remaining optimizations require the format string to be "%s" or "%c"
// and have an extra operand.
if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
CI->getNumArgOperands() < 3)
return 0;
// Decode the second character of the format string.
if (FormatStr[1] == 'c') {
// fprintf(F, "%c", chr) --> fputc(chr, F)
if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return 0;
EmitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B, TD);
Owen Anderson
committed
return ConstantInt::get(CI->getType(), 1);
if (FormatStr[1] == 's') {
// fprintf(F, "%s", str) --> fputs(str, F)
if (!CI->getArgOperand(2)->getType()->isPointerTy() || !CI->use_empty())
return 0;
EmitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B, TD);
return CI;
}
return 0;
}
};
Bill Wendling
committed
} // end anonymous namespace.
//===----------------------------------------------------------------------===//
// SimplifyLibCalls Pass Implementation
//===----------------------------------------------------------------------===//
namespace {
/// This pass optimizes well known library functions from libc and libm.
///
class SimplifyLibCalls : public FunctionPass {
StringMap<LibCallOptimization*> Optimizations;
// String and Memory LibCall Optimizations
StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr;
StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrCpyOpt StrCpyChk;
StrNCpyOpt StrNCpy; StrLenOpt StrLen;
StrToOpt StrTo; StrStrOpt StrStr;
MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet;
// Math Library Optimizations
PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP;
// Integer Optimizations
FFSOpt FFS; AbsOpt Abs; IsDigitOpt IsDigit; IsAsciiOpt IsAscii;
ToAsciiOpt ToAscii;
// Formatting and IO Optimizations
SPrintFOpt SPrintF; PrintFOpt PrintF;
FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF;
bool Modified; // This is only used by doInitialization.
public:
static char ID; // Pass identification
SimplifyLibCalls() : FunctionPass(ID), StrCpy(false), StrCpyChk(true) {}
void InitOptimizations();
bool runOnFunction(Function &F);
void setDoesNotAccessMemory(Function &F);
void setOnlyReadsMemory(Function &F);
void setDoesNotThrow(Function &F);
void setDoesNotCapture(Function &F, unsigned n);
void setDoesNotAlias(Function &F, unsigned n);
bool doInitialization(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
}
};
char SimplifyLibCalls::ID = 0;
} // end anonymous namespace.
INITIALIZE_PASS(SimplifyLibCalls, "simplify-libcalls",
"Simplify well-known library calls", false, false);
// Public interface to the Simplify LibCalls pass.
FunctionPass *llvm::createSimplifyLibCallsPass() {
}
/// Optimizations - Populate the Optimizations map with all the optimizations
/// we know.
void SimplifyLibCalls::InitOptimizations() {
// String and Memory LibCall Optimizations
Optimizations["strcat"] = &StrCat;
Optimizations["strncat"] = &StrNCat;
Optimizations["strchr"] = &StrChr;
Optimizations["strrchr"] = &StrRChr;
Optimizations["strcmp"] = &StrCmp;
Optimizations["strncmp"] = &StrNCmp;
Optimizations["strcpy"] = &StrCpy;
Optimizations["strncpy"] = &StrNCpy;
Optimizations["strlen"] = &StrLen;
Nick Lewycky
committed
Optimizations["strtol"] = &StrTo;
Optimizations["strtod"] = &StrTo;
Optimizations["strtof"] = &StrTo;
Optimizations["strtoul"] = &StrTo;
Optimizations["strtoll"] = &StrTo;
Optimizations["strtold"] = &StrTo;
Optimizations["strtoull"] = &StrTo;
Optimizations["strstr"] = &StrStr;
Optimizations["memcmp"] = &MemCmp;
Optimizations["memcpy"] = &MemCpy;
Optimizations["memmove"] = &MemMove;
Optimizations["memset"] = &MemSet;
// _chk variants of String and Memory LibCall Optimizations.
Optimizations["__strcpy_chk"] = &StrCpyChk;
// Math Library Optimizations
Optimizations["powf"] = &Pow;
Optimizations["pow"] = &Pow;
Optimizations["powl"] = &Pow;
Optimizations["llvm.pow.f32"] = &Pow;
Optimizations["llvm.pow.f64"] = &Pow;
Optimizations["llvm.pow.f80"] = &Pow;
Optimizations["llvm.pow.f128"] = &Pow;
Optimizations["llvm.pow.ppcf128"] = &Pow;
Optimizations["exp2l"] = &Exp2;
Optimizations["exp2"] = &Exp2;
Optimizations["exp2f"] = &Exp2;
Optimizations["llvm.exp2.ppcf128"] = &Exp2;
Optimizations["llvm.exp2.f128"] = &Exp2;
Optimizations["llvm.exp2.f80"] = &Exp2;
Optimizations["llvm.exp2.f64"] = &Exp2;
Optimizations["llvm.exp2.f32"] = &Exp2;
#ifdef HAVE_FLOORF
Optimizations["floor"] = &UnaryDoubleFP;
#endif
#ifdef HAVE_CEILF
Optimizations["ceil"] = &UnaryDoubleFP;
#endif
#ifdef HAVE_ROUNDF
Optimizations["round"] = &UnaryDoubleFP;
#endif
#ifdef HAVE_RINTF
Optimizations["rint"] = &UnaryDoubleFP;
#endif
#ifdef HAVE_NEARBYINTF
Optimizations["nearbyint"] = &UnaryDoubleFP;
#endif
// Integer Optimizations
Optimizations["ffs"] = &FFS;
Optimizations["ffsl"] = &FFS;
Optimizations["ffsll"] = &FFS;
Optimizations["abs"] = &Abs;
Optimizations["labs"] = &Abs;
Optimizations["llabs"] = &Abs;
Optimizations["isdigit"] = &IsDigit;
Optimizations["isascii"] = &IsAscii;
Optimizations["toascii"] = &ToAscii;
// Formatting and IO Optimizations
Optimizations["sprintf"] = &SPrintF;
Optimizations["printf"] = &PrintF;
Optimizations["fwrite"] = &FWrite;
Optimizations["fputs"] = &FPuts;
Optimizations["fprintf"] = &FPrintF;
}
/// runOnFunction - Top level algorithm.
///
bool SimplifyLibCalls::runOnFunction(Function &F) {
if (Optimizations.empty())
InitOptimizations();
const TargetData *TD = getAnalysisIfAvailable<TargetData>();
IRBuilder<> Builder(F.getContext());
bool Changed = false;
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
// Ignore non-calls.
CallInst *CI = dyn_cast<CallInst>(I++);
if (!CI) continue;
// Ignore indirect calls and calls to non-external functions.
Function *Callee = CI->getCalledFunction();
if (Callee == 0 || !Callee->isDeclaration() ||
!(Callee->hasExternalLinkage() || Callee->hasDLLImportLinkage()))
continue;
// Ignore unknown calls.
LibCallOptimization *LCO = Optimizations.lookup(Callee->getName());
if (!LCO) continue;
// Set the builder to the instruction after the call.
Builder.SetInsertPoint(BB, I);
// Try to optimize this call.
Value *Result = LCO->OptimizeCall(CI, TD, Builder);
if (Result == 0) continue;
DEBUG(dbgs() << "SimplifyLibCalls simplified: " << *CI;
dbgs() << " into: " << *Result << "\n");
// Something changed!
Changed = true;
++NumSimplified;
// Inspect the instruction after the call (which was potentially just
// added) next.
I = CI; ++I;
if (CI != Result && !CI->use_empty()) {
CI->replaceAllUsesWith(Result);
if (!Result->hasName())
Result->takeName(CI);
}
CI->eraseFromParent();
}
}
return Changed;
}
// Utility methods for doInitialization.
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
void SimplifyLibCalls::setDoesNotAccessMemory(Function &F) {
if (!F.doesNotAccessMemory()) {
F.setDoesNotAccessMemory();
++NumAnnotated;
Modified = true;
}
}
void SimplifyLibCalls::setOnlyReadsMemory(Function &F) {
if (!F.onlyReadsMemory()) {
F.setOnlyReadsMemory();
++NumAnnotated;
Modified = true;
}
}
void SimplifyLibCalls::setDoesNotThrow(Function &F) {
if (!F.doesNotThrow()) {
F.setDoesNotThrow();
++NumAnnotated;
Modified = true;
}
}
void SimplifyLibCalls::setDoesNotCapture(Function &F, unsigned n) {
if (!F.doesNotCapture(n)) {
F.setDoesNotCapture(n);
++NumAnnotated;
Modified = true;
}
}
void SimplifyLibCalls::setDoesNotAlias(Function &F, unsigned n) {
if (!F.doesNotAlias(n)) {
F.setDoesNotAlias(n);
++NumAnnotated;
Modified = true;
}
}
/// 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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "strxfrm") {
if (FTy->getNumParams() != 3 ||
Duncan Sands
committed
!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 == "strcoll" ||
Name == "strcasecmp" ||
Name == "strncasecmp") {
if (FTy->getNumParams() < 2 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setOnlyReadsMemory(F);
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "strtok" ||
Name == "strtok_r") {
if (FTy->getNumParams() < 2 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "scanf" ||
Name == "setbuf" ||
Name == "setvbuf") {
if (FTy->getNumParams() < 1 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "strdup" ||
Name == "strndup") {
if (FTy->getNumParams() < 1 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
// May throw; "system" is a valid pthread cancellation point.
setDoesNotCapture(F, 1);
}
break;
case 'm':
Victor Hernandez
committed
if (Name == "malloc") {
if (FTy->getNumParams() != 1 ||
Duncan Sands
committed
!FTy->getReturnType()->isPointerTy())
Victor Hernandez
committed
continue;
setDoesNotThrow(F);
setDoesNotAlias(F, 0);
} else if (Name == "memcmp") {
if (FTy->getNumParams() != 3 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "memalign") {
Duncan Sands
committed
if (!FTy->getReturnType()->isPointerTy())
continue;
setDoesNotAlias(F, 0);
} else if (Name == "mkdir" ||
Name == "mktime") {
if (FTy->getNumParams() == 0 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
}
break;
case 'r':
if (Name == "realloc") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy() ||
!FTy->getReturnType()->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotAlias(F, 0);
setDoesNotCapture(F, 1);
} else if (Name == "read") {
if (FTy->getNumParams() != 3 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "rename" ||
Name == "readlink") {
if (FTy->getNumParams() < 2 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
}
break;
case 'c':
if (Name == "calloc") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setOnlyReadsMemory(F);
setDoesNotCapture(F, 1);
} else if (Name == "access") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
}
break;
case 'f':
if (Name == "fopen") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "ferror") {
if (FTy->getNumParams() != 1 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "fgets") {
if (FTy->getNumParams() != 3 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy() ||
!FTy->getParamType(2)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 3);
} else if (Name == "fread" ||
Name == "fwrite") {
if (FTy->getNumParams() != 4 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "getenv") {
if (FTy->getNumParams() != 1 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "getpwnam") {
if (FTy->getNumParams() != 1 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
}
break;
case 'u':
if (Name == "ungetc") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "uname" ||
Name == "unlink" ||
Name == "unsetenv") {
if (FTy->getNumParams() != 1 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "utime" ||
Name == "utimes") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 2);
} else if (Name == "puts" ||
Name == "printf" ||
Name == "perror") {
if (FTy->getNumParams() != 1 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "pread" ||
Name == "pwrite") {
if (FTy->getNumParams() != 4 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
}
break;
case 'v':
if (Name == "vscanf") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "vsscanf" ||
Name == "vfscanf") {
if (FTy->getNumParams() != 3 ||
Duncan Sands
committed
!FTy->getParamType(1)->isPointerTy() ||
!FTy->getParamType(2)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
setDoesNotCapture(F, 2);
} else if (Name == "valloc") {
Duncan Sands
committed
if (!FTy->getReturnType()->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotAlias(F, 0);
} else if (Name == "vprintf") {
if (FTy->getNumParams() != 2 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy())
continue;
setDoesNotThrow(F);
setDoesNotCapture(F, 1);
} else if (Name == "vfprintf" ||
Name == "vsprintf") {
if (FTy->getNumParams() != 3 ||
Duncan Sands
committed
!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 ||
Duncan Sands
committed
!FTy->getParamType(0)->isPointerTy() ||