diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 602 |
1 files changed, 390 insertions, 212 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 245f2d4e442a..20f18322d43c 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -33,6 +33,8 @@ #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/SizeOpts.h" +#include <cmath> + using namespace llvm; using namespace PatternMatch; @@ -245,13 +247,14 @@ static void annotateNonNullNoUndefBasedOnAccess(CallInst *CI, if (!CI->paramHasAttr(ArgNo, Attribute::NoUndef)) CI->addParamAttr(ArgNo, Attribute::NoUndef); - if (CI->paramHasAttr(ArgNo, Attribute::NonNull)) - continue; - unsigned AS = CI->getArgOperand(ArgNo)->getType()->getPointerAddressSpace(); - if (llvm::NullPointerIsDefined(F, AS)) - continue; + if (!CI->paramHasAttr(ArgNo, Attribute::NonNull)) { + unsigned AS = + CI->getArgOperand(ArgNo)->getType()->getPointerAddressSpace(); + if (llvm::NullPointerIsDefined(F, AS)) + continue; + CI->addParamAttr(ArgNo, Attribute::NonNull); + } - CI->addParamAttr(ArgNo, Attribute::NonNull); annotateDereferenceableBytes(CI, ArgNo, 1); } } @@ -285,6 +288,13 @@ static Value *copyFlags(const CallInst &Old, Value *New) { return New; } +static Value *mergeAttributesAndFlags(CallInst *NewCI, const CallInst &Old) { + NewCI->setAttributes(AttributeList::get( + NewCI->getContext(), {NewCI->getAttributes(), Old.getAttributes()})); + NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); + return copyFlags(Old, NewCI); +} + // Helper to avoid truncating the length if size_t is 32-bits. static StringRef substr(StringRef Str, uint64_t Len) { return Len >= Str.size() ? Str : Str.substr(0, Len); @@ -424,14 +434,16 @@ Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilderBase &B) { Function *Callee = CI->getCalledFunction(); FunctionType *FT = Callee->getFunctionType(); - if (!FT->getParamType(1)->isIntegerTy(32)) // memchr needs i32. + unsigned IntBits = TLI->getIntSize(); + if (!FT->getParamType(1)->isIntegerTy(IntBits)) // memchr needs 'int'. return nullptr; - return copyFlags( - *CI, - emitMemChr(SrcStr, CharVal, // include nul. - ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len), B, - DL, TLI)); + unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule()); + Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits); + return copyFlags(*CI, + emitMemChr(SrcStr, CharVal, // include nul. + ConstantInt::get(SizeTTy, Len), B, + DL, TLI)); } if (CharC->isZero()) { @@ -478,11 +490,13 @@ Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilderBase &B) { return nullptr; } + unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule()); + Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits); + // Try to expand strrchr to the memrchr nonstandard extension if it's // available, or simply fail otherwise. uint64_t NBytes = Str.size() + 1; // Include the terminating nul. - Type *IntPtrType = DL.getIntPtrType(CI->getContext()); - Value *Size = ConstantInt::get(IntPtrType, NBytes); + Value *Size = ConstantInt::get(SizeTTy, NBytes); return copyFlags(*CI, emitMemRChr(SrcStr, CharVal, Size, B, DL, TLI)); } @@ -497,7 +511,8 @@ Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilderBase &B) { // strcmp(x, y) -> cnst (if both x and y are constant strings) if (HasStr1 && HasStr2) - return ConstantInt::get(CI->getType(), Str1.compare(Str2)); + return ConstantInt::get(CI->getType(), + std::clamp(Str1.compare(Str2), -1, 1)); if (HasStr1 && Str1.empty()) // strcmp("", x) -> -*x return B.CreateNeg(B.CreateZExt( @@ -581,7 +596,8 @@ Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilderBase &B) { // Avoid truncating the 64-bit Length to 32 bits in ILP32. StringRef SubStr1 = substr(Str1, Length); StringRef SubStr2 = substr(Str2, Length); - return ConstantInt::get(CI->getType(), SubStr1.compare(SubStr2)); + return ConstantInt::get(CI->getType(), + std::clamp(SubStr1.compare(SubStr2), -1, 1)); } if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> -*x @@ -652,9 +668,7 @@ Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilderBase &B) { CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len)); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return Dst; } @@ -686,44 +700,145 @@ Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilderBase &B) { // We have enough information to now generate the memcpy call to do the // copy for us. Make a memcpy to copy the nul byte with align = 1. CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), LenV); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return DstEnd; } -Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilderBase &B) { +// Optimize a call to size_t strlcpy(char*, const char*, size_t). + +Value *LibCallSimplifier::optimizeStrLCpy(CallInst *CI, IRBuilderBase &B) { + Value *Size = CI->getArgOperand(2); + if (isKnownNonZero(Size, DL)) + // Like snprintf, the function stores into the destination only when + // the size argument is nonzero. + annotateNonNullNoUndefBasedOnAccess(CI, 0); + // The function reads the source argument regardless of Size (it returns + // its length). + annotateNonNullNoUndefBasedOnAccess(CI, 1); + + uint64_t NBytes; + if (ConstantInt *SizeC = dyn_cast<ConstantInt>(Size)) + NBytes = SizeC->getZExtValue(); + else + return nullptr; + + Value *Dst = CI->getArgOperand(0); + Value *Src = CI->getArgOperand(1); + if (NBytes <= 1) { + if (NBytes == 1) + // For a call to strlcpy(D, S, 1) first store a nul in *D. + B.CreateStore(B.getInt8(0), Dst); + + // Transform strlcpy(D, S, 0) to a call to strlen(S). + return copyFlags(*CI, emitStrLen(Src, B, DL, TLI)); + } + + // Try to determine the length of the source, substituting its size + // when it's not nul-terminated (as it's required to be) to avoid + // reading past its end. + StringRef Str; + if (!getConstantStringInfo(Src, Str, /*TrimAtNul=*/false)) + return nullptr; + + uint64_t SrcLen = Str.find('\0'); + // Set if the terminating nul should be copied by the call to memcpy + // below. + bool NulTerm = SrcLen < NBytes; + + if (NulTerm) + // Overwrite NBytes with the number of bytes to copy, including + // the terminating nul. + NBytes = SrcLen + 1; + else { + // Set the length of the source for the function to return to its + // size, and cap NBytes at the same. + SrcLen = std::min(SrcLen, uint64_t(Str.size())); + NBytes = std::min(NBytes - 1, SrcLen); + } + + if (SrcLen == 0) { + // Transform strlcpy(D, "", N) to (*D = '\0, 0). + B.CreateStore(B.getInt8(0), Dst); + return ConstantInt::get(CI->getType(), 0); + } + + Function *Callee = CI->getCalledFunction(); + Type *PT = Callee->getFunctionType()->getParamType(0); + // Transform strlcpy(D, S, N) to memcpy(D, S, N') where N' is the lower + // bound on strlen(S) + 1 and N, optionally followed by a nul store to + // D[N' - 1] if necessary. + CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), + ConstantInt::get(DL.getIntPtrType(PT), NBytes)); + mergeAttributesAndFlags(NewCI, *CI); + + if (!NulTerm) { + Value *EndOff = ConstantInt::get(CI->getType(), NBytes); + Value *EndPtr = B.CreateInBoundsGEP(B.getInt8Ty(), Dst, EndOff); + B.CreateStore(B.getInt8(0), EndPtr); + } + + // Like snprintf, strlcpy returns the number of nonzero bytes that would + // have been copied if the bound had been sufficiently big (which in this + // case is strlen(Src)). + return ConstantInt::get(CI->getType(), SrcLen); +} + +// Optimize a call CI to either stpncpy when RetEnd is true, or to strncpy +// otherwise. +Value *LibCallSimplifier::optimizeStringNCpy(CallInst *CI, bool RetEnd, + IRBuilderBase &B) { Function *Callee = CI->getCalledFunction(); Value *Dst = CI->getArgOperand(0); Value *Src = CI->getArgOperand(1); Value *Size = CI->getArgOperand(2); - annotateNonNullNoUndefBasedOnAccess(CI, 0); - if (isKnownNonZero(Size, DL)) + + if (isKnownNonZero(Size, DL)) { + // Both st{p,r}ncpy(D, S, N) access the source and destination arrays + // only when N is nonzero. + annotateNonNullNoUndefBasedOnAccess(CI, 0); annotateNonNullNoUndefBasedOnAccess(CI, 1); + } - uint64_t Len; - if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(Size)) - Len = LengthArg->getZExtValue(); - else - return nullptr; + // If the "bound" argument is known set N to it. Otherwise set it to + // UINT64_MAX and handle it later. + uint64_t N = UINT64_MAX; + if (ConstantInt *SizeC = dyn_cast<ConstantInt>(Size)) + N = SizeC->getZExtValue(); - // strncpy(x, y, 0) -> x - if (Len == 0) + if (N == 0) + // Fold st{p,r}ncpy(D, S, 0) to D. return Dst; - // See if we can get the length of the input string. + if (N == 1) { + Type *CharTy = B.getInt8Ty(); + Value *CharVal = B.CreateLoad(CharTy, Src, "stxncpy.char0"); + B.CreateStore(CharVal, Dst); + if (!RetEnd) + // Transform strncpy(D, S, 1) to return (*D = *S), D. + return Dst; + + // Transform stpncpy(D, S, 1) to return (*D = *S) ? D + 1 : D. + Value *ZeroChar = ConstantInt::get(CharTy, 0); + Value *Cmp = B.CreateICmpEQ(CharVal, ZeroChar, "stpncpy.char0cmp"); + + Value *Off1 = B.getInt32(1); + Value *EndPtr = B.CreateInBoundsGEP(CharTy, Dst, Off1, "stpncpy.end"); + return B.CreateSelect(Cmp, Dst, EndPtr, "stpncpy.sel"); + } + + // If the length of the input string is known set SrcLen to it. uint64_t SrcLen = GetStringLength(Src); - if (SrcLen) { + if (SrcLen) annotateDereferenceableBytes(CI, 1, SrcLen); - --SrcLen; // Unbias length. - } else { + else return nullptr; - } + + --SrcLen; // Unbias length. if (SrcLen == 0) { - // strncpy(x, "", y) -> memset(x, '\0', y) + // Transform st{p,r}ncpy(D, "", N) to memset(D, '\0', N) for any N. Align MemSetAlign = - CI->getAttributes().getParamAttrs(0).getAlignment().valueOrOne(); + CI->getAttributes().getParamAttrs(0).getAlignment().valueOrOne(); CallInst *NewCI = B.CreateMemSet(Dst, B.getInt8('\0'), Size, MemSetAlign); AttrBuilder ArgAttrs(CI->getContext(), CI->getAttributes().getParamAttrs(0)); NewCI->setAttributes(NewCI->getAttributes().addParamAttributes( @@ -732,28 +847,35 @@ Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilderBase &B) { return Dst; } - // strncpy(a, "a", 4) - > memcpy(a, "a\0\0\0", 4) - if (Len > SrcLen + 1) { - if (Len <= 128) { - StringRef Str; - if (!getConstantStringInfo(Src, Str)) - return nullptr; - std::string SrcStr = Str.str(); - SrcStr.resize(Len, '\0'); - Src = B.CreateGlobalString(SrcStr, "str"); - } else { + if (N > SrcLen + 1) { + if (N > 128) + // Bail if N is large or unknown. return nullptr; - } + + // st{p,r}ncpy(D, "a", N) -> memcpy(D, "a\0\0\0", N) for N <= 128. + StringRef Str; + if (!getConstantStringInfo(Src, Str)) + return nullptr; + std::string SrcStr = Str.str(); + // Create a bigger, nul-padded array with the same length, SrcLen, + // as the original string. + SrcStr.resize(N, '\0'); + Src = B.CreateGlobalString(SrcStr, "str"); } Type *PT = Callee->getFunctionType()->getParamType(0); - // strncpy(x, s, c) -> memcpy(align 1 x, align 1 s, c) [s and c are constant] + // st{p,r}ncpy(D, S, N) -> memcpy(align 1 D, align 1 S, N) when both + // S and N are constant. CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), - ConstantInt::get(DL.getIntPtrType(PT), Len)); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); - return Dst; + ConstantInt::get(DL.getIntPtrType(PT), N)); + mergeAttributesAndFlags(NewCI, *CI); + if (!RetEnd) + return Dst; + + // stpncpy(D, S, N) returns the address of the first null in D if it writes + // one, otherwise D + N. + Value *Off = B.getInt64(std::min(SrcLen, N)); + return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, Off, "endptr"); } Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B, @@ -807,9 +929,9 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B, // strlen(s + x) to strlen(s) - x, when x is known to be in the range // [0, strlen(s)] or the string has a single null terminator '\0' at the end. // We only try to simplify strlen when the pointer s points to an array - // of i8. Otherwise, we would need to scale the offset x before doing the - // subtraction. This will make the optimization more complex, and it's not - // very useful because calling strlen for a pointer of other types is + // of CharSize elements. Otherwise, we would need to scale the offset x before + // doing the subtraction. This will make the optimization more complex, and + // it's not very useful because calling strlen for a pointer of other types is // very uncommon. if (GEPOperator *GEP = dyn_cast<GEPOperator>(Src)) { // TODO: Handle subobjects. @@ -1064,7 +1186,7 @@ Value *LibCallSimplifier::optimizeMemRChr(CallInst *CI, IRBuilderBase &B) { } StringRef Str; - if (!getConstantStringInfo(SrcStr, Str, 0, /*TrimAtNul=*/false)) + if (!getConstantStringInfo(SrcStr, Str, /*TrimAtNul=*/false)) return nullptr; if (Str.size() == 0) @@ -1159,7 +1281,7 @@ Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilderBase &B) { } StringRef Str; - if (!getConstantStringInfo(SrcStr, Str, 0, /*TrimAtNul=*/false)) + if (!getConstantStringInfo(SrcStr, Str, /*TrimAtNul=*/false)) return nullptr; if (CharC) { @@ -1298,8 +1420,8 @@ static Value *optimizeMemCmpVarSize(CallInst *CI, Value *LHS, Value *RHS, return Constant::getNullValue(CI->getType()); StringRef LStr, RStr; - if (!getConstantStringInfo(LHS, LStr, 0, /*TrimAtNul=*/false) || - !getConstantStringInfo(RHS, RStr, 0, /*TrimAtNul=*/false)) + if (!getConstantStringInfo(LHS, LStr, /*TrimAtNul=*/false) || + !getConstantStringInfo(RHS, RStr, /*TrimAtNul=*/false)) return nullptr; // If the contents of both constant arrays are known, fold a call to @@ -1355,7 +1477,7 @@ static Value *optimizeMemCmpConstantSize(CallInst *CI, Value *LHS, Value *RHS, // to legal integers or equality comparison. See block below this. if (DL.isLegalInteger(Len * 8) && isOnlyUsedInZeroEqualityComparison(CI)) { IntegerType *IntType = IntegerType::get(CI->getContext(), Len * 8); - unsigned PrefAlignment = DL.getPrefTypeAlignment(IntType); + Align PrefAlignment = DL.getPrefTypeAlign(IntType); // First, see if we can fold either argument to a constant. Value *LHSV = nullptr; @@ -1441,9 +1563,7 @@ Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilderBase &B) { // memcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n) CallInst *NewCI = B.CreateMemCpy(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), Size); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return CI->getArgOperand(0); } @@ -1459,8 +1579,7 @@ Value *LibCallSimplifier::optimizeMemCCpy(CallInst *CI, IRBuilderBase &B) { if (N) { if (N->isNullValue()) return Constant::getNullValue(CI->getType()); - if (!getConstantStringInfo(Src, SrcStr, /*Offset=*/0, - /*TrimAtNul=*/false) || + if (!getConstantStringInfo(Src, SrcStr, /*TrimAtNul=*/false) || // TODO: Handle zeroinitializer. !StopChar) return nullptr; @@ -1497,9 +1616,7 @@ Value *LibCallSimplifier::optimizeMemPCpy(CallInst *CI, IRBuilderBase &B) { // Propagate attributes, but memcpy has no return value, so make sure that // any return attributes are compliant. // TODO: Attach return value attributes to the 1st operand to preserve them? - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, N); } @@ -1512,9 +1629,7 @@ Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilderBase &B) { // memmove(x, y, n) -> llvm.memmove(align 1 x, align 1 y, n) CallInst *NewCI = B.CreateMemMove(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), Size); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return CI->getArgOperand(0); } @@ -1527,9 +1642,7 @@ Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilderBase &B) { // memset(p, v, n) -> llvm.memset(align 1 p, v, n) Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false); CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val, Size, Align(1)); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return CI->getArgOperand(0); } @@ -1745,7 +1858,6 @@ static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B, unsigned DstWidth) { Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { Module *M = Pow->getModule(); Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); - AttributeList Attrs; // Attributes are only meaningful on the original call Module *Mod = Pow->getModule(); Type *Ty = Pow->getType(); bool Ignored; @@ -1770,8 +1882,7 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { LibFunc LibFn; Function *CalleeFn = BaseFn->getCalledFunction(); - if (CalleeFn && - TLI->getLibFunc(CalleeFn->getName(), LibFn) && + if (CalleeFn && TLI->getLibFunc(CalleeFn->getName(), LibFn) && isLibFuncEmittable(M, TLI, LibFn)) { StringRef ExpName; Intrinsic::ID ID; @@ -1781,14 +1892,18 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { switch (LibFn) { default: return nullptr; - case LibFunc_expf: case LibFunc_exp: case LibFunc_expl: + case LibFunc_expf: + case LibFunc_exp: + case LibFunc_expl: ExpName = TLI->getName(LibFunc_exp); ID = Intrinsic::exp; LibFnFloat = LibFunc_expf; LibFnDouble = LibFunc_exp; LibFnLongDouble = LibFunc_expl; break; - case LibFunc_exp2f: case LibFunc_exp2: case LibFunc_exp2l: + case LibFunc_exp2f: + case LibFunc_exp2: + case LibFunc_exp2l: ExpName = TLI->getName(LibFunc_exp2); ID = Intrinsic::exp2; LibFnFloat = LibFunc_exp2f; @@ -1821,6 +1936,8 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { if (!match(Pow->getArgOperand(0), m_APFloat(BaseF))) return nullptr; + AttributeList NoAttrs; // Attributes are only meaningful on the original call + // pow(2.0, itofp(x)) -> ldexp(1.0, x) if (match(Base, m_SpecificFP(2.0)) && (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo)) && @@ -1829,7 +1946,7 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { return copyFlags(*Pow, emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), ExpoI, TLI, LibFunc_ldexp, LibFunc_ldexpf, - LibFunc_ldexpl, B, Attrs)); + LibFunc_ldexpl, B, NoAttrs)); } // pow(2.0 ** n, x) -> exp2(n * x) @@ -1853,7 +1970,7 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { else return copyFlags(*Pow, emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, - LibFunc_exp2l, B, Attrs)); + LibFunc_exp2l, B, NoAttrs)); } } @@ -1863,7 +1980,7 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { hasFloatFn(M, TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) return copyFlags(*Pow, emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l, - B, Attrs)); + B, NoAttrs)); // pow(x, y) -> exp2(log2(x) * y) if (Pow->hasApproxFunc() && Pow->hasNoNaNs() && BaseF->isFiniteNonZero() && @@ -1889,7 +2006,7 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { LibFunc_exp2l)) return copyFlags(*Pow, emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, - LibFunc_exp2l, B, Attrs)); + LibFunc_exp2l, B, NoAttrs)); } } @@ -1921,7 +2038,6 @@ static Value *getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno, /// Use square root in place of pow(x, +/-0.5). Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B) { Value *Sqrt, *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); - AttributeList Attrs; // Attributes are only meaningful on the original call Module *Mod = Pow->getModule(); Type *Ty = Pow->getType(); @@ -1943,7 +2059,8 @@ Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B) { !isKnownNeverInfinity(Base, TLI)) return nullptr; - Sqrt = getSqrtCall(Base, Attrs, Pow->doesNotAccessMemory(), Mod, B, TLI); + Sqrt = getSqrtCall(Base, AttributeList(), Pow->doesNotAccessMemory(), Mod, B, + TLI); if (!Sqrt) return nullptr; @@ -2049,8 +2166,8 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) { return nullptr; ExpoF = &ExpoI; - Sqrt = getSqrtCall(Base, Pow->getCalledFunction()->getAttributes(), - Pow->doesNotAccessMemory(), M, B, TLI); + Sqrt = getSqrtCall(Base, AttributeList(), Pow->doesNotAccessMemory(), M, + B, TLI); if (!Sqrt) return nullptr; } @@ -2094,7 +2211,6 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) { Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); - AttributeList Attrs; // Attributes are only meaningful on the original call StringRef Name = Callee->getName(); Value *Ret = nullptr; if (UnsafeFPShrink && Name == TLI->getName(LibFunc_exp2) && @@ -2104,14 +2220,14 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { Type *Ty = CI->getType(); Value *Op = CI->getArgOperand(0); - // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= IntSize - // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < IntSize + // exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= IntSize + // exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < IntSize if ((isa<SIToFPInst>(Op) || isa<UIToFPInst>(Op)) && hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *Exp = getIntToFPVal(Op, B, TLI->getIntSize())) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, - LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, - B, Attrs); + LibFunc_ldexp, LibFunc_ldexpf, + LibFunc_ldexpl, B, AttributeList()); } return Ret; @@ -2149,7 +2265,6 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) { Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) { Function *LogFn = Log->getCalledFunction(); - AttributeList Attrs; // Attributes are only meaningful on the original call StringRef LogNm = LogFn->getName(); Intrinsic::ID LogID = LogFn->getIntrinsicID(); Module *Mod = Log->getModule(); @@ -2260,12 +2375,13 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) { TLI->getLibFunc(*Arg, ArgLb); // log(pow(x,y)) -> y*log(x) + AttributeList NoAttrs; if (ArgLb == PowLb || ArgID == Intrinsic::pow) { Value *LogX = Log->doesNotAccessMemory() ? B.CreateCall(Intrinsic::getDeclaration(Mod, LogID, Ty), Arg->getOperand(0), "log") - : emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, Attrs); + : emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, NoAttrs); Value *MulY = B.CreateFMul(Arg->getArgOperand(1), LogX, "mul"); // Since pow() may have side effects, e.g. errno, // dead code elimination may not be trusted to remove it. @@ -2288,7 +2404,7 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) { Value *LogE = Log->doesNotAccessMemory() ? B.CreateCall(Intrinsic::getDeclaration(Mod, LogID, Ty), Eul, "log") - : emitUnaryFloatFnCall(Eul, TLI, LogNm, B, Attrs); + : emitUnaryFloatFnCall(Eul, TLI, LogNm, B, NoAttrs); Value *MulY = B.CreateFMul(Arg->getArgOperand(0), LogE, "mul"); // Since exp() may have side effects, e.g. errno, // dead code elimination may not be trusted to remove it. @@ -2404,8 +2520,7 @@ static bool isTrigLibCall(CallInst *CI) { // We can only hope to do anything useful if we can ignore things like errno // and floating-point exceptions. // We already checked the prototype. - return CI->hasFnAttr(Attribute::NoUnwind) && - CI->hasFnAttr(Attribute::ReadNone); + return CI->doesNotThrow() && CI->doesNotAccessMemory(); } static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value *Arg, @@ -2511,9 +2626,7 @@ void LibCallSimplifier::classifyArgUse( SmallVectorImpl<CallInst *> &SinCalls, SmallVectorImpl<CallInst *> &CosCalls, SmallVectorImpl<CallInst *> &SinCosCalls) { - CallInst *CI = dyn_cast<CallInst>(Val); - Module *M = CI->getModule(); - + auto *CI = dyn_cast<CallInst>(Val); if (!CI || CI->use_empty()) return; @@ -2521,6 +2634,7 @@ void LibCallSimplifier::classifyArgUse( if (CI->getFunction() != F) return; + Module *M = CI->getModule(); Function *Callee = CI->getCalledFunction(); LibFunc Func; if (!Callee || !TLI->getLibFunc(*Callee, Func) || @@ -2550,21 +2664,24 @@ void LibCallSimplifier::classifyArgUse( //===----------------------------------------------------------------------===// Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilderBase &B) { - // ffs(x) -> x != 0 ? (i32)llvm.cttz(x)+1 : 0 + // All variants of ffs return int which need not be 32 bits wide. + // ffs{,l,ll}(x) -> x != 0 ? (int)llvm.cttz(x)+1 : 0 + Type *RetType = CI->getType(); Value *Op = CI->getArgOperand(0); Type *ArgType = Op->getType(); Function *F = Intrinsic::getDeclaration(CI->getCalledFunction()->getParent(), Intrinsic::cttz, ArgType); Value *V = B.CreateCall(F, {Op, B.getTrue()}, "cttz"); V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1)); - V = B.CreateIntCast(V, B.getInt32Ty(), false); + V = B.CreateIntCast(V, RetType, false); Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType)); - return B.CreateSelect(Cond, V, B.getInt32(0)); + return B.CreateSelect(Cond, V, ConstantInt::get(RetType, 0)); } Value *LibCallSimplifier::optimizeFls(CallInst *CI, IRBuilderBase &B) { - // fls(x) -> (i32)(sizeInBits(x) - llvm.ctlz(x, false)) + // All variants of fls return int which need not be 32 bits wide. + // fls{,l,ll}(x) -> (int)(sizeInBits(x) - llvm.ctlz(x, false)) Value *Op = CI->getArgOperand(0); Type *ArgType = Op->getType(); Function *F = Intrinsic::getDeclaration(CI->getCalledFunction()->getParent(), @@ -2587,15 +2704,17 @@ Value *LibCallSimplifier::optimizeAbs(CallInst *CI, IRBuilderBase &B) { Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilderBase &B) { // isdigit(c) -> (c-'0') <u 10 Value *Op = CI->getArgOperand(0); - Op = B.CreateSub(Op, B.getInt32('0'), "isdigittmp"); - Op = B.CreateICmpULT(Op, B.getInt32(10), "isdigit"); + Type *ArgType = Op->getType(); + Op = B.CreateSub(Op, ConstantInt::get(ArgType, '0'), "isdigittmp"); + Op = B.CreateICmpULT(Op, ConstantInt::get(ArgType, 10), "isdigit"); return B.CreateZExt(Op, CI->getType()); } Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilderBase &B) { // isascii(c) -> c <u 128 Value *Op = CI->getArgOperand(0); - Op = B.CreateICmpULT(Op, B.getInt32(128), "isascii"); + Type *ArgType = Op->getType(); + Op = B.CreateICmpULT(Op, ConstantInt::get(ArgType, 128), "isascii"); return B.CreateZExt(Op, CI->getType()); } @@ -2701,9 +2820,15 @@ Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilderBase &B) { if (!CI->use_empty()) return nullptr; + Type *IntTy = CI->getType(); // printf("x") -> putchar('x'), even for "%" and "%%". - if (FormatStr.size() == 1 || FormatStr == "%%") - return copyFlags(*CI, emitPutChar(B.getInt32(FormatStr[0]), B, TLI)); + if (FormatStr.size() == 1 || FormatStr == "%%") { + // Convert the character to unsigned char before passing it to putchar + // to avoid host-specific sign extension in the IR. Putchar converts + // it to unsigned char regardless. + Value *IntChar = ConstantInt::get(IntTy, (unsigned char)FormatStr[0]); + return copyFlags(*CI, emitPutChar(IntChar, B, TLI)); + } // Try to remove call or emit putchar/puts. if (FormatStr == "%s" && CI->arg_size() > 1) { @@ -2714,8 +2839,13 @@ Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilderBase &B) { if (OperandStr.empty()) return (Value *)CI; // printf("%s", "a") --> putchar('a') - if (OperandStr.size() == 1) - return copyFlags(*CI, emitPutChar(B.getInt32(OperandStr[0]), B, TLI)); + if (OperandStr.size() == 1) { + // Convert the character to unsigned char before passing it to putchar + // to avoid host-specific sign extension in the IR. Putchar converts + // it to unsigned char regardless. + Value *IntChar = ConstantInt::get(IntTy, (unsigned char)OperandStr[0]); + return copyFlags(*CI, emitPutChar(IntChar, B, TLI)); + } // printf("%s", str"\n") --> puts(str) if (OperandStr.back() == '\n') { OperandStr = OperandStr.drop_back(); @@ -2738,8 +2868,12 @@ Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilderBase &B) { // Optimize specific format strings. // printf("%c", chr) --> putchar(chr) if (FormatStr == "%c" && CI->arg_size() > 1 && - CI->getArgOperand(1)->getType()->isIntegerTy()) - return copyFlags(*CI, emitPutChar(CI->getArgOperand(1), B, TLI)); + CI->getArgOperand(1)->getType()->isIntegerTy()) { + // Convert the argument to the type expected by putchar, i.e., int, which + // need not be 32 bits wide but which is the same as printf's return type. + Value *IntChar = B.CreateIntCast(CI->getArgOperand(1), IntTy, false); + return copyFlags(*CI, emitPutChar(IntChar, B, TLI)); + } // printf("%s\n", str) --> puts(str) if (FormatStr == "%s\n" && CI->arg_size() > 1 && @@ -2757,6 +2891,8 @@ Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilderBase &B) { return V; } + annotateNonNullNoUndefBasedOnAccess(CI, 0); + // printf(format, ...) -> iprintf(format, ...) if no floating point // arguments. if (isLibFuncEmittable(M, TLI, LibFunc_iprintf) && @@ -2781,7 +2917,6 @@ Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilderBase &B) { return New; } - annotateNonNullNoUndefBasedOnAccess(CI, 0); return nullptr; } @@ -2880,6 +3015,8 @@ Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilderBase &B) { return V; } + annotateNonNullNoUndefBasedOnAccess(CI, {0, 1}); + // sprintf(str, format, ...) -> siprintf(str, format, ...) if no floating // point arguments. if (isLibFuncEmittable(M, TLI, LibFunc_siprintf) && @@ -2904,10 +3041,63 @@ Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilderBase &B) { return New; } - annotateNonNullNoUndefBasedOnAccess(CI, {0, 1}); return nullptr; } +// Transform an snprintf call CI with the bound N to format the string Str +// either to a call to memcpy, or to single character a store, or to nothing, +// and fold the result to a constant. A nonnull StrArg refers to the string +// argument being formatted. Otherwise the call is one with N < 2 and +// the "%c" directive to format a single character. +Value *LibCallSimplifier::emitSnPrintfMemCpy(CallInst *CI, Value *StrArg, + StringRef Str, uint64_t N, + IRBuilderBase &B) { + assert(StrArg || (N < 2 && Str.size() == 1)); + + unsigned IntBits = TLI->getIntSize(); + uint64_t IntMax = maxIntN(IntBits); + if (Str.size() > IntMax) + // Bail if the string is longer than INT_MAX. POSIX requires + // implementations to set errno to EOVERFLOW in this case, in + // addition to when N is larger than that (checked by the caller). + return nullptr; + + Value *StrLen = ConstantInt::get(CI->getType(), Str.size()); + if (N == 0) + return StrLen; + + // Set to the number of bytes to copy fron StrArg which is also + // the offset of the terinating nul. + uint64_t NCopy; + if (N > Str.size()) + // Copy the full string, including the terminating nul (which must + // be present regardless of the bound). + NCopy = Str.size() + 1; + else + NCopy = N - 1; + + Value *DstArg = CI->getArgOperand(0); + if (NCopy && StrArg) + // Transform the call to lvm.memcpy(dst, fmt, N). + copyFlags( + *CI, + B.CreateMemCpy( + DstArg, Align(1), StrArg, Align(1), + ConstantInt::get(DL.getIntPtrType(CI->getContext()), NCopy))); + + if (N > Str.size()) + // Return early when the whole format string, including the final nul, + // has been copied. + return StrLen; + + // Otherwise, when truncating the string append a terminating nul. + Type *Int8Ty = B.getInt8Ty(); + Value *NulOff = B.getIntN(IntBits, NCopy); + Value *DstEnd = B.CreateInBoundsGEP(Int8Ty, DstArg, NulOff, "endptr"); + B.CreateStore(ConstantInt::get(Int8Ty, 0), DstEnd); + return StrLen; +} + Value *LibCallSimplifier::optimizeSnPrintFString(CallInst *CI, IRBuilderBase &B) { // Check for size @@ -2916,78 +3106,66 @@ Value *LibCallSimplifier::optimizeSnPrintFString(CallInst *CI, return nullptr; uint64_t N = Size->getZExtValue(); + uint64_t IntMax = maxIntN(TLI->getIntSize()); + if (N > IntMax) + // Bail if the bound exceeds INT_MAX. POSIX requires implementations + // to set errno to EOVERFLOW in this case. + return nullptr; + + Value *DstArg = CI->getArgOperand(0); + Value *FmtArg = CI->getArgOperand(2); + // Check for a fixed format string. StringRef FormatStr; - if (!getConstantStringInfo(CI->getArgOperand(2), FormatStr)) + if (!getConstantStringInfo(FmtArg, FormatStr)) return nullptr; // If we just have a format string (nothing else crazy) transform it. if (CI->arg_size() == 3) { - // Make sure there's no % in the constant array. We could try to handle - // %% -> % in the future if we cared. if (FormatStr.contains('%')) - return nullptr; // we found a format specifier, bail out. - - if (N == 0) - return ConstantInt::get(CI->getType(), FormatStr.size()); - else if (N < FormatStr.size() + 1) + // Bail if the format string contains a directive and there are + // no arguments. We could handle "%%" in the future. return nullptr; - // snprintf(dst, size, fmt) -> llvm.memcpy(align 1 dst, align 1 fmt, - // strlen(fmt)+1) - copyFlags( - *CI, - B.CreateMemCpy( - CI->getArgOperand(0), Align(1), CI->getArgOperand(2), Align(1), - ConstantInt::get(DL.getIntPtrType(CI->getContext()), - FormatStr.size() + 1))); // Copy the null byte. - return ConstantInt::get(CI->getType(), FormatStr.size()); + return emitSnPrintfMemCpy(CI, FmtArg, FormatStr, N, B); } // The remaining optimizations require the format string to be "%s" or "%c" // and have an extra operand. - if (FormatStr.size() == 2 && FormatStr[0] == '%' && CI->arg_size() == 4) { - - // Decode the second character of the format string. - if (FormatStr[1] == 'c') { - if (N == 0) - return ConstantInt::get(CI->getType(), 1); - else if (N == 1) - return nullptr; - - // snprintf(dst, size, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0 - if (!CI->getArgOperand(3)->getType()->isIntegerTy()) - return nullptr; - Value *V = B.CreateTrunc(CI->getArgOperand(3), B.getInt8Ty(), "char"); - Value *Ptr = castToCStr(CI->getArgOperand(0), B); - B.CreateStore(V, Ptr); - Ptr = B.CreateInBoundsGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul"); - B.CreateStore(B.getInt8(0), Ptr); + if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->arg_size() != 4) + return nullptr; - return ConstantInt::get(CI->getType(), 1); + // Decode the second character of the format string. + if (FormatStr[1] == 'c') { + if (N <= 1) { + // Use an arbitary string of length 1 to transform the call into + // either a nul store (N == 1) or a no-op (N == 0) and fold it + // to one. + StringRef CharStr("*"); + return emitSnPrintfMemCpy(CI, nullptr, CharStr, N, B); } - if (FormatStr[1] == 's') { - // snprintf(dest, size, "%s", str) to llvm.memcpy(dest, str, len+1, 1) - StringRef Str; - if (!getConstantStringInfo(CI->getArgOperand(3), Str)) - return nullptr; + // snprintf(dst, size, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0 + if (!CI->getArgOperand(3)->getType()->isIntegerTy()) + return nullptr; + Value *V = B.CreateTrunc(CI->getArgOperand(3), B.getInt8Ty(), "char"); + Value *Ptr = castToCStr(DstArg, B); + B.CreateStore(V, Ptr); + Ptr = B.CreateInBoundsGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul"); + B.CreateStore(B.getInt8(0), Ptr); + return ConstantInt::get(CI->getType(), 1); + } - if (N == 0) - return ConstantInt::get(CI->getType(), Str.size()); - else if (N < Str.size() + 1) - return nullptr; + if (FormatStr[1] != 's') + return nullptr; - copyFlags( - *CI, B.CreateMemCpy(CI->getArgOperand(0), Align(1), - CI->getArgOperand(3), Align(1), - ConstantInt::get(CI->getType(), Str.size() + 1))); + Value *StrArg = CI->getArgOperand(3); + // snprintf(dest, size, "%s", str) to llvm.memcpy(dest, str, len+1, 1) + StringRef Str; + if (!getConstantStringInfo(StrArg, Str)) + return nullptr; - // The snprintf result is the unincremented number of bytes in the string. - return ConstantInt::get(CI->getType(), Str.size()); - } - } - return nullptr; + return emitSnPrintfMemCpy(CI, StrArg, Str, N, B); } Value *LibCallSimplifier::optimizeSnPrintF(CallInst *CI, IRBuilderBase &B) { @@ -3021,10 +3199,11 @@ Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI, if (FormatStr.contains('%')) return nullptr; // We found a format specifier. + unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule()); + Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits); return copyFlags( *CI, emitFWrite(CI->getArgOperand(1), - ConstantInt::get(DL.getIntPtrType(CI->getContext()), - FormatStr.size()), + ConstantInt::get(SizeTTy, FormatStr.size()), CI->getArgOperand(0), B, DL, TLI)); } @@ -3035,11 +3214,13 @@ Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI, // Decode the second character of the format string. if (FormatStr[1] == 'c') { - // fprintf(F, "%c", chr) --> fputc(chr, F) + // fprintf(F, "%c", chr) --> fputc((int)chr, F) if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return nullptr; - return copyFlags( - *CI, emitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B, TLI)); + Type *IntTy = B.getIntNTy(TLI->getIntSize()); + Value *V = B.CreateIntCast(CI->getArgOperand(2), IntTy, /*isSigned*/ true, + "chari"); + return copyFlags(*CI, emitFPutC(V, CI->getArgOperand(0), B, TLI)); } if (FormatStr[1] == 's') { @@ -3106,7 +3287,9 @@ Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilderBase &B) { if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) -> fputc(S[0],F) Value *Char = B.CreateLoad(B.getInt8Ty(), castToCStr(CI->getArgOperand(0), B), "char"); - Value *NewCI = emitFPutC(Char, CI->getArgOperand(3), B, TLI); + Type *IntTy = B.getIntNTy(TLI->getIntSize()); + Value *Cast = B.CreateIntCast(Char, IntTy, /*isSigned*/ true, "chari"); + Value *NewCI = emitFPutC(Cast, CI->getArgOperand(3), B, TLI); return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr; } } @@ -3135,10 +3318,12 @@ Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilderBase &B) { return nullptr; // Known to have no uses (see above). + unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule()); + Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits); return copyFlags( *CI, emitFWrite(CI->getArgOperand(0), - ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len - 1), + ConstantInt::get(SizeTTy, Len - 1), CI->getArgOperand(1), B, DL, TLI)); } @@ -3150,8 +3335,12 @@ Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilderBase &B) { // Check for a constant string. // puts("") -> putchar('\n') StringRef Str; - if (getConstantStringInfo(CI->getArgOperand(0), Str) && Str.empty()) - return copyFlags(*CI, emitPutChar(B.getInt32('\n'), B, TLI)); + if (getConstantStringInfo(CI->getArgOperand(0), Str) && Str.empty()) { + // putchar takes an argument of the same type as puts returns, i.e., + // int, which need not be 32 bits wide. + Type *IntTy = CI->getType(); + return copyFlags(*CI, emitPutChar(ConstantInt::get(IntTy, '\n'), B, TLI)); + } return nullptr; } @@ -3198,8 +3387,12 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, return optimizeStrCpy(CI, Builder); case LibFunc_stpcpy: return optimizeStpCpy(CI, Builder); + case LibFunc_strlcpy: + return optimizeStrLCpy(CI, Builder); + case LibFunc_stpncpy: + return optimizeStringNCpy(CI, /*RetEnd=*/true, Builder); case LibFunc_strncpy: - return optimizeStrNCpy(CI, Builder); + return optimizeStringNCpy(CI, /*RetEnd=*/false, Builder); case LibFunc_strlen: return optimizeStrLen(CI, Builder); case LibFunc_strnlen: @@ -3555,12 +3748,9 @@ void LibCallSimplifier::eraseFromParent(Instruction *I) { // Fortified Library Call Optimizations //===----------------------------------------------------------------------===// -bool -FortifiedLibCallSimplifier::isFortifiedCallFoldable(CallInst *CI, - unsigned ObjSizeOp, - Optional<unsigned> SizeOp, - Optional<unsigned> StrOp, - Optional<unsigned> FlagOp) { +bool FortifiedLibCallSimplifier::isFortifiedCallFoldable( + CallInst *CI, unsigned ObjSizeOp, std::optional<unsigned> SizeOp, + std::optional<unsigned> StrOp, std::optional<unsigned> FlagOp) { // If this function takes a flag argument, the implementation may use it to // perform extra checks. Don't fold into the non-checking variant. if (FlagOp) { @@ -3605,9 +3795,7 @@ Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI, CallInst *NewCI = B.CreateMemCpy(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), CI->getArgOperand(2)); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return CI->getArgOperand(0); } return nullptr; @@ -3619,9 +3807,7 @@ Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI, CallInst *NewCI = B.CreateMemMove(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), CI->getArgOperand(2)); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return CI->getArgOperand(0); } return nullptr; @@ -3633,9 +3819,7 @@ Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI, Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false); CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), Align(1)); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - copyFlags(*CI, NewCI); + mergeAttributesAndFlags(NewCI, *CI); return CI->getArgOperand(0); } return nullptr; @@ -3647,10 +3831,7 @@ Value *FortifiedLibCallSimplifier::optimizeMemPCpyChk(CallInst *CI, if (isFortifiedCallFoldable(CI, 3, 2)) if (Value *Call = emitMemPCpy(CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, DL, TLI)) { - CallInst *NewCI = cast<CallInst>(Call); - NewCI->setAttributes(CI->getAttributes()); - NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType())); - return copyFlags(*CI, NewCI); + return mergeAttributesAndFlags(cast<CallInst>(Call), *CI); } return nullptr; } @@ -3673,7 +3854,7 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, // st[rp]cpy_chk call which may fail at runtime if the size is too long. // TODO: It might be nice to get a maximum length out of the possible // string lengths for varying. - if (isFortifiedCallFoldable(CI, 2, None, 1)) { + if (isFortifiedCallFoldable(CI, 2, std::nullopt, 1)) { if (Func == LibFunc_strcpy_chk) return copyFlags(*CI, emitStrCpy(Dst, Src, B, TLI)); else @@ -3690,11 +3871,8 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, else return nullptr; - // FIXME: There is really no guarantee that sizeof(size_t) is equal to - // sizeof(int*) for every target. So the assumption used here to derive the - // SizeTBits based on the size of an integer pointer in address space zero - // isn't always valid. - Type *SizeTTy = DL.getIntPtrType(CI->getContext(), /*AddressSpace=*/0); + unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule()); + Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits); Value *LenV = ConstantInt::get(SizeTTy, Len); Value *Ret = emitMemCpyChk(Dst, Src, LenV, ObjSize, B, DL, TLI); // If the function was an __stpcpy_chk, and we were able to fold it into @@ -3707,7 +3885,7 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, Value *FortifiedLibCallSimplifier::optimizeStrLenChk(CallInst *CI, IRBuilderBase &B) { - if (isFortifiedCallFoldable(CI, 1, None, 0)) + if (isFortifiedCallFoldable(CI, 1, std::nullopt, 0)) return copyFlags(*CI, emitStrLen(CI->getArgOperand(0), B, CI->getModule()->getDataLayout(), TLI)); return nullptr; @@ -3742,7 +3920,7 @@ Value *FortifiedLibCallSimplifier::optimizeMemCCpyChk(CallInst *CI, Value *FortifiedLibCallSimplifier::optimizeSNPrintfChk(CallInst *CI, IRBuilderBase &B) { - if (isFortifiedCallFoldable(CI, 3, 1, None, 2)) { + if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2)) { SmallVector<Value *, 8> VariadicArgs(drop_begin(CI->args(), 5)); return copyFlags(*CI, emitSNPrintf(CI->getArgOperand(0), CI->getArgOperand(1), @@ -3754,7 +3932,7 @@ Value *FortifiedLibCallSimplifier::optimizeSNPrintfChk(CallInst *CI, Value *FortifiedLibCallSimplifier::optimizeSPrintfChk(CallInst *CI, IRBuilderBase &B) { - if (isFortifiedCallFoldable(CI, 2, None, None, 1)) { + if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1)) { SmallVector<Value *, 8> VariadicArgs(drop_begin(CI->args(), 4)); return copyFlags(*CI, emitSPrintf(CI->getArgOperand(0), CI->getArgOperand(3), @@ -3805,7 +3983,7 @@ Value *FortifiedLibCallSimplifier::optimizeStrLCpyChk(CallInst *CI, Value *FortifiedLibCallSimplifier::optimizeVSNPrintfChk(CallInst *CI, IRBuilderBase &B) { - if (isFortifiedCallFoldable(CI, 3, 1, None, 2)) + if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2)) return copyFlags( *CI, emitVSNPrintf(CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4), CI->getArgOperand(5), B, TLI)); @@ -3815,7 +3993,7 @@ Value *FortifiedLibCallSimplifier::optimizeVSNPrintfChk(CallInst *CI, Value *FortifiedLibCallSimplifier::optimizeVSPrintfChk(CallInst *CI, IRBuilderBase &B) { - if (isFortifiedCallFoldable(CI, 2, None, None, 1)) + if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1)) return copyFlags(*CI, emitVSPrintf(CI->getArgOperand(0), CI->getArgOperand(3), CI->getArgOperand(4), B, TLI)); |