Index: include/llvm/Transforms/Utils/SimplifyLibCalls.h =================================================================== --- include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -134,9 +134,9 @@ Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemChr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B); - Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); - Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); - Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); + Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); + Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); Value *optimizeRealloc(CallInst *CI, IRBuilder<> &B); Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B); // Wrapper for all String/Memory Library Call Optimizations Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -178,6 +178,22 @@ return true; } +static bool isPositiveSize(Value *Arg) { + return isa(Arg) && cast(Arg)->getZExtValue() > 0; +} + +static bool setNonNullParam(CallInst *CI, unsigned ArgNo) { + Function *F = CI->getFunction(); + if (!F || F->nullPointerIsDefined()) + return false; + + if (!CI->paramHasAttr(ArgNo, Attribute::NonNull)) { + CI->addParamAttr(ArgNo, Attribute::NonNull); + return true; + } + return false; +} + //===----------------------------------------------------------------------===// // String and Memory Library Call Optimizations //===----------------------------------------------------------------------===// @@ -187,6 +203,8 @@ Value *Dst = CI->getArgOperand(0); Value *Src = CI->getArgOperand(1); + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); if (Len == 0) @@ -226,6 +244,7 @@ Value *Src = CI->getArgOperand(1); uint64_t Len; + setNonNullParam(CI, 0); // We don't do anything if length is not constant. if (ConstantInt *LengthArg = dyn_cast(CI->getArgOperand(2))) Len = LengthArg->getZExtValue(); @@ -244,6 +263,9 @@ if (SrcLen == 0 || Len == 0) return Dst; + // Non-zero length case + setNonNullParam(CI, 1); + // We don't optimize this case. if (Len < SrcLen) return nullptr; @@ -365,6 +387,8 @@ TLI); } + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -424,6 +448,9 @@ TLI); } + // Non-zero length case + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -432,6 +459,8 @@ if (Dst == Src) // strcpy(x,x) -> x return Src; + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); if (Len == 0) @@ -474,6 +503,7 @@ Value *Src = CI->getArgOperand(1); Value *LenOp = CI->getArgOperand(2); + setNonNullParam(CI, 0); // See if we can get the length of the input string. uint64_t SrcLen = GetStringLength(Src); if (SrcLen == 0) @@ -495,6 +525,10 @@ if (Len == 0) return Dst; // strncpy(x, y, 0) -> x + // Non-zero length case + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); + // Let strncpy handle the zero padding if (Len > SrcLen + 1) return nullptr; @@ -597,7 +631,11 @@ } Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) { - return optimizeStringLength(CI, B, 8); + if (Value *V = optimizeStringLength(CI, B, 8)) + return V; + + setNonNullParam(CI, 0); + return nullptr; } Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilder<> &B) { @@ -744,6 +782,9 @@ Value *StrChr = emitStrChr(CI->getArgOperand(0), ToFindStr[0], B, TLI); return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : nullptr; } + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -905,17 +946,39 @@ return ConstantInt::get(CI->getType(), Ret); } + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } -Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B, + bool isIntrinsic) { + if (isIntrinsic) { + if (!isPositiveSize(CI->getArgOperand(2))) + return nullptr; + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); + return nullptr; + } + // memcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n) B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, CI->getArgOperand(2)); return CI->getArgOperand(0); } -Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B, + bool isIntrinsic) { + if (isIntrinsic) { + if (!isPositiveSize(CI->getArgOperand(2))) + return nullptr; + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); + return nullptr; + } + // memmove(x, y, n) -> llvm.memmove(align 1 x, align 1 y, n) B.CreateMemMove(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, CI->getArgOperand(2)); @@ -968,7 +1031,16 @@ return Calloc; } -Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B, + bool isIntrinsic) { + if (isIntrinsic) { + if (!isPositiveSize(CI->getArgOperand(2))) + return nullptr; + + setNonNullParam(CI, 0); + return nullptr; + } + if (auto *Calloc = foldMallocMemset(CI, B)) return Calloc; @@ -1880,7 +1952,11 @@ if (!getConstantStringInfo(CI->getArgOperand(0), Str)) return nullptr; - return convertStrToNumber(CI, Str, 10); + if (Value *V = convertStrToNumber(CI, Str, 10)) + return V; + + setNonNullParam(CI, 0); + return nullptr; } Value *LibCallSimplifier::optimizeStrtol(CallInst *CI, IRBuilder<> &B) { @@ -1891,10 +1967,11 @@ if (!isa(CI->getArgOperand(1))) return nullptr; - if (ConstantInt *CInt = dyn_cast(CI->getArgOperand(2))) { - return convertStrToNumber(CI, Str, CInt->getSExtValue()); - } + if (ConstantInt *CInt = dyn_cast(CI->getArgOperand(2))) + if (Value *V = convertStrToNumber(CI, Str, CInt->getSExtValue())) + return V; + setNonNullParam(CI, 0); return nullptr; } @@ -2016,6 +2093,8 @@ B.Insert(New); return New; } + + setNonNullParam(CI, 0); return nullptr; } @@ -2095,6 +2174,9 @@ B.Insert(New); return New; } + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -2182,6 +2264,7 @@ return V; } + setNonNullParam(CI, 2); return nullptr; } @@ -2363,6 +2446,7 @@ return B.CreateIntCast(Res, CI->getType(), true); } + setNonNullParam(CI, 0); return nullptr; } @@ -2574,6 +2658,12 @@ case Intrinsic::sqrt: return optimizeSqrt(CI, Builder); // TODO: Use foldMallocMemset() with memset intrinsic. + case Intrinsic::memset: + return optimizeMemSet(CI, Builder, true); + case Intrinsic::memcpy: + return optimizeMemCpy(CI, Builder, true); + case Intrinsic::memmove: + return optimizeMemMove(CI, Builder, true); default: return nullptr; }