Index: include/llvm/Analysis/TargetLibraryInfo.h =================================================================== --- include/llvm/Analysis/TargetLibraryInfo.h +++ include/llvm/Analysis/TargetLibraryInfo.h @@ -71,6 +71,15 @@ /// on VectorFnName rather than ScalarFnName. std::vector ScalarDescs; + /// The size (in bits) of a pointer in addresspace 0. + /// Used to verify the integer width of size_t types, for, e.g., strlen. + /// If 0 (unknown), these types only need to be integers: width isn't checked. + unsigned PointerSize = 0; + + /// 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; + public: /// List of known vector-functions libraries. /// @@ -99,6 +108,13 @@ /// 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 +211,10 @@ 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; Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -541,22 +541,6 @@ 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(MemsetType->getParamType(0)) && - isa(MemsetType->getParamType(1)) && - isa(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 @@ // 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; Index: lib/Analysis/MemoryLocation.cpp =================================================================== --- lib/Analysis/MemoryLocation.cpp +++ lib/Analysis/MemoryLocation.cpp @@ -90,23 +90,6 @@ 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(MemsetType->getParamType(0)) && - isa(MemsetType->getParamType(1)) && - isa(MemsetType->getParamType(2))) - return true; - } - - return false; -} - MemoryLocation MemoryLocation::getForArgument(ImmutableCallSite CS, unsigned ArgIdx, const TargetLibraryInfo &TLI) { @@ -159,8 +142,9 @@ // 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) Index: lib/Analysis/TargetLibraryInfo.cpp =================================================================== --- lib/Analysis/TargetLibraryInfo.cpp +++ lib/Analysis/TargetLibraryInfo.cpp @@ -406,6 +406,17 @@ TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary); } +/// Figure out the pointer integer size (for things like size_t) from the arch. +static unsigned getTriplePointerBitWidth(const Triple &T) { + if (T.isArch64Bit()) + return 64; + if (T.isArch32Bit()) + return 32; + if (T.isArch16Bit()) + return 16; + return 0; +} + TargetLibraryInfoImpl::TargetLibraryInfoImpl() { // Default to everything being available. memset(AvailableArray, -1, sizeof(AvailableArray)); @@ -418,17 +429,18 @@ memset(AvailableArray, -1, sizeof(AvailableArray)); initialize(*this, T, StandardNames); + PointerSize = getTriplePointerBitWidth(T); } TargetLibraryInfoImpl::TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI) - : CustomNames(TLI.CustomNames) { + : CustomNames(TLI.CustomNames), PointerSize(TLI.PointerSize) { memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); VectorDescs = TLI.VectorDescs; ScalarDescs = TLI.ScalarDescs; } TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI) - : CustomNames(std::move(TLI.CustomNames)) { + : CustomNames(std::move(TLI.CustomNames)), PointerSize(TLI.PointerSize) { std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray), AvailableArray); VectorDescs = TLI.VectorDescs; @@ -479,6 +491,533 @@ return false; } +bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, + LibFunc::Func F) const { + LLVMContext &Ctx = FTy.getContext(); + Type *PCharTy = Type::getInt8PtrTy(Ctx); + auto IsIntPtrTy = [this](Type *Ty) { + return PointerSize ? Ty->isIntegerTy(PointerSize) : 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 (!IsIntPtrTy(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 (!IsIntPtrTy(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 (!IsIntPtrTy(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() && + IsIntPtrTy(FTy.getParamType(2))); + + case LibFunc::memset_chk: + --NumParams; + if (!IsIntPtrTy(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() && + IsIntPtrTy(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(FTy.getParamType(0)) && + isa(FTy.getParamType(1)) && + isa(FTy.getParamType(2))); + + // int __nvvm_reflect(const char *); + case LibFunc::nvvm_reflect: + return (NumParams == 1 && isa(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 { + return getLibFunc(FDecl.getName(), F) && + isValidProtoForLibFunc(*FDecl.getFunctionType(), F); +} + void TargetLibraryInfoImpl::disableAllFunctions() { memset(AvailableArray, 0, sizeof(AvailableArray)); } Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -2242,46 +2242,6 @@ 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 @@ // 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 @@ 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; } Index: lib/Transforms/IPO/GlobalOpt.cpp =================================================================== --- lib/Transforms/IPO/GlobalOpt.cpp +++ lib/Transforms/IPO/GlobalOpt.cpp @@ -2412,23 +2412,16 @@ } 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; Index: lib/Transforms/IPO/InferFunctionAttrs.cpp =================================================================== --- lib/Transforms/IPO/InferFunctionAttrs.cpp +++ lib/Transforms/IPO/InferFunctionAttrs.cpp @@ -106,25 +106,19 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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(FTy->getParamType(0)) || - !isa(FTy->getParamType(1)) || - !isa(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(FTy->getParamType(0))) - return false; - Changed |= setDoesNotAccessMemory(F); Changed |= setDoesNotThrow(F); return Changed; Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -103,84 +103,11 @@ } } -/// \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::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::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::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(CI->getArgOperand(1)); @@ -343,14 +247,6 @@ } 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::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::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::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::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::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::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::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(EndPtr)) { // With a null EndPtr, this function won't capture the main argument. @@ -661,13 +517,6 @@ } 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::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::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::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(CI->getArgOperand(1)); ConstantInt *LenC = dyn_cast(CI->getArgOperand(2)); @@ -867,13 +694,6 @@ } 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::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::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 @@ // 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(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 @@ } 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 @@ 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 @@ /// 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 @@ 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 @@ 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::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::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::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::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::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 @@ // 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 @@ } 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 @@ 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 @@ // 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::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::optimizeIsDigit(CallInst *CI, IRBuilder<> &B) { - if (!checkIntUnaryReturnAndParam(CI->getCalledFunction())) - return nullptr; - // isdigit(c) -> (c-'0') getArgOperand(0); Op = B.CreateSub(Op, B.getInt32('0'), "isdigittmp"); @@ -1800,9 +1524,6 @@ } Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilder<> &B) { - if (!checkIntUnaryReturnAndParam(CI->getCalledFunction())) - return nullptr; - // isascii(c) -> c getArgOperand(0); Op = B.CreateICmpULT(Op, B.getInt32(128), "isascii"); @@ -1810,9 +1531,6 @@ } 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 @@ 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 @@ // 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::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::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::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::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(CI->getArgOperand(1)); ConstantInt *CountC = dyn_cast(CI->getArgOperand(2)); @@ -2146,12 +1836,8 @@ 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::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 @@ 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 @@ } // 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 @@ 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::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::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 @@ 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 @@ 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 @@ LibFunc::Func Func; Function *Callee = CI->getCalledFunction(); - StringRef FuncName = Callee->getName(); SmallVector 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.