forked from OSchip/llvm-project
[TLI] Unify LibFunc signature checking. NFCI.
I tried to be as close as possible to the strongest check that existed before; cleaning these up properly is left for future work. Differential Revision: http://reviews.llvm.org/D19469 llvm-svn: 267758
This commit is contained in:
parent
220c4010bf
commit
d765a82b54
|
@ -71,6 +71,11 @@ class TargetLibraryInfoImpl {
|
|||
/// on VectorFnName rather than ScalarFnName.
|
||||
std::vector<VecDesc> ScalarDescs;
|
||||
|
||||
/// Return true if the function type FTy is valid for the library function
|
||||
/// F, regardless of whether the function is available.
|
||||
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc::Func F,
|
||||
const DataLayout *DL) const;
|
||||
|
||||
public:
|
||||
/// List of known vector-functions libraries.
|
||||
///
|
||||
|
@ -99,6 +104,13 @@ public:
|
|||
/// corresponding value.
|
||||
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const;
|
||||
|
||||
/// Searches for a particular function name, also checking that its type is
|
||||
/// valid for the library function matching that name.
|
||||
///
|
||||
/// If it is one of the known library functions, return true and set F to the
|
||||
/// corresponding value.
|
||||
bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const;
|
||||
|
||||
/// Forces a function to be marked as unavailable.
|
||||
void setUnavailable(LibFunc::Func F) {
|
||||
setState(F, Unavailable);
|
||||
|
@ -195,6 +207,10 @@ public:
|
|||
return Impl->getLibFunc(funcName, F);
|
||||
}
|
||||
|
||||
bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const {
|
||||
return Impl->getLibFunc(FDecl, F);
|
||||
}
|
||||
|
||||
/// Tests whether a library function is available.
|
||||
bool has(LibFunc::Func F) const {
|
||||
return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
|
||||
|
|
|
@ -541,22 +541,6 @@ bool BasicAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
|
|||
return Worklist.empty();
|
||||
}
|
||||
|
||||
// FIXME: This code is duplicated with MemoryLocation and should be hoisted to
|
||||
// some common utility location.
|
||||
static bool isMemsetPattern16(const Function *MS,
|
||||
const TargetLibraryInfo &TLI) {
|
||||
if (TLI.has(LibFunc::memset_pattern16) &&
|
||||
MS->getName() == "memset_pattern16") {
|
||||
FunctionType *MemsetType = MS->getFunctionType();
|
||||
if (!MemsetType->isVarArg() && MemsetType->getNumParams() == 3 &&
|
||||
isa<PointerType>(MemsetType->getParamType(0)) &&
|
||||
isa<PointerType>(MemsetType->getParamType(1)) &&
|
||||
isa<IntegerType>(MemsetType->getParamType(2)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns the behavior when calling the given call site.
|
||||
FunctionModRefBehavior BasicAAResult::getModRefBehavior(ImmutableCallSite CS) {
|
||||
if (CS.doesNotAccessMemory())
|
||||
|
@ -629,7 +613,9 @@ static bool isWriteOnlyParam(ImmutableCallSite CS, unsigned ArgIdx,
|
|||
// LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
|
||||
// whenever possible. Note that all but the missing writeonly attribute are
|
||||
// handled via InferFunctionAttr.
|
||||
if (CS.getCalledFunction() && isMemsetPattern16(CS.getCalledFunction(), TLI))
|
||||
LibFunc::Func F;
|
||||
if (CS.getCalledFunction() && TLI.getLibFunc(*CS.getCalledFunction(), F) &&
|
||||
F == LibFunc::memset_pattern16 && TLI.has(F))
|
||||
if (ArgIdx == 0)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -90,23 +90,6 @@ MemoryLocation MemoryLocation::getForDest(const MemIntrinsic *MTI) {
|
|||
return MemoryLocation(MTI->getRawDest(), Size, AATags);
|
||||
}
|
||||
|
||||
// FIXME: This code is duplicated with BasicAliasAnalysis and should be hoisted
|
||||
// to some common utility location.
|
||||
static bool isMemsetPattern16(const Function *MS,
|
||||
const TargetLibraryInfo &TLI) {
|
||||
if (TLI.has(LibFunc::memset_pattern16) &&
|
||||
MS->getName() == "memset_pattern16") {
|
||||
FunctionType *MemsetType = MS->getFunctionType();
|
||||
if (!MemsetType->isVarArg() && MemsetType->getNumParams() == 3 &&
|
||||
isa<PointerType>(MemsetType->getParamType(0)) &&
|
||||
isa<PointerType>(MemsetType->getParamType(1)) &&
|
||||
isa<IntegerType>(MemsetType->getParamType(2)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryLocation MemoryLocation::getForArgument(ImmutableCallSite CS,
|
||||
unsigned ArgIdx,
|
||||
const TargetLibraryInfo &TLI) {
|
||||
|
@ -159,8 +142,9 @@ MemoryLocation MemoryLocation::getForArgument(ImmutableCallSite CS,
|
|||
// for memcpy/memset. This is particularly important because the
|
||||
// LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
|
||||
// whenever possible.
|
||||
if (CS.getCalledFunction() &&
|
||||
isMemsetPattern16(CS.getCalledFunction(), TLI)) {
|
||||
LibFunc::Func F;
|
||||
if (CS.getCalledFunction() && TLI.getLibFunc(*CS.getCalledFunction(), F) &&
|
||||
F == LibFunc::memset_pattern16 && TLI.has(F)) {
|
||||
assert((ArgIdx == 0 || ArgIdx == 1) &&
|
||||
"Invalid argument index for memset_pattern16");
|
||||
if (ArgIdx == 1)
|
||||
|
|
|
@ -479,6 +479,537 @@ bool TargetLibraryInfoImpl::getLibFunc(StringRef funcName,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
LibFunc::Func F,
|
||||
const DataLayout *DL) const {
|
||||
LLVMContext &Ctx = FTy.getContext();
|
||||
Type *PCharTy = Type::getInt8PtrTy(Ctx);
|
||||
Type *SizeTTy = DL ? DL->getIntPtrType(Ctx, /*AS=*/0) : nullptr;
|
||||
auto IsSizeTTy = [SizeTTy](Type *Ty) {
|
||||
return SizeTTy ? Ty == SizeTTy : Ty->isIntegerTy();
|
||||
};
|
||||
unsigned NumParams = FTy.getNumParams();
|
||||
|
||||
switch (F) {
|
||||
case LibFunc::strlen:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getReturnType()->isIntegerTy());
|
||||
|
||||
case LibFunc::strchr:
|
||||
case LibFunc::strrchr:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0) == FTy.getReturnType() &&
|
||||
FTy.getParamType(1)->isIntegerTy());
|
||||
|
||||
case LibFunc::strtol:
|
||||
case LibFunc::strtod:
|
||||
case LibFunc::strtof:
|
||||
case LibFunc::strtoul:
|
||||
case LibFunc::strtoll:
|
||||
case LibFunc::strtold:
|
||||
case LibFunc::strtoull:
|
||||
return ((NumParams == 2 || NumParams == 3) &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::strcat:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0) == FTy.getReturnType() &&
|
||||
FTy.getParamType(1) == FTy.getReturnType());
|
||||
|
||||
case LibFunc::strncat:
|
||||
return (NumParams == 3 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0) == FTy.getReturnType() &&
|
||||
FTy.getParamType(1) == FTy.getReturnType() &&
|
||||
FTy.getParamType(2)->isIntegerTy());
|
||||
|
||||
case LibFunc::strcpy_chk:
|
||||
case LibFunc::stpcpy_chk:
|
||||
--NumParams;
|
||||
if (!IsSizeTTy(FTy.getParamType(NumParams)))
|
||||
return false;
|
||||
// fallthrough
|
||||
case LibFunc::strcpy:
|
||||
case LibFunc::stpcpy:
|
||||
return (NumParams == 2 && FTy.getReturnType() == FTy.getParamType(0) &&
|
||||
FTy.getParamType(0) == FTy.getParamType(1) &&
|
||||
FTy.getParamType(0) == PCharTy);
|
||||
|
||||
case LibFunc::strncpy_chk:
|
||||
case LibFunc::stpncpy_chk:
|
||||
--NumParams;
|
||||
if (!IsSizeTTy(FTy.getParamType(NumParams)))
|
||||
return false;
|
||||
// fallthrough
|
||||
case LibFunc::strncpy:
|
||||
case LibFunc::stpncpy:
|
||||
return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) &&
|
||||
FTy.getParamType(0) == FTy.getParamType(1) &&
|
||||
FTy.getParamType(0) == PCharTy &&
|
||||
FTy.getParamType(2)->isIntegerTy());
|
||||
|
||||
case LibFunc::strxfrm:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
|
||||
case LibFunc::strcmp:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isIntegerTy(32) &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(0) == FTy.getParamType(1));
|
||||
|
||||
case LibFunc::strncmp:
|
||||
return (NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(0) == FTy.getParamType(1) &&
|
||||
FTy.getParamType(2)->isIntegerTy());
|
||||
|
||||
case LibFunc::strspn:
|
||||
case LibFunc::strcspn:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(0) == FTy.getParamType(1) &&
|
||||
FTy.getReturnType()->isIntegerTy());
|
||||
|
||||
case LibFunc::strcoll:
|
||||
case LibFunc::strcasecmp:
|
||||
case LibFunc::strncasecmp:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
|
||||
case LibFunc::strstr:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
|
||||
case LibFunc::strpbrk:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getReturnType() == FTy.getParamType(0) &&
|
||||
FTy.getParamType(0) == FTy.getParamType(1));
|
||||
|
||||
case LibFunc::strtok:
|
||||
case LibFunc::strtok_r:
|
||||
return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::scanf:
|
||||
return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::setbuf:
|
||||
case LibFunc::setvbuf:
|
||||
return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::strdup:
|
||||
case LibFunc::strndup:
|
||||
return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::stat:
|
||||
case LibFunc::statvfs:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::sscanf:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::sprintf:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::snprintf:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
case LibFunc::setitimer:
|
||||
return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
case LibFunc::system:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::malloc:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::memcmp:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy() &&
|
||||
FTy.getReturnType()->isIntegerTy(32));
|
||||
|
||||
case LibFunc::memchr:
|
||||
case LibFunc::memrchr:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isIntegerTy(32) &&
|
||||
FTy.getParamType(2)->isIntegerTy() &&
|
||||
FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::modf:
|
||||
case LibFunc::modff:
|
||||
case LibFunc::modfl:
|
||||
return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy());
|
||||
|
||||
case LibFunc::memcpy_chk:
|
||||
case LibFunc::memmove_chk:
|
||||
--NumParams;
|
||||
if (!IsSizeTTy(FTy.getParamType(NumParams)))
|
||||
return false;
|
||||
// fallthrough
|
||||
case LibFunc::memcpy:
|
||||
case LibFunc::memmove:
|
||||
return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy() &&
|
||||
IsSizeTTy(FTy.getParamType(2)));
|
||||
|
||||
case LibFunc::memset_chk:
|
||||
--NumParams;
|
||||
if (!IsSizeTTy(FTy.getParamType(NumParams)))
|
||||
return false;
|
||||
// fallthrough
|
||||
case LibFunc::memset:
|
||||
return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isIntegerTy() &&
|
||||
IsSizeTTy(FTy.getParamType(2)));
|
||||
|
||||
case LibFunc::memccpy:
|
||||
return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::memalign:
|
||||
return (FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::mkdir:
|
||||
return (NumParams == 0 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::mktime:
|
||||
return (NumParams == 0 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::realloc:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::read:
|
||||
return (NumParams == 3 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::rewind:
|
||||
return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::rmdir:
|
||||
case LibFunc::remove:
|
||||
case LibFunc::realpath:
|
||||
return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::rename:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::readlink:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::write:
|
||||
return (NumParams == 3 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::bcopy:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::bcmp:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::bzero:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::calloc:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::chmod:
|
||||
case LibFunc::chown:
|
||||
return (NumParams == 0 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::ctermid:
|
||||
case LibFunc::clearerr:
|
||||
case LibFunc::closedir:
|
||||
return (NumParams == 0 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::atoi:
|
||||
case LibFunc::atol:
|
||||
case LibFunc::atof:
|
||||
case LibFunc::atoll:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::access:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::fopen:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::fdopen:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::feof:
|
||||
case LibFunc::free:
|
||||
case LibFunc::fseek:
|
||||
case LibFunc::ftell:
|
||||
case LibFunc::fgetc:
|
||||
case LibFunc::fseeko:
|
||||
case LibFunc::ftello:
|
||||
case LibFunc::fileno:
|
||||
case LibFunc::fflush:
|
||||
case LibFunc::fclose:
|
||||
case LibFunc::fsetpos:
|
||||
case LibFunc::flockfile:
|
||||
case LibFunc::funlockfile:
|
||||
case LibFunc::ftrylockfile:
|
||||
return (NumParams == 0 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::ferror:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::fputc:
|
||||
case LibFunc::fstat:
|
||||
case LibFunc::frexp:
|
||||
case LibFunc::frexpf:
|
||||
case LibFunc::frexpl:
|
||||
case LibFunc::fstatvfs:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::fgets:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
case LibFunc::fread:
|
||||
return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(3)->isPointerTy());
|
||||
case LibFunc::fwrite:
|
||||
return (NumParams == 4 && FTy.getReturnType()->isIntegerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isIntegerTy() &&
|
||||
FTy.getParamType(2)->isIntegerTy() &&
|
||||
FTy.getParamType(3)->isPointerTy());
|
||||
case LibFunc::fputs:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::fscanf:
|
||||
case LibFunc::fprintf:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::fgetpos:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::getc:
|
||||
case LibFunc::getlogin_r:
|
||||
case LibFunc::getc_unlocked:
|
||||
return (NumParams == 0 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::getenv:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::gets:
|
||||
case LibFunc::getchar:
|
||||
case LibFunc::getitimer:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::getpwnam:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::ungetc:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::uname:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::unlink:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::unsetenv:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::utime:
|
||||
case LibFunc::utimes:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::putc:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::puts:
|
||||
case LibFunc::printf:
|
||||
case LibFunc::perror:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::pread:
|
||||
case LibFunc::pwrite:
|
||||
return (NumParams == 4 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::putchar:
|
||||
case LibFunc::popen:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::pclose:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::vscanf:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::vsscanf:
|
||||
return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
case LibFunc::vfscanf:
|
||||
return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
case LibFunc::valloc:
|
||||
return (FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::vprintf:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::vfprintf:
|
||||
case LibFunc::vsprintf:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::vsnprintf:
|
||||
return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
case LibFunc::open:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::opendir:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::tmpfile:
|
||||
return (FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::times:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::htonl:
|
||||
case LibFunc::htons:
|
||||
case LibFunc::ntohl:
|
||||
case LibFunc::ntohs:
|
||||
case LibFunc::lstat:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::lchown:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::qsort:
|
||||
return (NumParams == 4 && FTy.getParamType(3)->isPointerTy());
|
||||
case LibFunc::dunder_strdup:
|
||||
case LibFunc::dunder_strndup:
|
||||
return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::dunder_strtok_r:
|
||||
return (NumParams == 3 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::under_IO_getc:
|
||||
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::under_IO_putc:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::dunder_isoc99_scanf:
|
||||
return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::stat64:
|
||||
case LibFunc::lstat64:
|
||||
case LibFunc::statvfs64:
|
||||
return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::dunder_isoc99_sscanf:
|
||||
return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::fopen64:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::fseeko64:
|
||||
case LibFunc::ftello64:
|
||||
return (NumParams == 0 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::tmpfile64:
|
||||
return (FTy.getReturnType()->isPointerTy());
|
||||
case LibFunc::fstat64:
|
||||
case LibFunc::fstatvfs64:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc::open64:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy());
|
||||
case LibFunc::gettimeofday:
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
|
||||
case LibFunc::Znwj: // new(unsigned int);
|
||||
case LibFunc::Znwm: // new(unsigned long);
|
||||
case LibFunc::Znaj: // new[](unsigned int);
|
||||
case LibFunc::Znam: // new[](unsigned long);
|
||||
case LibFunc::msvc_new_int: // new(unsigned int);
|
||||
case LibFunc::msvc_new_longlong: // new(unsigned long long);
|
||||
case LibFunc::msvc_new_array_int: // new[](unsigned int);
|
||||
case LibFunc::msvc_new_array_longlong: // new[](unsigned long long);
|
||||
return (NumParams == 1);
|
||||
|
||||
case LibFunc::memset_pattern16:
|
||||
return (!FTy.isVarArg() && NumParams == 3 &&
|
||||
isa<PointerType>(FTy.getParamType(0)) &&
|
||||
isa<PointerType>(FTy.getParamType(1)) &&
|
||||
isa<IntegerType>(FTy.getParamType(2)));
|
||||
|
||||
// int __nvvm_reflect(const char *);
|
||||
case LibFunc::nvvm_reflect:
|
||||
return (NumParams == 1 && isa<PointerType>(FTy.getParamType(0)));
|
||||
|
||||
case LibFunc::sin:
|
||||
case LibFunc::sinf:
|
||||
case LibFunc::sinl:
|
||||
case LibFunc::cos:
|
||||
case LibFunc::cosf:
|
||||
case LibFunc::cosl:
|
||||
case LibFunc::exp:
|
||||
case LibFunc::expf:
|
||||
case LibFunc::expl:
|
||||
case LibFunc::exp2:
|
||||
case LibFunc::exp2f:
|
||||
case LibFunc::exp2l:
|
||||
case LibFunc::log:
|
||||
case LibFunc::logf:
|
||||
case LibFunc::logl:
|
||||
case LibFunc::log10:
|
||||
case LibFunc::log10f:
|
||||
case LibFunc::log10l:
|
||||
case LibFunc::log2:
|
||||
case LibFunc::log2f:
|
||||
case LibFunc::log2l:
|
||||
case LibFunc::fabs:
|
||||
case LibFunc::fabsf:
|
||||
case LibFunc::fabsl:
|
||||
case LibFunc::floor:
|
||||
case LibFunc::floorf:
|
||||
case LibFunc::floorl:
|
||||
case LibFunc::ceil:
|
||||
case LibFunc::ceilf:
|
||||
case LibFunc::ceill:
|
||||
case LibFunc::trunc:
|
||||
case LibFunc::truncf:
|
||||
case LibFunc::truncl:
|
||||
case LibFunc::rint:
|
||||
case LibFunc::rintf:
|
||||
case LibFunc::rintl:
|
||||
case LibFunc::nearbyint:
|
||||
case LibFunc::nearbyintf:
|
||||
case LibFunc::nearbyintl:
|
||||
case LibFunc::round:
|
||||
case LibFunc::roundf:
|
||||
case LibFunc::roundl:
|
||||
case LibFunc::sqrt:
|
||||
case LibFunc::sqrtf:
|
||||
case LibFunc::sqrtl:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isFloatingPointTy() &&
|
||||
FTy.getReturnType() == FTy.getParamType(0));
|
||||
|
||||
case LibFunc::fmin:
|
||||
case LibFunc::fminf:
|
||||
case LibFunc::fminl:
|
||||
case LibFunc::fmax:
|
||||
case LibFunc::fmaxf:
|
||||
case LibFunc::fmaxl:
|
||||
case LibFunc::copysign:
|
||||
case LibFunc::copysignf:
|
||||
case LibFunc::copysignl:
|
||||
case LibFunc::pow:
|
||||
case LibFunc::powf:
|
||||
case LibFunc::powl:
|
||||
return (NumParams == 2 && FTy.getReturnType()->isFloatingPointTy() &&
|
||||
FTy.getReturnType() == FTy.getParamType(0) &&
|
||||
FTy.getReturnType() == FTy.getParamType(1));
|
||||
|
||||
case LibFunc::ffs:
|
||||
case LibFunc::ffsl:
|
||||
case LibFunc::ffsll:
|
||||
case LibFunc::isdigit:
|
||||
case LibFunc::isascii:
|
||||
case LibFunc::toascii:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isIntegerTy(32) &&
|
||||
FTy.getParamType(0)->isIntegerTy());
|
||||
|
||||
case LibFunc::fls:
|
||||
case LibFunc::flsl:
|
||||
case LibFunc::flsll:
|
||||
case LibFunc::abs:
|
||||
case LibFunc::labs:
|
||||
case LibFunc::llabs:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isIntegerTy() &&
|
||||
FTy.getReturnType() == FTy.getParamType(0));
|
||||
|
||||
case LibFunc::cxa_atexit:
|
||||
return (NumParams == 3 && FTy.getReturnType()->isIntegerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
|
||||
case LibFunc::sinpi:
|
||||
case LibFunc::cospi:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isDoubleTy() &&
|
||||
FTy.getReturnType() == FTy.getParamType(0));
|
||||
|
||||
case LibFunc::sinpif:
|
||||
case LibFunc::cospif:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isFloatTy() &&
|
||||
FTy.getReturnType() == FTy.getParamType(0));
|
||||
|
||||
default:
|
||||
// Assume the other functions are correct.
|
||||
// FIXME: It'd be really nice to cover them all.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl,
|
||||
LibFunc::Func &F) const {
|
||||
const DataLayout *DL =
|
||||
FDecl.getParent() ? &FDecl.getParent()->getDataLayout() : nullptr;
|
||||
return getLibFunc(FDecl.getName(), F) &&
|
||||
isValidProtoForLibFunc(*FDecl.getFunctionType(), F, DL);
|
||||
}
|
||||
|
||||
void TargetLibraryInfoImpl::disableAllFunctions() {
|
||||
memset(AvailableArray, 0, sizeof(AvailableArray));
|
||||
}
|
||||
|
|
|
@ -2242,46 +2242,6 @@ bool llvm::ComputeMultiple(Value *V, unsigned Base, Value *&Multiple,
|
|||
return false;
|
||||
}
|
||||
|
||||
/// \brief Check call has a unary float signature
|
||||
/// It checks following:
|
||||
/// a) call should have a single argument
|
||||
/// b) argument type should be floating point type
|
||||
/// c) call instruction type and argument type should be same
|
||||
/// d) call should only reads memory.
|
||||
/// If all these condition is met then return ValidIntrinsicID
|
||||
/// else return not_intrinsic.
|
||||
static Intrinsic::ID checkUnaryFloatSignature(ImmutableCallSite ICS,
|
||||
Intrinsic::ID ValidIntrinsicID) {
|
||||
if (ICS.getNumArgOperands() != 1 ||
|
||||
!ICS.getArgOperand(0)->getType()->isFloatingPointTy() ||
|
||||
ICS.getType() != ICS.getArgOperand(0)->getType() ||
|
||||
!ICS.onlyReadsMemory())
|
||||
return Intrinsic::not_intrinsic;
|
||||
|
||||
return ValidIntrinsicID;
|
||||
}
|
||||
|
||||
/// \brief Check call has a binary float signature
|
||||
/// It checks following:
|
||||
/// a) call should have 2 arguments.
|
||||
/// b) arguments type should be floating point type
|
||||
/// c) call instruction type and arguments type should be same
|
||||
/// d) call should only reads memory.
|
||||
/// If all these condition is met then return ValidIntrinsicID
|
||||
/// else return not_intrinsic.
|
||||
static Intrinsic::ID checkBinaryFloatSignature(ImmutableCallSite ICS,
|
||||
Intrinsic::ID ValidIntrinsicID) {
|
||||
if (ICS.getNumArgOperands() != 2 ||
|
||||
!ICS.getArgOperand(0)->getType()->isFloatingPointTy() ||
|
||||
!ICS.getArgOperand(1)->getType()->isFloatingPointTy() ||
|
||||
ICS.getType() != ICS.getArgOperand(0)->getType() ||
|
||||
ICS.getType() != ICS.getArgOperand(1)->getType() ||
|
||||
!ICS.onlyReadsMemory())
|
||||
return Intrinsic::not_intrinsic;
|
||||
|
||||
return ValidIntrinsicID;
|
||||
}
|
||||
|
||||
Intrinsic::ID llvm::getIntrinsicForCallSite(ImmutableCallSite ICS,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
const Function *F = ICS.getCalledFunction();
|
||||
|
@ -2298,7 +2258,10 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(ImmutableCallSite ICS,
|
|||
// We're going to make assumptions on the semantics of the functions, check
|
||||
// that the target knows that it's available in this environment and it does
|
||||
// not have local linkage.
|
||||
if (!F || F->hasLocalLinkage() || !TLI->getLibFunc(F->getName(), Func))
|
||||
if (!F || F->hasLocalLinkage() || !TLI->getLibFunc(*F, Func))
|
||||
return Intrinsic::not_intrinsic;
|
||||
|
||||
if (!ICS.onlyReadsMemory())
|
||||
return Intrinsic::not_intrinsic;
|
||||
|
||||
// Otherwise check if we have a call to a function that can be turned into a
|
||||
|
@ -2309,80 +2272,80 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(ImmutableCallSite ICS,
|
|||
case LibFunc::sin:
|
||||
case LibFunc::sinf:
|
||||
case LibFunc::sinl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::sin);
|
||||
return Intrinsic::sin;
|
||||
case LibFunc::cos:
|
||||
case LibFunc::cosf:
|
||||
case LibFunc::cosl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::cos);
|
||||
return Intrinsic::cos;
|
||||
case LibFunc::exp:
|
||||
case LibFunc::expf:
|
||||
case LibFunc::expl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::exp);
|
||||
return Intrinsic::exp;
|
||||
case LibFunc::exp2:
|
||||
case LibFunc::exp2f:
|
||||
case LibFunc::exp2l:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::exp2);
|
||||
return Intrinsic::exp2;
|
||||
case LibFunc::log:
|
||||
case LibFunc::logf:
|
||||
case LibFunc::logl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::log);
|
||||
return Intrinsic::log;
|
||||
case LibFunc::log10:
|
||||
case LibFunc::log10f:
|
||||
case LibFunc::log10l:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::log10);
|
||||
return Intrinsic::log10;
|
||||
case LibFunc::log2:
|
||||
case LibFunc::log2f:
|
||||
case LibFunc::log2l:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::log2);
|
||||
return Intrinsic::log2;
|
||||
case LibFunc::fabs:
|
||||
case LibFunc::fabsf:
|
||||
case LibFunc::fabsl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::fabs);
|
||||
return Intrinsic::fabs;
|
||||
case LibFunc::fmin:
|
||||
case LibFunc::fminf:
|
||||
case LibFunc::fminl:
|
||||
return checkBinaryFloatSignature(ICS, Intrinsic::minnum);
|
||||
return Intrinsic::minnum;
|
||||
case LibFunc::fmax:
|
||||
case LibFunc::fmaxf:
|
||||
case LibFunc::fmaxl:
|
||||
return checkBinaryFloatSignature(ICS, Intrinsic::maxnum);
|
||||
return Intrinsic::maxnum;
|
||||
case LibFunc::copysign:
|
||||
case LibFunc::copysignf:
|
||||
case LibFunc::copysignl:
|
||||
return checkBinaryFloatSignature(ICS, Intrinsic::copysign);
|
||||
return Intrinsic::copysign;
|
||||
case LibFunc::floor:
|
||||
case LibFunc::floorf:
|
||||
case LibFunc::floorl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::floor);
|
||||
return Intrinsic::floor;
|
||||
case LibFunc::ceil:
|
||||
case LibFunc::ceilf:
|
||||
case LibFunc::ceill:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::ceil);
|
||||
return Intrinsic::ceil;
|
||||
case LibFunc::trunc:
|
||||
case LibFunc::truncf:
|
||||
case LibFunc::truncl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::trunc);
|
||||
return Intrinsic::trunc;
|
||||
case LibFunc::rint:
|
||||
case LibFunc::rintf:
|
||||
case LibFunc::rintl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::rint);
|
||||
return Intrinsic::rint;
|
||||
case LibFunc::nearbyint:
|
||||
case LibFunc::nearbyintf:
|
||||
case LibFunc::nearbyintl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::nearbyint);
|
||||
return Intrinsic::nearbyint;
|
||||
case LibFunc::round:
|
||||
case LibFunc::roundf:
|
||||
case LibFunc::roundl:
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::round);
|
||||
return Intrinsic::round;
|
||||
case LibFunc::pow:
|
||||
case LibFunc::powf:
|
||||
case LibFunc::powl:
|
||||
return checkBinaryFloatSignature(ICS, Intrinsic::pow);
|
||||
return Intrinsic::pow;
|
||||
case LibFunc::sqrt:
|
||||
case LibFunc::sqrtf:
|
||||
case LibFunc::sqrtl:
|
||||
if (ICS->hasNoNaNs())
|
||||
return checkUnaryFloatSignature(ICS, Intrinsic::sqrt);
|
||||
return Intrinsic::sqrt;
|
||||
return Intrinsic::not_intrinsic;
|
||||
}
|
||||
|
||||
|
|
|
@ -2391,23 +2391,16 @@ OptimizeGlobalAliases(Module &M,
|
|||
}
|
||||
|
||||
static Function *FindCXAAtExit(Module &M, TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc::cxa_atexit))
|
||||
LibFunc::Func F = LibFunc::cxa_atexit;
|
||||
if (!TLI->has(F))
|
||||
return nullptr;
|
||||
|
||||
Function *Fn = M.getFunction(TLI->getName(LibFunc::cxa_atexit));
|
||||
|
||||
Function *Fn = M.getFunction(TLI->getName(F));
|
||||
if (!Fn)
|
||||
return nullptr;
|
||||
|
||||
FunctionType *FTy = Fn->getFunctionType();
|
||||
|
||||
// Checking that the function has the right return type, the right number of
|
||||
// parameters and that they all have pointer types should be enough.
|
||||
if (!FTy->getReturnType()->isIntegerTy() ||
|
||||
FTy->getNumParams() != 3 ||
|
||||
!FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy() ||
|
||||
!FTy->getParamType(2)->isPointerTy())
|
||||
// Make sure that the function has the correct prototype.
|
||||
if (!TLI->getLibFunc(*Fn, F) || F != LibFunc::cxa_atexit)
|
||||
return nullptr;
|
||||
|
||||
return Fn;
|
||||
|
|
|
@ -106,25 +106,19 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
if (F.hasFnAttribute(Attribute::OptimizeNone))
|
||||
return false;
|
||||
|
||||
FunctionType *FTy = F.getFunctionType();
|
||||
LibFunc::Func TheLibFunc;
|
||||
if (!(TLI.getLibFunc(F.getName(), TheLibFunc) && TLI.has(TheLibFunc)))
|
||||
if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc)))
|
||||
return false;
|
||||
|
||||
bool Changed = false;
|
||||
switch (TheLibFunc) {
|
||||
case LibFunc::strlen:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::strchr:
|
||||
case LibFunc::strrchr:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isIntegerTy())
|
||||
return false;
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotThrow(F);
|
||||
return Changed;
|
||||
|
@ -135,8 +129,6 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::strtoll:
|
||||
case LibFunc::strtold:
|
||||
case LibFunc::strtoull:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
|
@ -147,16 +139,11 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::strncat:
|
||||
case LibFunc::strncpy:
|
||||
case LibFunc::stpncpy:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::strxfrm:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -169,9 +156,6 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::strcoll: // 0,1
|
||||
case LibFunc::strcasecmp: // 0,1
|
||||
case LibFunc::strncasecmp: //
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
|
@ -179,39 +163,28 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
return Changed;
|
||||
case LibFunc::strstr:
|
||||
case LibFunc::strpbrk:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::strtok:
|
||||
case LibFunc::strtok_r:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::scanf:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::setbuf:
|
||||
case LibFunc::setvbuf:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::strdup:
|
||||
case LibFunc::strndup:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy() ||
|
||||
!FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
|
@ -219,18 +192,12 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
return Changed;
|
||||
case LibFunc::stat:
|
||||
case LibFunc::statvfs:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::sscanf:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -238,49 +205,33 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::sprintf:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::snprintf:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(2)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 3);
|
||||
Changed |= setOnlyReadsMemory(F, 3);
|
||||
return Changed;
|
||||
case LibFunc::setitimer:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy() ||
|
||||
!FTy->getParamType(2)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setDoesNotCapture(F, 3);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::system:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
// May throw; "system" is a valid pthread cancellation point.
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::malloc:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getReturnType()->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
return Changed;
|
||||
case LibFunc::memcmp:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
|
@ -288,79 +239,55 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
return Changed;
|
||||
case LibFunc::memchr:
|
||||
case LibFunc::memrchr:
|
||||
if (FTy->getNumParams() != 3)
|
||||
return false;
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotThrow(F);
|
||||
return Changed;
|
||||
case LibFunc::modf:
|
||||
case LibFunc::modff:
|
||||
case LibFunc::modfl:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::memcpy:
|
||||
case LibFunc::memccpy:
|
||||
case LibFunc::memmove:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::memalign:
|
||||
if (!FTy->getReturnType()->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
return Changed;
|
||||
case LibFunc::mkdir:
|
||||
if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::mktime:
|
||||
if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::realloc:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getReturnType()->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::read:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
// May throw; "read" is a valid pthread cancellation point.
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::rewind:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::rmdir:
|
||||
case LibFunc::remove:
|
||||
case LibFunc::realpath:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::rename:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -368,55 +295,38 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::readlink:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::write:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
// May throw; "write" is a valid pthread cancellation point.
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::bcopy:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::bcmp:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::bzero:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::calloc:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getReturnType()->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
return Changed;
|
||||
case LibFunc::chmod:
|
||||
case LibFunc::chown:
|
||||
if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
|
@ -424,8 +334,6 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::ctermid:
|
||||
case LibFunc::clearerr:
|
||||
case LibFunc::closedir:
|
||||
if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
|
@ -433,24 +341,16 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::atol:
|
||||
case LibFunc::atof:
|
||||
case LibFunc::atoll:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::access:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::fopen:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getReturnType()->isPointerTy() ||
|
||||
!FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
|
@ -459,9 +359,6 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::fdopen:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getReturnType()->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -481,14 +378,10 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::flockfile:
|
||||
case LibFunc::funlockfile:
|
||||
case LibFunc::ftrylockfile:
|
||||
if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::ferror:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
|
@ -499,38 +392,24 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::frexpf:
|
||||
case LibFunc::frexpl:
|
||||
case LibFunc::fstatvfs:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::fgets:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(2)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 3);
|
||||
return Changed;
|
||||
case LibFunc::fread:
|
||||
if (FTy->getNumParams() != 4 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(3)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 4);
|
||||
return Changed;
|
||||
case LibFunc::fwrite:
|
||||
if (FTy->getNumParams() != 4 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(3)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 4);
|
||||
return Changed;
|
||||
case LibFunc::fputs:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -538,18 +417,12 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
return Changed;
|
||||
case LibFunc::fscanf:
|
||||
case LibFunc::fprintf:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::fgetpos:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -557,14 +430,10 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::getc:
|
||||
case LibFunc::getlogin_r:
|
||||
case LibFunc::getc_unlocked:
|
||||
if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::getenv:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
|
@ -574,49 +443,34 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setDoesNotThrow(F);
|
||||
return Changed;
|
||||
case LibFunc::getitimer:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::getpwnam:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::ungetc:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::uname:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::unlink:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::unsetenv:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::utime:
|
||||
case LibFunc::utimes:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -624,29 +478,21 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::putc:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::puts:
|
||||
case LibFunc::printf:
|
||||
case LibFunc::perror:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::pread:
|
||||
if (FTy->getNumParams() != 4 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
// May throw; "pread" is a valid pthread cancellation point.
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::pwrite:
|
||||
if (FTy->getNumParams() != 4 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
// May throw; "pwrite" is a valid pthread cancellation point.
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
|
@ -655,10 +501,6 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setDoesNotThrow(F);
|
||||
return Changed;
|
||||
case LibFunc::popen:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getReturnType()->isPointerTy() ||
|
||||
!FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
|
@ -667,22 +509,15 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::pclose:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::vscanf:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::vsscanf:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy() ||
|
||||
!FTy->getParamType(2)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -690,71 +525,49 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::vfscanf:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy() ||
|
||||
!FTy->getParamType(2)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::valloc:
|
||||
if (!FTy->getReturnType()->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
return Changed;
|
||||
case LibFunc::vprintf:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::vfprintf:
|
||||
case LibFunc::vsprintf:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::vsnprintf:
|
||||
if (FTy->getNumParams() != 4 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(2)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 3);
|
||||
Changed |= setOnlyReadsMemory(F, 3);
|
||||
return Changed;
|
||||
case LibFunc::open:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
// May throw; "open" is a valid pthread cancellation point.
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::opendir:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getReturnType()->isPointerTy() ||
|
||||
!FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::tmpfile:
|
||||
if (!FTy->getReturnType()->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
return Changed;
|
||||
case LibFunc::times:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
|
@ -766,59 +579,41 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setDoesNotAccessMemory(F);
|
||||
return Changed;
|
||||
case LibFunc::lstat:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::lchown:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::qsort:
|
||||
if (FTy->getNumParams() != 4 || !FTy->getParamType(3)->isPointerTy())
|
||||
return false;
|
||||
// May throw; places call through function pointer.
|
||||
Changed |= setDoesNotCapture(F, 4);
|
||||
return Changed;
|
||||
case LibFunc::dunder_strdup:
|
||||
case LibFunc::dunder_strndup:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy() ||
|
||||
!FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::dunder_strtok_r:
|
||||
if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::under_IO_getc:
|
||||
if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::under_IO_putc:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::dunder_isoc99_scanf:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
|
@ -826,18 +621,12 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::stat64:
|
||||
case LibFunc::lstat64:
|
||||
case LibFunc::statvfs64:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::dunder_isoc99_sscanf:
|
||||
if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
|
@ -845,10 +634,6 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::fopen64:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getReturnType()->isPointerTy() ||
|
||||
!FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
|
@ -858,35 +643,24 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
return Changed;
|
||||
case LibFunc::fseeko64:
|
||||
case LibFunc::ftello64:
|
||||
if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::tmpfile64:
|
||||
if (!FTy->getReturnType()->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotAlias(F, 0);
|
||||
return Changed;
|
||||
case LibFunc::fstat64:
|
||||
case LibFunc::fstatvfs64:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc::open64:
|
||||
if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
|
||||
return false;
|
||||
// May throw; "open" is a valid pthread cancellation point.
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc::gettimeofday:
|
||||
if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy() ||
|
||||
!FTy->getParamType(1)->isPointerTy())
|
||||
return false;
|
||||
// Currently some platforms have the restrict keyword on the arguments to
|
||||
// gettimeofday. To be conservative, do not add noalias to gettimeofday's
|
||||
// arguments.
|
||||
|
@ -894,7 +668,6 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
Changed |= setDoesNotCapture(F, 1);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
|
||||
case LibFunc::Znwj: // new(unsigned int)
|
||||
case LibFunc::Znwm: // new(unsigned long)
|
||||
case LibFunc::Znaj: // new[](unsigned int)
|
||||
|
@ -903,32 +676,19 @@ static bool inferPrototypeAttributes(Function &F,
|
|||
case LibFunc::msvc_new_longlong: // new(unsigned long long)
|
||||
case LibFunc::msvc_new_array_int: // new[](unsigned int)
|
||||
case LibFunc::msvc_new_array_longlong: // new[](unsigned long long)
|
||||
if (FTy->getNumParams() != 1)
|
||||
return false;
|
||||
// Operator new always returns a nonnull noalias pointer
|
||||
Changed |= setNonNull(F, AttributeSet::ReturnIndex);
|
||||
Changed |= setDoesNotAlias(F, AttributeSet::ReturnIndex);
|
||||
return Changed;
|
||||
|
||||
//TODO: add LibFunc entries for:
|
||||
//case LibFunc::memset_pattern4:
|
||||
//case LibFunc::memset_pattern8:
|
||||
case LibFunc::memset_pattern16:
|
||||
if (FTy->isVarArg() || FTy->getNumParams() != 3 ||
|
||||
!isa<PointerType>(FTy->getParamType(0)) ||
|
||||
!isa<PointerType>(FTy->getParamType(1)) ||
|
||||
!isa<IntegerType>(FTy->getParamType(2)))
|
||||
return false;
|
||||
|
||||
Changed |= setOnlyAccessesArgMemory(F);
|
||||
Changed |= setOnlyReadsMemory(F, 2);
|
||||
return Changed;
|
||||
|
||||
// int __nvvm_reflect(const char *)
|
||||
case LibFunc::nvvm_reflect:
|
||||
if (FTy->getNumParams() != 1 || !isa<PointerType>(FTy->getParamType(0)))
|
||||
return false;
|
||||
|
||||
Changed |= setDoesNotAccessMemory(F);
|
||||
Changed |= setDoesNotThrow(F);
|
||||
return Changed;
|
||||
|
|
|
@ -103,84 +103,11 @@ static bool hasUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty,
|
|||
}
|
||||
}
|
||||
|
||||
/// \brief Returns whether \p F matches the signature expected for the
|
||||
/// string/memory copying library function \p Func.
|
||||
/// Acceptable functions are st[rp][n]?cpy, memove, memcpy, and memset.
|
||||
/// Their fortified (_chk) counterparts are also accepted.
|
||||
static bool checkStringCopyLibFuncSignature(Function *F, LibFunc::Func Func) {
|
||||
const DataLayout &DL = F->getParent()->getDataLayout();
|
||||
FunctionType *FT = F->getFunctionType();
|
||||
LLVMContext &Context = F->getContext();
|
||||
Type *PCharTy = Type::getInt8PtrTy(Context);
|
||||
Type *SizeTTy = DL.getIntPtrType(Context);
|
||||
unsigned NumParams = FT->getNumParams();
|
||||
|
||||
// All string libfuncs return the same type as the first parameter.
|
||||
if (FT->getReturnType() != FT->getParamType(0))
|
||||
return false;
|
||||
|
||||
switch (Func) {
|
||||
default:
|
||||
llvm_unreachable("Can't check signature for non-string-copy libfunc.");
|
||||
case LibFunc::stpncpy_chk:
|
||||
case LibFunc::strncpy_chk:
|
||||
--NumParams; // fallthrough
|
||||
case LibFunc::stpncpy:
|
||||
case LibFunc::strncpy: {
|
||||
if (NumParams != 3 || FT->getParamType(0) != FT->getParamType(1) ||
|
||||
FT->getParamType(0) != PCharTy || !FT->getParamType(2)->isIntegerTy())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case LibFunc::strcpy_chk:
|
||||
case LibFunc::stpcpy_chk:
|
||||
--NumParams; // fallthrough
|
||||
case LibFunc::stpcpy:
|
||||
case LibFunc::strcpy: {
|
||||
if (NumParams != 2 || FT->getParamType(0) != FT->getParamType(1) ||
|
||||
FT->getParamType(0) != PCharTy)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case LibFunc::memmove_chk:
|
||||
case LibFunc::memcpy_chk:
|
||||
--NumParams; // fallthrough
|
||||
case LibFunc::memmove:
|
||||
case LibFunc::memcpy: {
|
||||
if (NumParams != 3 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isPointerTy() || FT->getParamType(2) != SizeTTy)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case LibFunc::memset_chk:
|
||||
--NumParams; // fallthrough
|
||||
case LibFunc::memset: {
|
||||
if (NumParams != 3 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isIntegerTy() || FT->getParamType(2) != SizeTTy)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If this is a fortified libcall, the last parameter is a size_t.
|
||||
if (NumParams == FT->getNumParams() - 1)
|
||||
return FT->getParamType(FT->getNumParams() - 1) == SizeTTy;
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// String and Memory Library Call Optimizations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrCat(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Verify the "strcat" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2||
|
||||
FT->getReturnType() != B.getInt8PtrTy() ||
|
||||
FT->getParamType(0) != FT->getReturnType() ||
|
||||
FT->getParamType(1) != FT->getReturnType())
|
||||
return nullptr;
|
||||
|
||||
// Extract some information from the instruction
|
||||
Value *Dst = CI->getArgOperand(0);
|
||||
Value *Src = CI->getArgOperand(1);
|
||||
|
@ -220,15 +147,6 @@ Value *LibCallSimplifier::emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Verify the "strncat" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 3 || FT->getReturnType() != B.getInt8PtrTy() ||
|
||||
FT->getParamType(0) != FT->getReturnType() ||
|
||||
FT->getParamType(1) != FT->getReturnType() ||
|
||||
!FT->getParamType(2)->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
// Extract some information from the instruction.
|
||||
Value *Dst = CI->getArgOperand(0);
|
||||
Value *Src = CI->getArgOperand(1);
|
||||
|
@ -263,13 +181,7 @@ Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Verify the "strchr" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || FT->getReturnType() != B.getInt8PtrTy() ||
|
||||
FT->getParamType(0) != FT->getReturnType() ||
|
||||
!FT->getParamType(1)->isIntegerTy(32))
|
||||
return nullptr;
|
||||
|
||||
Value *SrcStr = CI->getArgOperand(0);
|
||||
|
||||
// If the second operand is non-constant, see if we can compute the length
|
||||
|
@ -308,14 +220,6 @@ Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Verify the "strrchr" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || FT->getReturnType() != B.getInt8PtrTy() ||
|
||||
FT->getParamType(0) != FT->getReturnType() ||
|
||||
!FT->getParamType(1)->isIntegerTy(32))
|
||||
return nullptr;
|
||||
|
||||
Value *SrcStr = CI->getArgOperand(0);
|
||||
ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
|
||||
|
||||
|
@ -343,14 +247,6 @@ Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Verify the "strcmp" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || !FT->getReturnType()->isIntegerTy(32) ||
|
||||
FT->getParamType(0) != FT->getParamType(1) ||
|
||||
FT->getParamType(0) != B.getInt8PtrTy())
|
||||
return nullptr;
|
||||
|
||||
Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
|
||||
if (Str1P == Str2P) // strcmp(x,x) -> 0
|
||||
return ConstantInt::get(CI->getType(), 0);
|
||||
|
@ -384,15 +280,6 @@ Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Verify the "strncmp" function prototype.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 3 || !FT->getReturnType()->isIntegerTy(32) ||
|
||||
FT->getParamType(0) != FT->getParamType(1) ||
|
||||
FT->getParamType(0) != B.getInt8PtrTy() ||
|
||||
!FT->getParamType(2)->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
|
||||
if (Str1P == Str2P) // strncmp(x,x,n) -> 0
|
||||
return ConstantInt::get(CI->getType(), 0);
|
||||
|
@ -432,11 +319,6 @@ Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::strcpy))
|
||||
return nullptr;
|
||||
|
||||
Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
|
||||
if (Dst == Src) // strcpy(x,x) -> x
|
||||
return Src;
|
||||
|
@ -455,9 +337,6 @@ Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::stpcpy))
|
||||
return nullptr;
|
||||
|
||||
Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
|
||||
if (Dst == Src) { // stpcpy(x,x) -> x+strlen(x)
|
||||
Value *StrLen = emitStrLen(Src, B, DL, TLI);
|
||||
|
@ -482,9 +361,6 @@ Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::strncpy))
|
||||
return nullptr;
|
||||
|
||||
Value *Dst = CI->getArgOperand(0);
|
||||
Value *Src = CI->getArgOperand(1);
|
||||
Value *LenOp = CI->getArgOperand(2);
|
||||
|
@ -522,12 +398,6 @@ Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 1 || FT->getParamType(0) != B.getInt8PtrTy() ||
|
||||
!FT->getReturnType()->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
Value *Src = CI->getArgOperand(0);
|
||||
|
||||
// Constant folding: strlen("xyz") -> 3
|
||||
|
@ -609,13 +479,6 @@ Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrPBrk(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || FT->getParamType(0) != B.getInt8PtrTy() ||
|
||||
FT->getParamType(1) != FT->getParamType(0) ||
|
||||
FT->getReturnType() != FT->getParamType(0))
|
||||
return nullptr;
|
||||
|
||||
StringRef S1, S2;
|
||||
bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
|
||||
bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
|
||||
|
@ -643,13 +506,6 @@ Value *LibCallSimplifier::optimizeStrPBrk(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrTo(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) ||
|
||||
!FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isPointerTy())
|
||||
return nullptr;
|
||||
|
||||
Value *EndPtr = CI->getArgOperand(1);
|
||||
if (isa<ConstantPointerNull>(EndPtr)) {
|
||||
// With a null EndPtr, this function won't capture the main argument.
|
||||
|
@ -661,13 +517,6 @@ Value *LibCallSimplifier::optimizeStrTo(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrSpn(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || FT->getParamType(0) != B.getInt8PtrTy() ||
|
||||
FT->getParamType(1) != FT->getParamType(0) ||
|
||||
!FT->getReturnType()->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
StringRef S1, S2;
|
||||
bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
|
||||
bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
|
||||
|
@ -689,13 +538,6 @@ Value *LibCallSimplifier::optimizeStrSpn(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrCSpn(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || FT->getParamType(0) != B.getInt8PtrTy() ||
|
||||
FT->getParamType(1) != FT->getParamType(0) ||
|
||||
!FT->getReturnType()->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
StringRef S1, S2;
|
||||
bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
|
||||
bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
|
||||
|
@ -720,13 +562,6 @@ Value *LibCallSimplifier::optimizeStrCSpn(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeStrStr(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isPointerTy() ||
|
||||
!FT->getReturnType()->isPointerTy())
|
||||
return nullptr;
|
||||
|
||||
// fold strstr(x, x) -> x.
|
||||
if (CI->getArgOperand(0) == CI->getArgOperand(1))
|
||||
return B.CreateBitCast(CI->getArgOperand(0), CI->getType());
|
||||
|
@ -781,14 +616,6 @@ Value *LibCallSimplifier::optimizeStrStr(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isIntegerTy(32) ||
|
||||
!FT->getParamType(2)->isIntegerTy() ||
|
||||
!FT->getReturnType()->isPointerTy())
|
||||
return nullptr;
|
||||
|
||||
Value *SrcStr = CI->getArgOperand(0);
|
||||
ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
|
||||
ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
|
||||
|
@ -867,13 +694,6 @@ Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeMemCmp(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isPointerTy() ||
|
||||
!FT->getReturnType()->isIntegerTy(32))
|
||||
return nullptr;
|
||||
|
||||
Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1);
|
||||
|
||||
if (LHS == RHS) // memcmp(s,s,x) -> 0
|
||||
|
@ -942,11 +762,6 @@ Value *LibCallSimplifier::optimizeMemCmp(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::memcpy))
|
||||
return nullptr;
|
||||
|
||||
// memcpy(x, y, n) -> llvm.memcpy(x, y, n, 1)
|
||||
B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), 1);
|
||||
|
@ -954,11 +769,6 @@ Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::memmove))
|
||||
return nullptr;
|
||||
|
||||
// memmove(x, y, n) -> llvm.memmove(x, y, n, 1)
|
||||
B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), 1);
|
||||
|
@ -1005,20 +815,10 @@ static Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B,
|
|||
// Is the inner call really malloc()?
|
||||
Function *InnerCallee = Malloc->getCalledFunction();
|
||||
LibFunc::Func Func;
|
||||
if (!TLI.getLibFunc(InnerCallee->getName(), Func) || !TLI.has(Func) ||
|
||||
if (!TLI.getLibFunc(*InnerCallee, Func) || !TLI.has(Func) ||
|
||||
Func != LibFunc::malloc)
|
||||
return nullptr;
|
||||
|
||||
// Matching the name is not good enough. Make sure the parameter and return
|
||||
// type match the standard library signature.
|
||||
FunctionType *FT = InnerCallee->getFunctionType();
|
||||
if (FT->getNumParams() != 1 || !FT->getParamType(0)->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
auto *RetType = dyn_cast<PointerType>(FT->getReturnType());
|
||||
if (!RetType || !RetType->getPointerElementType()->isIntegerTy(8))
|
||||
return nullptr;
|
||||
|
||||
// The memset must cover the same number of bytes that are malloc'd.
|
||||
if (Memset->getArgOperand(2) != Malloc->getArgOperand(0))
|
||||
return nullptr;
|
||||
|
@ -1041,11 +841,6 @@ static Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B,
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::memset))
|
||||
return nullptr;
|
||||
|
||||
if (auto *Calloc = foldMallocMemset(CI, B, *TLI))
|
||||
return Calloc;
|
||||
|
||||
|
@ -1081,34 +876,12 @@ static Value *valueHasFloatPrecision(Value *Val) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/// Any floating-point library function that we're trying to simplify will have
|
||||
/// a signature of the form: fptype foo(fptype param1, fptype param2, ...).
|
||||
/// CheckDoubleTy indicates that 'fptype' must be 'double'.
|
||||
static bool matchesFPLibFunctionSignature(const Function *F, unsigned NumParams,
|
||||
bool CheckDoubleTy) {
|
||||
FunctionType *FT = F->getFunctionType();
|
||||
if (FT->getNumParams() != NumParams)
|
||||
return false;
|
||||
|
||||
// The return type must match what we're looking for.
|
||||
Type *RetTy = FT->getReturnType();
|
||||
if (CheckDoubleTy ? !RetTy->isDoubleTy() : !RetTy->isFloatingPointTy())
|
||||
return false;
|
||||
|
||||
// Each parameter must match the return type, and therefore, match every other
|
||||
// parameter too.
|
||||
for (const Type *ParamTy : FT->params())
|
||||
if (ParamTy != RetTy)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Shrink double -> float for unary functions like 'floor'.
|
||||
static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B,
|
||||
bool CheckRetType) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 1, true))
|
||||
// We know this libcall has a valid prototype, but we don't know which.
|
||||
if (!CI->getType()->isDoubleTy())
|
||||
return nullptr;
|
||||
|
||||
if (CheckRetType) {
|
||||
|
@ -1146,7 +919,8 @@ static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B,
|
|||
/// Shrink double -> float for binary functions like 'fmin/fmax'.
|
||||
static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 2, true))
|
||||
// We know this libcall has a valid prototype, but we don't know which.
|
||||
if (!CI->getType()->isDoubleTy())
|
||||
return nullptr;
|
||||
|
||||
// If this is something like 'fmin((double)floatval1, (double)floatval2)',
|
||||
|
@ -1172,9 +946,6 @@ static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeCos(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 1, false))
|
||||
return nullptr;
|
||||
|
||||
Value *Ret = nullptr;
|
||||
StringRef Name = Callee->getName();
|
||||
if (UnsafeFPShrink && Name == "cos" && hasFloatVersion(Name))
|
||||
|
@ -1216,9 +987,6 @@ static Value *getPow(Value *InnerChain[33], unsigned Exp, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 2, false))
|
||||
return nullptr;
|
||||
|
||||
Value *Ret = nullptr;
|
||||
StringRef Name = Callee->getName();
|
||||
if (UnsafeFPShrink && Name == "pow" && hasFloatVersion(Name))
|
||||
|
@ -1337,9 +1105,6 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 1, false))
|
||||
return nullptr;
|
||||
|
||||
Value *Ret = nullptr;
|
||||
StringRef Name = Callee->getName();
|
||||
if (UnsafeFPShrink && Name == "exp2" && hasFloatVersion(Name))
|
||||
|
@ -1385,9 +1150,6 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeFabs(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 1, false))
|
||||
return nullptr;
|
||||
|
||||
Value *Ret = nullptr;
|
||||
StringRef Name = Callee->getName();
|
||||
if (Name == "fabs" && hasFloatVersion(Name))
|
||||
|
@ -1405,9 +1167,6 @@ Value *LibCallSimplifier::optimizeFabs(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 2, false))
|
||||
return nullptr;
|
||||
|
||||
// If we can shrink the call to a float function rather than a double
|
||||
// function, do that first.
|
||||
StringRef Name = Callee->getName();
|
||||
|
@ -1445,9 +1204,6 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 1, false))
|
||||
return nullptr;
|
||||
|
||||
Value *Ret = nullptr;
|
||||
StringRef Name = Callee->getName();
|
||||
if (UnsafeFPShrink && hasFloatVersion(Name))
|
||||
|
@ -1493,9 +1249,6 @@ Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 1, false))
|
||||
return nullptr;
|
||||
|
||||
Value *Ret = nullptr;
|
||||
if (TLI->has(LibFunc::sqrtf) && (Callee->getName() == "sqrt" ||
|
||||
Callee->getIntrinsicID() == Intrinsic::sqrt))
|
||||
|
@ -1563,9 +1316,6 @@ Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) {
|
|||
// TODO: Generalize to handle any trig function and its inverse.
|
||||
Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!matchesFPLibFunctionSignature(Callee, 1, false))
|
||||
return nullptr;
|
||||
|
||||
Value *Ret = nullptr;
|
||||
StringRef Name = Callee->getName();
|
||||
if (UnsafeFPShrink && Name == "tan" && hasFloatVersion(Name))
|
||||
|
@ -1594,19 +1344,11 @@ Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
static bool isTrigLibCall(CallInst *CI) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
|
||||
// We can only hope to do anything useful if we can ignore things like errno
|
||||
// and floating-point exceptions.
|
||||
bool AttributesSafe =
|
||||
CI->hasFnAttr(Attribute::NoUnwind) && CI->hasFnAttr(Attribute::ReadNone);
|
||||
|
||||
// Other than that we need float(float) or double(double)
|
||||
return AttributesSafe && FT->getNumParams() == 1 &&
|
||||
FT->getReturnType() == FT->getParamType(0) &&
|
||||
(FT->getParamType(0)->isFloatTy() ||
|
||||
FT->getParamType(0)->isDoubleTy());
|
||||
// We already checked the prototype.
|
||||
return CI->hasFnAttr(Attribute::NoUnwind) &&
|
||||
CI->hasFnAttr(Attribute::ReadNone);
|
||||
}
|
||||
|
||||
static void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg,
|
||||
|
@ -1709,7 +1451,7 @@ void LibCallSimplifier::classifyArgUse(
|
|||
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
LibFunc::Func Func;
|
||||
if (!Callee || !TLI->getLibFunc(Callee->getName(), Func) || !TLI->has(Func) ||
|
||||
if (!Callee || !TLI->getLibFunc(*Callee, Func) || !TLI->has(Func) ||
|
||||
!isTrigLibCall(CI))
|
||||
return;
|
||||
|
||||
|
@ -1740,16 +1482,8 @@ void LibCallSimplifier::replaceTrigInsts(SmallVectorImpl<CallInst *> &Calls,
|
|||
// Integer Library Call Optimizations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static bool checkIntUnaryReturnAndParam(Function *Callee) {
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
return FT->getNumParams() == 1 && FT->getReturnType()->isIntegerTy(32) &&
|
||||
FT->getParamType(0)->isIntegerTy();
|
||||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
if (!checkIntUnaryReturnAndParam(Callee))
|
||||
return nullptr;
|
||||
Value *Op = CI->getArgOperand(0);
|
||||
|
||||
// Constant fold.
|
||||
|
@ -1773,13 +1507,6 @@ Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeAbs(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
// We require integer(integer) where the types agree.
|
||||
if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
|
||||
FT->getParamType(0) != FT->getReturnType())
|
||||
return nullptr;
|
||||
|
||||
// abs(x) -> x >s -1 ? x : -x
|
||||
Value *Op = CI->getArgOperand(0);
|
||||
Value *Pos =
|
||||
|
@ -1789,9 +1516,6 @@ Value *LibCallSimplifier::optimizeAbs(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilder<> &B) {
|
||||
if (!checkIntUnaryReturnAndParam(CI->getCalledFunction()))
|
||||
return nullptr;
|
||||
|
||||
// isdigit(c) -> (c-'0') <u 10
|
||||
Value *Op = CI->getArgOperand(0);
|
||||
Op = B.CreateSub(Op, B.getInt32('0'), "isdigittmp");
|
||||
|
@ -1800,9 +1524,6 @@ Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilder<> &B) {
|
||||
if (!checkIntUnaryReturnAndParam(CI->getCalledFunction()))
|
||||
return nullptr;
|
||||
|
||||
// isascii(c) -> c <u 128
|
||||
Value *Op = CI->getArgOperand(0);
|
||||
Op = B.CreateICmpULT(Op, B.getInt32(128), "isascii");
|
||||
|
@ -1810,9 +1531,6 @@ Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeToAscii(CallInst *CI, IRBuilder<> &B) {
|
||||
if (!checkIntUnaryReturnAndParam(CI->getCalledFunction()))
|
||||
return nullptr;
|
||||
|
||||
// toascii(c) -> c & 0x7f
|
||||
return B.CreateAnd(CI->getArgOperand(0),
|
||||
ConstantInt::get(CI->getType(), 0x7F));
|
||||
|
@ -1826,6 +1544,7 @@ static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg);
|
|||
|
||||
Value *LibCallSimplifier::optimizeErrorReporting(CallInst *CI, IRBuilder<> &B,
|
||||
int StreamArg) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Error reporting calls should be cold, mark them as such.
|
||||
// This applies even to non-builtin calls: it is only a hint and applies to
|
||||
// functions that the frontend might not understand as builtins.
|
||||
|
@ -1834,8 +1553,6 @@ Value *LibCallSimplifier::optimizeErrorReporting(CallInst *CI, IRBuilder<> &B,
|
|||
// Improving Static Branch Prediction in a Compiler
|
||||
// Brian L. Deitrich, Ben-Chung Cheng, Wen-mei W. Hwu
|
||||
// Proceedings of PACT'98, Oct. 1998, IEEE
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!CI->hasFnAttr(Attribute::Cold) &&
|
||||
isReportingError(Callee, CI, StreamArg)) {
|
||||
CI->addAttribute(AttributeSet::FunctionIndex, Attribute::Cold);
|
||||
|
@ -1921,12 +1638,7 @@ Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilder<> &B) {
|
|||
Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilder<> &B) {
|
||||
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Require one fixed pointer argument and an integer/void result.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!(FT->getReturnType()->isIntegerTy() || FT->getReturnType()->isVoidTy()))
|
||||
return nullptr;
|
||||
|
||||
if (Value *V = optimizePrintFString(CI, B)) {
|
||||
return V;
|
||||
}
|
||||
|
@ -2007,13 +1719,7 @@ Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Require two fixed pointer arguments and an integer result.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isPointerTy() ||
|
||||
!FT->getReturnType()->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
if (Value *V = optimizeSPrintFString(CI, B)) {
|
||||
return V;
|
||||
}
|
||||
|
@ -2083,13 +1789,7 @@ Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI, IRBuilder<> &B) {
|
|||
|
||||
Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Require two fixed paramters as pointers and integer result.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isPointerTy() ||
|
||||
!FT->getReturnType()->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
if (Value *V = optimizeFPrintFString(CI, B)) {
|
||||
return V;
|
||||
}
|
||||
|
@ -2111,16 +1811,6 @@ Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilder<> &B) {
|
|||
Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilder<> &B) {
|
||||
optimizeErrorReporting(CI, B, 3);
|
||||
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Require a pointer, an integer, an integer, a pointer, returning integer.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 4 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isIntegerTy() ||
|
||||
!FT->getParamType(2)->isIntegerTy() ||
|
||||
!FT->getParamType(3)->isPointerTy() ||
|
||||
!FT->getReturnType()->isIntegerTy())
|
||||
return nullptr;
|
||||
|
||||
// Get the element size and count.
|
||||
ConstantInt *SizeC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
|
||||
ConstantInt *CountC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
|
||||
|
@ -2146,12 +1836,8 @@ Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilder<> &B) {
|
|||
Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilder<> &B) {
|
||||
optimizeErrorReporting(CI, B, 1);
|
||||
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
// Require two pointers. Also, we can't optimize if return value is used.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!FT->getParamType(1)->isPointerTy() || !CI->use_empty())
|
||||
// We can't optimize if return value is used.
|
||||
if (!CI->use_empty())
|
||||
return nullptr;
|
||||
|
||||
// fputs(s,F) --> fwrite(s,1,strlen(s),F)
|
||||
|
@ -2167,13 +1853,6 @@ Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilder<> &B) {
|
|||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
// Require one fixed pointer argument and an integer/void result.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!(FT->getReturnType()->isIntegerTy() || FT->getReturnType()->isVoidTy()))
|
||||
return nullptr;
|
||||
|
||||
// Check for a constant string.
|
||||
StringRef Str;
|
||||
if (!getConstantStringInfo(CI->getArgOperand(0), Str))
|
||||
|
@ -2203,10 +1882,8 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI,
|
|||
IRBuilder<> &Builder) {
|
||||
LibFunc::Func Func;
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
StringRef FuncName = Callee->getName();
|
||||
|
||||
// Check for string/memory library functions.
|
||||
if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func)) {
|
||||
if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) {
|
||||
// Make sure we never change the calling convention.
|
||||
assert((ignoreCallingConv(Func) ||
|
||||
CI->getCallingConv() == llvm::CallingConv::C) &&
|
||||
|
@ -2324,7 +2001,7 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
|
|||
}
|
||||
|
||||
// Then check for known library functions.
|
||||
if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func)) {
|
||||
if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) {
|
||||
// We never change the calling convention.
|
||||
if (!ignoreCallingConv(Func) && !isCallingConvC)
|
||||
return nullptr;
|
||||
|
@ -2528,11 +2205,6 @@ bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(CallInst *CI,
|
|||
|
||||
Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI,
|
||||
IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::memcpy_chk))
|
||||
return nullptr;
|
||||
|
||||
if (isFortifiedCallFoldable(CI, 3, 2, false)) {
|
||||
B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), 1);
|
||||
|
@ -2543,11 +2215,6 @@ Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI,
|
|||
|
||||
Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI,
|
||||
IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::memmove_chk))
|
||||
return nullptr;
|
||||
|
||||
if (isFortifiedCallFoldable(CI, 3, 2, false)) {
|
||||
B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), 1);
|
||||
|
@ -2558,11 +2225,6 @@ Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI,
|
|||
|
||||
Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI,
|
||||
IRBuilder<> &B) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::memset_chk))
|
||||
return nullptr;
|
||||
|
||||
// TODO: Try foldMallocMemset() here.
|
||||
|
||||
if (isFortifiedCallFoldable(CI, 3, 2, false)) {
|
||||
|
@ -2579,10 +2241,6 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
|
|||
Function *Callee = CI->getCalledFunction();
|
||||
StringRef Name = Callee->getName();
|
||||
const DataLayout &DL = CI->getModule()->getDataLayout();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, Func))
|
||||
return nullptr;
|
||||
|
||||
Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1),
|
||||
*ObjSize = CI->getArgOperand(2);
|
||||
|
||||
|
@ -2623,9 +2281,6 @@ Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,
|
|||
LibFunc::Func Func) {
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
StringRef Name = Callee->getName();
|
||||
|
||||
if (!checkStringCopyLibFuncSignature(Callee, Func))
|
||||
return nullptr;
|
||||
if (isFortifiedCallFoldable(CI, 3, 2, false)) {
|
||||
Value *Ret = emitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), B, TLI, Name.substr(2, 7));
|
||||
|
@ -2650,15 +2305,15 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) {
|
|||
|
||||
LibFunc::Func Func;
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
StringRef FuncName = Callee->getName();
|
||||
|
||||
SmallVector<OperandBundleDef, 2> OpBundles;
|
||||
CI->getOperandBundlesAsDefs(OpBundles);
|
||||
IRBuilder<> Builder(CI, /*FPMathTag=*/nullptr, OpBundles);
|
||||
bool isCallingConvC = CI->getCallingConv() == llvm::CallingConv::C;
|
||||
|
||||
// First, check that this is a known library functions.
|
||||
if (!TLI->getLibFunc(FuncName, Func))
|
||||
// First, check that this is a known library functions and that the prototype
|
||||
// is correct.
|
||||
if (!TLI->getLibFunc(*Callee, Func))
|
||||
return nullptr;
|
||||
|
||||
// We never change the calling convention.
|
||||
|
|
Loading…
Reference in New Issue