diff options
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/IPO/GlobalOpt.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp | 242 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 379 |
3 files changed, 23 insertions, 615 deletions
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 26c1e09876d..05de965c098 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -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; diff --git a/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp b/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp index 70d53abcf99..3c46c4968cc 100644 --- a/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp @@ -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; diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 104a82ce2a5..42b3cef470c 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -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. |