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,11 +178,32 @@ 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 //===----------------------------------------------------------------------===// Value *LibCallSimplifier::optimizeStrCat(CallInst *CI, IRBuilder<> &B) { + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; // Extract some information from the instruction Value *Dst = CI->getArgOperand(0); Value *Src = CI->getArgOperand(1); @@ -244,6 +265,13 @@ if (SrcLen == 0 || Len == 0) return Dst; + // Non-zero length case + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + // We don't optimize this case. if (Len < SrcLen) return nullptr; @@ -365,6 +393,12 @@ TLI); } + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + return nullptr; } @@ -424,6 +458,13 @@ TLI); } + // Non-zero length case + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + return nullptr; } @@ -432,6 +473,12 @@ if (Dst == Src) // strcpy(x,x) -> x return Src; + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); if (Len == 0) @@ -495,6 +542,13 @@ if (Len == 0) return Dst; // strncpy(x, y, 0) -> x + // Non-zero length case + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + // Let strncpy handle the zero padding if (Len > SrcLen + 1) return nullptr; @@ -597,7 +651,16 @@ } Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) { - return optimizeStringLength(CI, B, 8); + if (Value *V = optimizeStringLength(CI, B, 8)) + return V; + + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + if (AttrChanged) + CI->dump(); + if (AttrChanged) + return CI; + return nullptr; } Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilder<> &B) { @@ -744,6 +807,12 @@ Value *StrChr = emitStrChr(CI->getArgOperand(0), ToFindStr[0], B, TLI); return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : nullptr; } + + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; return nullptr; } @@ -905,17 +974,47 @@ return ConstantInt::get(CI->getType(), Ret); } + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + 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; + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + 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; + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; + 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 +1067,18 @@ 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; + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + if (AttrChanged) + return CI; + return nullptr; + } + if (auto *Calloc = foldMallocMemset(CI, B)) return Calloc; @@ -1880,7 +1990,14 @@ if (!getConstantStringInfo(CI->getArgOperand(0), Str)) return nullptr; - return convertStrToNumber(CI, Str, 10); + if (Value *V = convertStrToNumber(CI, Str, 10)) + return V; + + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + if (AttrChanged) + return CI; + return nullptr; } Value *LibCallSimplifier::optimizeStrtol(CallInst *CI, IRBuilder<> &B) { @@ -1891,10 +2008,14 @@ 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; + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + if (AttrChanged) + return CI; return nullptr; } @@ -2016,6 +2137,11 @@ B.Insert(New); return New; } + + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + if (AttrChanged) + return CI; return nullptr; } @@ -2095,6 +2221,12 @@ B.Insert(New); return New; } + + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + AttrChanged |= setNonNullParam(CI, 1); + if (AttrChanged) + return CI; return nullptr; } @@ -2182,6 +2314,10 @@ return V; } + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 2); + if (AttrChanged) + return CI; return nullptr; } @@ -2363,6 +2499,10 @@ return B.CreateIntCast(Res, CI->getType(), true); } + bool AttrChanged = false; + AttrChanged |= setNonNullParam(CI, 0); + if (AttrChanged) + return CI; return nullptr; } @@ -2574,6 +2714,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; }