Index: include/llvm/Transforms/Utils/SimplifyLibCalls.h =================================================================== --- include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -164,13 +164,14 @@ Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B); Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemChr(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemRChr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B); Value *optimizeBCmp(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCmpBCmpCommon(CallInst *CI, IRBuilder<> &B); Value *optimizeMemPCpy(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 *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); 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 @@ -189,21 +189,23 @@ static void annotateDereferenceableBytes(CallInst *CI, ArrayRef ArgNos, uint64_t DereferenceableBytes) { - const Function *F = CI->getFunction(); + const Function *F = CI->getCaller(); if (!F) return; for (unsigned ArgNo : ArgNos) { uint64_t DerefBytes = DereferenceableBytes; unsigned AS = CI->getArgOperand(ArgNo)->getType()->getPointerAddressSpace(); - if (!llvm::NullPointerIsDefined(F, AS)) + if (!llvm::NullPointerIsDefined(F, AS) || + CI->paramHasAttr(ArgNo, Attribute::NonNull)) DerefBytes = std::max(CI->getDereferenceableOrNullBytes( ArgNo + AttributeList::FirstArgIndex), DereferenceableBytes); - + if (CI->getDereferenceableBytes(ArgNo + AttributeList::FirstArgIndex) < DerefBytes) { CI->removeParamAttr(ArgNo, Attribute::Dereferenceable); - if (!llvm::NullPointerIsDefined(F, AS)) + if (!llvm::NullPointerIsDefined(F, AS) || + CI->paramHasAttr(ArgNo, Attribute::NonNull)) CI->removeParamAttr(ArgNo, Attribute::DereferenceableOrNull); CI->addParamAttr(ArgNo, Attribute::getWithDereferenceableBytes( CI->getContext(), DerefBytes)); @@ -211,6 +213,45 @@ } } +static void annotateNonNullBasedOnAccess(CallInst *CI, + ArrayRef ArgNos) { + Function *F = CI->getCaller(); + if (!F) + return; + + for (unsigned ArgNo : ArgNos) { + unsigned AS = CI->getArgOperand(ArgNo)->getType()->getPointerAddressSpace(); + if (llvm::NullPointerIsDefined(F, AS)) + continue; + + CI->addParamAttr(ArgNo, Attribute::NonNull); + annotateDereferenceableBytes(CI, ArgNo, 1); + } +} + +static void removeNonNull(CallInst *CI, ArrayRef ArgNos) { + for (unsigned ArgNo : ArgNos) + CI->removeParamAttr(ArgNo, Attribute::NonNull); +} + +static void annotateNonNullAndDereferenceable(CallInst *CI, ArrayRef ArgNos, + Value *Size, const DataLayout &DL) { + if (ConstantInt *LenC = dyn_cast(Size)) { + annotateNonNullBasedOnAccess(CI, ArgNos); + annotateDereferenceableBytes(CI, ArgNos, LenC->getZExtValue()); + } else if (isKnownNonZero(Size, DL)) { + annotateNonNullBasedOnAccess(CI, ArgNos); + const APInt *X, *Y; + uint64_t DerefMin = 1; + if (match(Size, m_Select(m_Value(), m_APInt(X), m_APInt(Y)))) { + DerefMin = std::min(X->getZExtValue(), Y->getZExtValue()); + annotateDereferenceableBytes(CI, ArgNos, DerefMin); + } + } else if (!isa(CI)) { + removeNonNull(CI, ArgNos); + } +} + //===----------------------------------------------------------------------===// // String and Memory Library Call Optimizations //===----------------------------------------------------------------------===// @@ -219,10 +260,13 @@ // Extract some information from the instruction Value *Dst = CI->getArgOperand(0); Value *Src = CI->getArgOperand(1); + annotateNonNullBasedOnAccess(CI, {0, 1}); // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); - if (Len == 0) + if (Len) + annotateDereferenceableBytes(CI, 1, Len); + else return nullptr; --Len; // Unbias length. @@ -257,24 +301,36 @@ // Extract some information from the instruction. Value *Dst = CI->getArgOperand(0); Value *Src = CI->getArgOperand(1); + Value *Size = CI->getArgOperand(2); uint64_t Len; + annotateNonNullBasedOnAccess(CI, 0); + if (isKnownNonZero(Size, DL)) + annotateNonNullBasedOnAccess(CI, 1); + else + removeNonNull(CI, 1); // We don't do anything if length is not constant. - if (ConstantInt *LengthArg = dyn_cast(CI->getArgOperand(2))) + ConstantInt *LengthArg = dyn_cast(Size); + if (LengthArg) { Len = LengthArg->getZExtValue(); - else + // strncat(x, c, 0) -> x + if (!Len) + return Dst; + } else { return nullptr; + } // See if we can get the length of the input string. uint64_t SrcLen = GetStringLength(Src); - if (SrcLen == 0) + if (SrcLen) { + annotateDereferenceableBytes(CI, 1, SrcLen); + --SrcLen; // Unbias length. + } else { return nullptr; - --SrcLen; // Unbias length. + } - // Handle the simple, do-nothing cases: // strncat(x, "", c) -> x - // strncat(x, c, 0) -> x - if (SrcLen == 0 || Len == 0) + if (SrcLen == 0) return Dst; // We don't optimize this case. @@ -290,13 +346,18 @@ Function *Callee = CI->getCalledFunction(); FunctionType *FT = Callee->getFunctionType(); Value *SrcStr = CI->getArgOperand(0); + annotateNonNullBasedOnAccess(CI, 0); // If the second operand is non-constant, see if we can compute the length // of the input string and turn this into memchr. ConstantInt *CharC = dyn_cast(CI->getArgOperand(1)); if (!CharC) { uint64_t Len = GetStringLength(SrcStr); - if (Len == 0 || !FT->getParamType(1)->isIntegerTy(32)) // memchr needs i32. + if (Len) + annotateDereferenceableBytes(CI, 0, Len); + else + return nullptr; + if (!FT->getParamType(1)->isIntegerTy(32)) // memchr needs i32. return nullptr; return emitMemChr(SrcStr, CI->getArgOperand(1), // include nul. @@ -329,6 +390,7 @@ Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilder<> &B) { Value *SrcStr = CI->getArgOperand(0); ConstantInt *CharC = dyn_cast(CI->getArgOperand(1)); + annotateNonNullBasedOnAccess(CI, 0); // Cannot fold anything if we're not looking for a constant. if (!CharC) @@ -376,7 +438,12 @@ // strcmp(P, "x") -> memcmp(P, "x", 2) uint64_t Len1 = GetStringLength(Str1P); + if (Len1) + annotateDereferenceableBytes(CI, 0, Len1); uint64_t Len2 = GetStringLength(Str2P); + if (Len2) + annotateDereferenceableBytes(CI, 1, Len2); + if (Len1 && Len2) { return emitMemCmp(Str1P, Str2P, ConstantInt::get(DL.getIntPtrType(CI->getContext()), @@ -399,17 +466,24 @@ TLI); } + annotateNonNullBasedOnAccess(CI, {0, 1}); return nullptr; } Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilder<> &B) { - Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1); + Value *Str1P = CI->getArgOperand(0); + Value *Str2P = CI->getArgOperand(1); + Value *Size = CI->getArgOperand(2); if (Str1P == Str2P) // strncmp(x,x,n) -> 0 return ConstantInt::get(CI->getType(), 0); + if (isKnownNonZero(Size, DL)) + annotateNonNullBasedOnAccess(CI, {0, 1}); + else + removeNonNull(CI, {0, 1}); // Get the length argument if it is constant. uint64_t Length; - if (ConstantInt *LengthArg = dyn_cast(CI->getArgOperand(2))) + if (ConstantInt *LengthArg = dyn_cast(Size)) Length = LengthArg->getZExtValue(); else return nullptr; @@ -418,7 +492,7 @@ return ConstantInt::get(CI->getType(), 0); if (Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1) - return emitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, DL, TLI); + return emitMemCmp(Str1P, Str2P, Size, B, DL, TLI); StringRef Str1, Str2; bool HasStr1 = getConstantStringInfo(Str1P, Str1); @@ -440,7 +514,11 @@ CI->getType()); uint64_t Len1 = GetStringLength(Str1P); + if (Len1) + annotateDereferenceableBytes(CI, 0, Len1); uint64_t Len2 = GetStringLength(Str2P); + if (Len2) + annotateDereferenceableBytes(CI, 1, Len2); // strncmp to memcmp if (!HasStr1 && HasStr2) { @@ -466,16 +544,21 @@ Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1); if (Dst == Src) // strcpy(x,x) -> x return Src; - + + annotateNonNullBasedOnAccess(CI, {0, 1}); // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); - if (Len == 0) + if (Len) + annotateDereferenceableBytes(CI, 1, Len); + else return nullptr; // 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. - B.CreateMemCpy(Dst, 1, Src, 1, - ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len)); + CallInst *NewCI = + B.CreateMemCpy(Dst, 1, Src, 1, + ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len)); + NewCI->setAttributes(CI->getAttributes()); return Dst; } @@ -489,7 +572,9 @@ // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); - if (Len == 0) + if (Len) + annotateDereferenceableBytes(CI, 1, Len); + else return nullptr; Type *PT = Callee->getFunctionType()->getParamType(0); @@ -499,7 +584,8 @@ // 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. - B.CreateMemCpy(Dst, 1, Src, 1, LenV); + CallInst *NewCI = B.CreateMemCpy(Dst, 1, Src, 1, LenV); + NewCI->setAttributes(CI->getAttributes()); return DstEnd; } @@ -507,37 +593,49 @@ Function *Callee = CI->getCalledFunction(); Value *Dst = CI->getArgOperand(0); Value *Src = CI->getArgOperand(1); - Value *LenOp = CI->getArgOperand(2); + Value *Size = CI->getArgOperand(2); + annotateNonNullBasedOnAccess(CI, 0); + if (isKnownNonZero(Size, DL)) + annotateNonNullBasedOnAccess(CI, 1); + else + removeNonNull(CI, 1); + + uint64_t Len; + if (ConstantInt *LengthArg = dyn_cast(Size)) + Len = LengthArg->getZExtValue(); + else + return nullptr; + + // strncpy(x, y, 0) -> x + if (Len == 0) + return Dst; // See if we can get the length of the input string. uint64_t SrcLen = GetStringLength(Src); - if (SrcLen == 0) + if (SrcLen) { + annotateDereferenceableBytes(CI, 1, SrcLen); + --SrcLen; // Unbias length. + } else { return nullptr; - --SrcLen; + } if (SrcLen == 0) { // strncpy(x, "", y) -> memset(align 1 x, '\0', y) - B.CreateMemSet(Dst, B.getInt8('\0'), LenOp, 1); + CallInst *NewCI = B.CreateMemSet(Dst, B.getInt8('\0'), Size, 1); + AttrBuilder ArgAttrs(CI->getAttributes().getParamAttributes(0)); + NewCI->getAttributes().addParamAttributes(CI->getContext(), 0, ArgAttrs); return Dst; } - uint64_t Len; - if (ConstantInt *LengthArg = dyn_cast(LenOp)) - Len = LengthArg->getZExtValue(); - else - return nullptr; - - if (Len == 0) - return Dst; // strncpy(x, y, 0) -> x - // Let strncpy handle the zero padding if (Len > SrcLen + 1) return nullptr; Type *PT = Callee->getFunctionType()->getParamType(0); // strncpy(x, s, c) -> memcpy(align 1 x, align 1 s, c) [s and c are constant] - B.CreateMemCpy(Dst, 1, Src, 1, ConstantInt::get(DL.getIntPtrType(PT), Len)); - + CallInst *NewCI = B.CreateMemCpy(Dst, 1, Src, 1, ConstantInt::get(DL.getIntPtrType(PT), Len)); + AttrBuilder ArgAttrs(CI->getAttributes().getParamAttributes(0)); + NewCI->getAttributes().addParamAttributes(CI->getContext(), 0, ArgAttrs); return Dst; } @@ -633,7 +731,10 @@ } Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) { - return optimizeStringLength(CI, B, 8); + if (Value *V = optimizeStringLength(CI, B, 8)) + return V; + annotateNonNullBasedOnAccess(CI, 0); + return nullptr; } Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilder<> &B) { @@ -781,23 +882,37 @@ Value *StrChr = emitStrChr(CI->getArgOperand(0), ToFindStr[0], B, TLI); return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : nullptr; } + + annotateNonNullBasedOnAccess(CI, {0, 1}); + return nullptr; +} + +Value *LibCallSimplifier::optimizeMemRChr(CallInst *CI, IRBuilder<> &B) { + if (isKnownNonZero(CI->getOperand(2), DL)) + annotateNonNullBasedOnAccess(CI, 0); + else + removeNonNull(CI, 0); return nullptr; } Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilder<> &B) { Value *SrcStr = CI->getArgOperand(0); + Value *Size = CI->getArgOperand(2); + annotateNonNullAndDereferenceable(CI, 0, Size, DL); ConstantInt *CharC = dyn_cast(CI->getArgOperand(1)); - ConstantInt *LenC = dyn_cast(CI->getArgOperand(2)); + ConstantInt *LenC = dyn_cast(Size); // memchr(x, y, 0) -> null if (LenC) { if (LenC->isZero()) return Constant::getNullValue(CI->getType()); - annotateDereferenceableBytes(CI, {0}, LenC->getZExtValue()); + } else { + // From now on we need at least constant length and string. + return nullptr; } - // From now on we need at least constant length and string. + StringRef Str; - if (!LenC || !getConstantStringInfo(SrcStr, Str, 0, /*TrimAtNul=*/false)) + if (!getConstantStringInfo(SrcStr, Str, 0, /*TrimAtNul=*/false)) return nullptr; // Truncate the string to LenC. If Str is smaller than LenC we will still only @@ -940,6 +1055,7 @@ Ret = 1; return ConstantInt::get(CI->getType(), Ret); } + return nullptr; } @@ -952,14 +1068,20 @@ if (LHS == RHS) // memcmp(s,s,x) -> 0 return Constant::getNullValue(CI->getType()); + annotateNonNullAndDereferenceable(CI, {0, 1}, Size, DL); // Handle constant lengths. - if (ConstantInt *LenC = dyn_cast(Size)) { - if (Value *Res = optimizeMemCmpConstantSize(CI, LHS, RHS, - LenC->getZExtValue(), B, DL)) - return Res; - annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue()); - } + ConstantInt *LenC = dyn_cast(Size); + if (!LenC) + return nullptr; + // memcmp(d,s,0) -> 0 + if (LenC->getZExtValue() == 0) + return Constant::getNullValue(CI->getType()); + + if (Value *Res = + optimizeMemCmpConstantSize(CI, LHS, RHS, LenC->getZExtValue(), B, DL)) + return Res; + annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue()); return nullptr; } @@ -984,17 +1106,16 @@ return optimizeMemCmpBCmpCommon(CI, B); } -Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B, - bool isIntrinsic) { +Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) { Value *Size = CI->getArgOperand(2); - if (ConstantInt *LenC = dyn_cast(Size)) - annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue()); - - if (isIntrinsic) + annotateNonNullAndDereferenceable(CI, {0, 1}, Size, DL); + if (isa(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, Size); + CallInst *NewCI = + B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, Size); + NewCI->setAttributes(CI->getAttributes()); return CI->getArgOperand(0); } @@ -1007,17 +1128,17 @@ return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, N); } -Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B, bool isIntrinsic) { +Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) { Value *Size = CI->getArgOperand(2); - if (ConstantInt *LenC = dyn_cast(Size)) - annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue()); - - if (isIntrinsic) + annotateNonNullAndDereferenceable(CI, {0, 1}, Size, DL); + if (isa(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, Size); - return CI->getArgOperand(0); + CallInst *NewCI = + B.CreateMemMove(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, Size); + NewCI->setAttributes(CI->getAttributes()); + return CI->getArgOperand(0); } /// Fold memset[_chk](malloc(n), 0, n) --> calloc(1, n). @@ -1066,13 +1187,10 @@ return Calloc; } -Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B, - bool isIntrinsic) { +Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) { Value *Size = CI->getArgOperand(2); - if (ConstantInt *LenC = dyn_cast(Size)) - annotateDereferenceableBytes(CI, {0}, LenC->getZExtValue()); - - if (isIntrinsic) + annotateNonNullAndDereferenceable(CI, 0, Size, DL); + if (isa(CI)) return nullptr; if (auto *Calloc = foldMallocMemset(CI, B)) @@ -1080,7 +1198,8 @@ // memset(p, v, n) -> llvm.memset(align 1 p, v, n) Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false); - B.CreateMemSet(CI->getArgOperand(0), Val, Size, 1); + CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val, Size, 1); + NewCI->setAttributes(CI->getAttributes()); return CI->getArgOperand(0); } @@ -2191,6 +2310,7 @@ return New; } + annotateNonNullBasedOnAccess(CI, 0); return nullptr; } @@ -2285,21 +2405,21 @@ return New; } + annotateNonNullBasedOnAccess(CI, {0, 1}); return nullptr; } Value *LibCallSimplifier::optimizeSnPrintFString(CallInst *CI, IRBuilder<> &B) { - // Check for a fixed format string. - StringRef FormatStr; - if (!getConstantStringInfo(CI->getArgOperand(2), FormatStr)) - return nullptr; - // Check for size ConstantInt *Size = dyn_cast(CI->getArgOperand(1)); if (!Size) return nullptr; uint64_t N = Size->getZExtValue(); + // Check for a fixed format string. + StringRef FormatStr; + if (!getConstantStringInfo(CI->getArgOperand(2), FormatStr)) + return nullptr; // If we just have a format string (nothing else crazy) transform it. if (CI->getNumArgOperands() == 3) { @@ -2372,6 +2492,10 @@ return V; } + if (isKnownNonZero(CI->getOperand(1), DL)) + annotateNonNullBasedOnAccess(CI, 0); + else + removeNonNull(CI, 0); return nullptr; } @@ -2566,6 +2690,7 @@ if (getConstantStringInfo(CI->getArgOperand(0), Str) && Str.empty()) return emitPutChar(B.getInt32('\n'), B, TLI); + annotateNonNullBasedOnAccess(CI, 0); return nullptr; } @@ -2627,6 +2752,8 @@ return optimizeStrStr(CI, Builder); case LibFunc_memchr: return optimizeMemChr(CI, Builder); + case LibFunc_memrchr: + return optimizeMemRChr(CI, Builder); case LibFunc_bcmp: return optimizeBCmp(CI, Builder); case LibFunc_memcmp: @@ -2782,11 +2909,11 @@ return optimizeSqrt(CI, Builder); // TODO: Use foldMallocMemset() with memset intrinsic. case Intrinsic::memset: - return optimizeMemSet(CI, Builder, true); + return optimizeMemSet(CI, Builder); case Intrinsic::memcpy: - return optimizeMemCpy(CI, Builder, true); + return optimizeMemCpy(CI, Builder); case Intrinsic::memmove: - return optimizeMemMove(CI, Builder, true); + return optimizeMemMove(CI, Builder); default: return nullptr; } @@ -2960,7 +3087,9 @@ uint64_t Len = GetStringLength(CI->getArgOperand(*StrOp)); // If the length is 0 we don't know how long it is and so we can't // remove the check. - if (Len == 0) + if (Len) + annotateDereferenceableBytes(CI, *StrOp, Len); + else return false; return ObjSizeCI->getZExtValue() >= Len; } @@ -2977,8 +3106,9 @@ Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B) { if (isFortifiedCallFoldable(CI, 3, 2)) { - B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, - CI->getArgOperand(2)); + CallInst *NewCI = B.CreateMemCpy( + CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, CI->getArgOperand(2)); + NewCI->setAttributes(CI->getAttributes()); return CI->getArgOperand(0); } return nullptr; @@ -3036,7 +3166,9 @@ // Maybe we can stil fold __st[rp]cpy_chk to __memcpy_chk. uint64_t Len = GetStringLength(Src); - if (Len == 0) + if (Len) + annotateDereferenceableBytes(CI, 1, Len); + else return nullptr; Type *SizeTTy = DL.getIntPtrType(CI->getContext()); Index: test/Analysis/BasicAA/gep-alias.ll =================================================================== --- test/Analysis/BasicAA/gep-alias.ll +++ test/Analysis/BasicAA/gep-alias.ll @@ -247,7 +247,7 @@ ; CHECK: [[U0ADDR:%[a-zA-Z0-9_]+]] = getelementptr inbounds [3 x i8], [3 x i8]* %u, i32 0, i32 0 ; CHECK: [[U0:%[a-zA-Z0-9_]+]] = load i8, i8* [[U0ADDR]], align 1 ; CHECK: [[U0ARG:%[a-zA-Z0-9_]+]] = zext i8 [[U0]] to i32 -; CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i32 [[T0ARG]], i32 [[U0ARG]]) +; CHECK: call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i32 [[T0ARG]], i32 [[U0ARG]]) ; CHECK: ret define void @test13() { entry: Index: test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll =================================================================== --- test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll +++ test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll @@ -8,7 +8,7 @@ define void @foo(i8* nocapture %p, i8* nocapture %q, i8* nocapture %s) nounwind { ; CHECK: @foo -; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) %p, i8* align 1 dereferenceable(16) %q, i64 16, i1 false), !tbaa !0 +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) %p, i8* nonnull align 1 dereferenceable(16) %q, i64 16, i1 false), !tbaa !0 ; CHECK-NEXT: store i8 2, i8* %s, align 1, !tbaa [[TAGA:!.*]] ; CHECK-NEXT: ret void tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 16, i1 false), !tbaa !2 Index: test/CodeGen/X86/no-plt-libcalls.ll =================================================================== --- test/CodeGen/X86/no-plt-libcalls.ll +++ test/CodeGen/X86/no-plt-libcalls.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Check if "RtLibUseGOT" works correctly when lib calls are simplified. ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -5,10 +6,13 @@ @hello_world = constant [13 x i8] c"hello world\0A\00" declare i32 @printf(i8*, ...) define void @printf_call() { +; CHECK-LABEL: @printf_call( +; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i64 0, i64 0)) +; CHECK-NEXT: ret void +; %fmt = getelementptr [4 x i8], [4 x i8]* @percent_s, i32 0, i32 0 %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt, i8* %str) -; CHECK: call i32 @puts(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i64 0, i64 0)) ret void } Index: test/Other/cgscc-libcall-update.ll =================================================================== --- test/Other/cgscc-libcall-update.ll +++ test/Other/cgscc-libcall-update.ll @@ -14,11 +14,12 @@ %tmp = alloca [1024 x i8], align 16 %tmp2 = getelementptr inbounds [1024 x i8], [1024 x i8]* %tmp, i64 0, i64 0 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp2, i8* %arg1, i64 1024, i1 false) -; CHECK: call void @llvm.memcpy +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(1024) %tmp3 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 false, i1 true, i1 false) %tmp4 = call i8* @__strncpy_chk(i8* %arg2, i8* %tmp2, i64 1023, i64 %tmp3) ; CHECK-NOT: call -; CHECK: call i8* @strncpy(i8* %arg2, i8* nonnull %tmp2, i64 1023) +; CHECK: call i8* @strncpy(i8* nonnull dereferenceable(1) %arg2, i8* nonnull dereferenceable(1) %tmp2, i64 1023) + ; CHECK-NOT: call ret i8* %tmp4 @@ -27,6 +28,7 @@ define i8* @strncpy(i8* %arg1, i8* %arg2, i64 %size) noinline { bb: +; CHECK: call i8* @my_special_strncpy(i8* %arg1, i8* %arg2, i64 %size) %result = call i8* @my_special_strncpy(i8* %arg1, i8* %arg2, i64 %size) ret i8* %result } Index: test/Transforms/InstCombine/ARM/strcmp.ll =================================================================== --- test/Transforms/InstCombine/ARM/strcmp.ll +++ test/Transforms/InstCombine/ARM/strcmp.ll @@ -67,7 +67,7 @@ define arm_aapcscc i32 @test5(i1 %b) { ; CHECK-LABEL: @test5( ; CHECK-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull dereferenceable(5) [[STR2]], i32 5) ; CHECK-NEXT: ret i32 [[MEMCMP]] ; @@ -145,7 +145,7 @@ define arm_aapcs_vfpcc i32 @test5_vfp(i1 %b) { ; CHECK-LABEL: @test5_vfp( ; CHECK-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull dereferenceable(5) [[STR2]], i32 5) ; CHECK-NEXT: ret i32 [[MEMCMP]] ; Index: test/Transforms/InstCombine/align-addr.ll =================================================================== --- test/Transforms/InstCombine/align-addr.ll +++ test/Transforms/InstCombine/align-addr.ll @@ -114,7 +114,7 @@ ; Check that the alignment is bumped up the alignment of the sret type. ; CHECK-LABEL: @test3( ; CHECK-NEXT: [[A4_CAST:%.*]] = bitcast %struct.s* [[A4:%.*]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(16) [[A4_CAST]], i8 0, i64 16, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 dereferenceable(16) [[A4_CAST]], i8 0, i64 16, i1 false) ; CHECK-NEXT: call void @use(i8* [[A4_CAST]]) ; CHECK-NEXT: ret void ; Index: test/Transforms/InstCombine/fortify-folding.ll =================================================================== --- test/Transforms/InstCombine/fortify-folding.ll +++ test/Transforms/InstCombine/fortify-folding.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s --dump-input-on-failure target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" @@ -9,9 +10,10 @@ %struct.__va_list_tag = type { i32, i32, i8*, i8* } define i8* @test_memccpy() { - ; CHECK-LABEL: define i8* @test_memccpy - ; CHECK-NEXT: call i8* @memccpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60) - ; CHECK-NEXT: ret i8* +; CHECK-LABEL: @test_memccpy( +; CHECK-NEXT: [[MEMCCPY:%.*]] = call i8* @memccpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60) +; CHECK-NEXT: ret i8* [[MEMCCPY]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i8* @__memccpy_chk(i8* %dst, i8* %src, i32 0, i64 60, i64 -1) @@ -19,9 +21,10 @@ } define i8* @test_not_memccpy() { - ; CHECK-LABEL: define i8* @test_not_memccpy - ; CHECK-NEXT: call i8* @__memccpy_chk - ; CHECK-NEXT: ret i8* +; CHECK-LABEL: @test_not_memccpy( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__memccpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60, i64 59) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i8* @__memccpy_chk(i8* %dst, i8* %src, i32 0, i64 60, i64 59) @@ -29,9 +32,10 @@ } define i32 @test_snprintf() { - ; CHECK-LABEL: define i32 @test_snprintf - ; CHECK-NEXT: call i32 (i8*, i64, i8*, ...) @snprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) - ; CHECK-NEXT: ret i32 +; CHECK-LABEL: @test_snprintf( +; CHECK-NEXT: [[SNPRINTF:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) +; CHECK-NEXT: ret i32 [[SNPRINTF]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %fmt = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* %dst, i64 60, i32 0, i64 -1, i8* %fmt) @@ -39,10 +43,11 @@ } define i32 @test_not_snprintf() { - ; CHECK-LABEL: define i32 @test_not_snprintf - ; CHECK-NEXT: call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk - ; CHECK-NEXT: call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk - ; CHECK-NEXT: ret i32 +; CHECK-LABEL: @test_not_snprintf( +; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i32 0, i64 59, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) +; CHECK-NEXT: [[IGN:%.*]] = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) +; CHECK-NEXT: ret i32 [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %fmt = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* %dst, i64 60, i32 0, i64 59, i8* %fmt) @@ -51,9 +56,10 @@ } define i32 @test_sprintf() { - ; CHECK-LABEL: define i32 @test_sprintf - ; CHECK-NEXT: call i32 (i8*, i8*, ...) @sprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) - ; CHECK-NEXT: ret i32 +; CHECK-LABEL: @test_sprintf( +; CHECK-NEXT: [[SPRINTF:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) +; CHECK-NEXT: ret i32 [[SPRINTF]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %fmt = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* %dst, i32 0, i64 -1, i8* %fmt) @@ -61,10 +67,11 @@ } define i32 @test_not_sprintf() { - ; CHECK-LABEL: define i32 @test_not_sprintf - ; CHECK-NEXT: call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk - ; CHECK-NEXT: call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk - ; CHECK-NEXT: ret i32 +; CHECK-LABEL: @test_not_sprintf( +; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 0, i64 59, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) +; CHECK-NEXT: [[IGNORED:%.*]] = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) +; CHECK-NEXT: ret i32 [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %fmt = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* %dst, i32 0, i64 59, i8* %fmt) @@ -73,9 +80,10 @@ } define i8* @test_strcat() { - ; CHECK-LABEL: define i8* @test_strcat - ; CHECK-NEXT: call i8* @strcat(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) - ; CHECK-NEXT: ret i8* +; CHECK-LABEL: @test_strcat( +; CHECK-NEXT: [[STRCAT:%.*]] = call i8* @strcat(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0)) +; CHECK-NEXT: ret i8* [[STRCAT]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i8* @__strcat_chk(i8* %dst, i8* %src, i64 -1) @@ -83,9 +91,10 @@ } define i8* @test_not_strcat() { - ; CHECK-LABEL: define i8* @test_not_strcat - ; CHECK-NEXT: call i8* @__strcat_chk - ; CHECK-NEXT: ret i8* +; CHECK-LABEL: @test_not_strcat( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__strcat_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 0) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i8* @__strcat_chk(i8* %dst, i8* %src, i64 0) @@ -93,9 +102,10 @@ } define i64 @test_strlcat() { - ; CHECK-LABEL: define i64 @test_strlcat - ; CHECK-NEXT: call i64 @strlcat(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22) - ; CHECK-NEXT: ret i64 +; CHECK-LABEL: @test_strlcat( +; CHECK-NEXT: [[STRLCAT:%.*]] = call i64 @strlcat(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22) +; CHECK-NEXT: ret i64 [[STRLCAT]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i64 @__strlcat_chk(i8* %dst, i8* %src, i64 22, i64 -1) @@ -103,9 +113,10 @@ } define i64 @test_not_strlcat() { - ; CHECK-LABEL: define i64 @test_not_strlcat - ; CHECK-NEXT: call i64 @__strlcat_chk - ; CHECK-NEXT: ret i64 +; CHECK-LABEL: @test_not_strlcat( +; CHECK-NEXT: [[RET:%.*]] = call i64 @__strlcat_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 0) +; CHECK-NEXT: ret i64 [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i64 @__strlcat_chk(i8* %dst, i8* %src, i64 22, i64 0) @@ -113,9 +124,10 @@ } define i8* @test_strncat() { - ; CHECK-LABEL: define i8* @test_strncat - ; CHECK-NEXT: call i8* @strncat(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22) - ; CHECK-NEXT: ret i8* +; CHECK-LABEL: @test_strncat( +; CHECK-NEXT: [[STRNCAT:%.*]] = call i8* @strncat(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22) +; CHECK-NEXT: ret i8* [[STRNCAT]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i8* @__strncat_chk(i8* %dst, i8* %src, i64 22, i64 -1) @@ -123,9 +135,10 @@ } define i8* @test_not_strncat() { - ; CHECK-LABEL: define i8* @test_not_strncat - ; CHECK-NEXT: call i8* @__strncat_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 3) - ; CHECK-NEXT: ret i8* +; CHECK-LABEL: @test_not_strncat( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__strncat_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 3) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i8* @__strncat_chk(i8* %dst, i8* %src, i64 22, i64 3) @@ -133,9 +146,10 @@ } define i64 @test_strlcpy() { - ; CHECK-LABEL: define i64 @test_strlcpy - ; CHECK-NEXT: call i64 @strlcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22) - ; CHECK-NEXT: ret i64 +; CHECK-LABEL: @test_strlcpy( +; CHECK-NEXT: [[STRLCPY:%.*]] = call i64 @strlcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22) +; CHECK-NEXT: ret i64 [[STRLCPY]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i64 @__strlcpy_chk(i8* %dst, i8* %src, i64 22, i64 -1) @@ -143,9 +157,10 @@ } define i64 @test_not_strlcpy() { - ; CHECK-LABEL: define i64 @test_not_strlcpy - ; CHECK-NEXT: call i64 @__strlcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 2) - ; CHECK-NEXT: ret i64 +; CHECK-LABEL: @test_not_strlcpy( +; CHECK-NEXT: [[RET:%.*]] = call i64 @__strlcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 2) +; CHECK-NEXT: ret i64 [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 %ret = call i64 @__strlcpy_chk(i8* %dst, i8* %src, i64 22, i64 2) @@ -153,8 +168,10 @@ } define i32 @test_vsnprintf() { - ; CHECK-LABEL: define i32 @test_vsnprintf - ; CHECK-NEXT: call i32 @vsnprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-LABEL: @test_vsnprintf( +; CHECK-NEXT: [[VSNPRINTF:%.*]] = call i32 @vsnprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-NEXT: ret i32 [[VSNPRINTF]] +; ; ret i32 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 @@ -163,9 +180,11 @@ } define i32 @test_not_vsnprintf() { - ; CHECK-LABEL: define i32 @test_not_vsnprintf - ; CHECK-NEXT: call i32 @__vsnprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 0, i64 3, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) - ; CHECK-NEXT: call i32 @__vsnprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-LABEL: @test_not_vsnprintf( +; CHECK-NEXT: [[RET:%.*]] = call i32 @__vsnprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 0, i64 3, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-NEXT: [[IGN:%.*]] = call i32 @__vsnprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-NEXT: ret i32 [[RET]] +; ; ret i32 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 @@ -175,8 +194,10 @@ } define i32 @test_vsprintf() { - ; CHECK-LABEL: define i32 @test_vsprintf - ; CHECK-NEXT: call i32 @vsprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-LABEL: @test_vsprintf( +; CHECK-NEXT: [[VSPRINTF:%.*]] = call i32 @vsprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-NEXT: ret i32 [[VSPRINTF]] +; ; ret i32 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 @@ -185,9 +206,11 @@ } define i32 @test_not_vsprintf() { - ; CHECK-LABEL: define i32 @test_not_vsprintf - ; CHECK-NEXT: call i32 @__vsprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 0, i64 3, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) - ; CHECK-NEXT: call i32 @__vsprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-LABEL: @test_not_vsprintf( +; CHECK-NEXT: [[RET:%.*]] = call i32 @__vsprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 0, i64 3, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-NEXT: [[IGN:%.*]] = call i32 @__vsprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null) +; CHECK-NEXT: ret i32 [[RET]] +; ; ret i32 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 Index: test/Transforms/InstCombine/getelementptr.ll =================================================================== --- test/Transforms/InstCombine/getelementptr.ll +++ test/Transforms/InstCombine/getelementptr.ll @@ -491,7 +491,7 @@ %tmp.0.reg2mem.0.rec = mul i32 %indvar, -1 %tmp12.rec = add i32 %tmp.0.reg2mem.0.rec, -1 %tmp12 = getelementptr inbounds %struct.x, %struct.x* %tmp45, i32 %tmp12.rec - %tmp16 = call i32 (i8*, ...) @printf( i8* getelementptr ([12 x i8], [12 x i8]* @.str1, i32 0, i32 0), %struct.x* %tmp12 ) nounwind + %tmp16 = call i32 (i8*, ...) @printf( i8* nonnull dereferenceable(1) getelementptr ([12 x i8], [12 x i8]* @.str1, i32 0, i32 0), %struct.x* %tmp12 ) nounwind %tmp84 = icmp eq %struct.x* %tmp12, %orientations62 %indvar.next = add i32 %indvar, 1 br i1 %tmp84, label %bb17, label %bb10 @@ -652,7 +652,7 @@ i8* getelementptr (%t1, %t1* bitcast (%t0* @s to %t1*), i32 0, i32 1, i32 0)) nounwind ret i32 0 ; CHECK-LABEL: @test35( -; CHECK: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @"\01LC8", i64 0, i64 0), i8* getelementptr inbounds (%t0, %t0* @s, i64 0, i32 1, i64 0)) [[$NUW:#[0-9]+]] +; CHECK: call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([17 x i8], [17 x i8]* @"\01LC8", i64 0, i64 0), i8* getelementptr inbounds (%t0, %t0* @s, i64 0, i32 1, i64 0)) [[$NUW:#[0-9]+]] } ; Don't treat signed offsets as unsigned. Index: test/Transforms/InstCombine/malloc-free-delete.ll =================================================================== --- test/Transforms/InstCombine/malloc-free-delete.ll +++ test/Transforms/InstCombine/malloc-free-delete.ll @@ -72,8 +72,8 @@ ; CHECK-NEXT: [[E:%.*]] = call dereferenceable_or_null(700) i8* @malloc(i32 700) ; CHECK-NEXT: [[F:%.*]] = call dereferenceable_or_null(700) i8* @malloc(i32 700) ; CHECK-NEXT: [[G:%.*]] = call dereferenceable_or_null(700) i8* @malloc(i32 700) -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(32) [[PTR:%.*]], i8* align 1 dereferenceable(32) [[A]], i32 32, i1 false) -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* align 1 dereferenceable(32) [[PTR]], i8* align 1 dereferenceable(32) [[B]], i32 32, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(32) [[PTR:%.*]], i8* nonnull align 1 dereferenceable(32) [[A]], i32 32, i1 false) +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(32) [[PTR]], i8* nonnull align 1 dereferenceable(32) [[B]], i32 32, i1 false) ; CHECK-NEXT: store i8* [[C]], i8** [[ESC:%.*]], align 8 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[D]], i8* [[PTR]], i32 32, i1 true) ; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* [[E]], i8* [[PTR]], i32 32, i1 true) Index: test/Transforms/InstCombine/mem-deref-bytes-addrspaces.ll =================================================================== --- test/Transforms/InstCombine/mem-deref-bytes-addrspaces.ll +++ test/Transforms/InstCombine/mem-deref-bytes-addrspaces.ll @@ -3,11 +3,20 @@ declare i32 @memcmp(i8 addrspace(1)* nocapture, i8* nocapture, i64) -define i32 @memcmp_const_size_update_deref8(i8 addrspace(1)* nocapture readonly %d, i8* nocapture readonly %s) { -; CHECK-LABEL: @memcmp_const_size_update_deref8( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8 addrspace(1)* dereferenceable(16) dereferenceable_or_null(40) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +define i32 @memcmp_const_size_update_deref(i8 addrspace(1)* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memcmp_const_size_update_deref( +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8 addrspace(1)* dereferenceable(16) dereferenceable_or_null(40) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8 addrspace(1)* dereferenceable_or_null(40) %d, i8* %s, i64 16) ret i32 %call } + +define i32 @memcmp_nonconst_size_nonnnull(i8 addrspace(1)* nocapture readonly %d, i8* nocapture readonly %s, i64 %n) { +; CHECK-LABEL: @memcmp_nonconst_size_nonnnull( +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8 addrspace(1)* dereferenceable_or_null(40) [[D:%.*]], i8* [[S:%.*]], i64 [[N:%.*]]) +; CHECK-NEXT: ret i32 [[CALL]] +; + %call = tail call i32 @memcmp(i8 addrspace(1)* nonnull dereferenceable_or_null(40) %d, i8* nonnull %s, i64 %n) + ret i32 %call +} Index: test/Transforms/InstCombine/mem-deref-bytes.ll =================================================================== --- test/Transforms/InstCombine/mem-deref-bytes.ll +++ test/Transforms/InstCombine/mem-deref-bytes.ll @@ -12,7 +12,7 @@ define i32 @memcmp_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcmp_const_size_set_deref( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8* %d, i8* %s, i64 16) @@ -21,7 +21,7 @@ define i32 @memcmp_const_size_update_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcmp_const_size_update_deref( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8* dereferenceable(4) %d, i8* dereferenceable(8) %s, i64 16) @@ -30,7 +30,7 @@ define i32 @memcmp_const_size_update_deref2(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcmp_const_size_update_deref2( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8* %d, i8* dereferenceable_or_null(8) %s, i64 16) @@ -39,7 +39,7 @@ define i32 @memcmp_const_size_update_deref3(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcmp_const_size_update_deref3( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(40) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8* dereferenceable(40) %d, i8* %s, i64 16) @@ -48,7 +48,7 @@ define i32 @memcmp_const_size_update_deref4(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcmp_const_size_update_deref4( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8* dereferenceable_or_null(16) %d, i8* %s, i64 16) @@ -57,7 +57,7 @@ define i32 @memcmp_const_size_update_deref5(i8* nocapture readonly %d, i8* nocapture readonly %s) "null-pointer-is-valid"="false" { ; CHECK-LABEL: @memcmp_const_size_update_deref5( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(40) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8* dereferenceable_or_null(40) %d, i8* %s, i64 16) @@ -73,9 +73,18 @@ ret i32 %call } +define i32 @memcmp_const_size_update_deref7(i8* nocapture readonly %d, i8* nocapture readonly %s) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @memcmp_const_size_update_deref7( +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT: ret i32 [[CALL]] +; + %call = tail call i32 @memcmp(i8* nonnull dereferenceable_or_null(40) %d, i8* %s, i64 16) + ret i32 %call +} + define i32 @memcmp_const_size_no_update_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcmp_const_size_no_update_deref( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(40) [[D:%.*]], i8* dereferenceable(20) [[S:%.*]], i64 16) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* nonnull dereferenceable(20) [[S:%.*]], i64 16) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = tail call i32 @memcmp(i8* dereferenceable(40) %d, i8* dereferenceable(20) %s, i64 16) @@ -93,7 +102,7 @@ define i8* @memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcpy_const_size_set_deref( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(64) [[D:%.*]], i8* align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(64) [[D:%.*]], i8* nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) ; CHECK-NEXT: ret i8* [[D]] ; %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 64) @@ -102,7 +111,7 @@ define i8* @memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memmove_const_size_set_deref( -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 dereferenceable(64) [[D:%.*]], i8* align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(64) [[D:%.*]], i8* nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) ; CHECK-NEXT: ret i8* [[D]] ; %call = tail call i8* @memmove(i8* %d, i8* %s, i64 64) @@ -111,7 +120,7 @@ define i8* @memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) { ; CHECK-LABEL: @memset_const_size_set_deref( -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 dereferenceable(64) [[S:%.*]], i8 [[C:%.*]], i64 64, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 1 dereferenceable(64) [[S:%.*]], i8 [[C:%.*]], i64 64, i1 false) ; CHECK-NEXT: ret i8* [[S]] ; %call = tail call i8* @memset(i8* %s, i8 %c, i64 64) @@ -120,7 +129,7 @@ define i8* @memchr_const_size_set_deref(i8* nocapture readonly %s, i32 %c) { ; CHECK-LABEL: @memchr_const_size_set_deref( -; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @memchr(i8* dereferenceable(64) [[S:%.*]], i32 [[C:%.*]], i64 64) +; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @memchr(i8* nonnull dereferenceable(64) [[S:%.*]], i32 [[C:%.*]], i64 64) ; CHECK-NEXT: ret i8* [[CALL]] ; %call = tail call i8* @memchr(i8* %s, i32 %c, i64 64) @@ -129,7 +138,7 @@ define i8* @llvm_memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @llvm_memcpy_const_size_set_deref( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[D:%.*]], i8* nonnull align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) ; CHECK-NEXT: ret i8* [[D]] ; call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %d, i8* align 1 %s, i64 16, i1 false) @@ -138,7 +147,7 @@ define i8* @llvm_memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @llvm_memmove_const_size_set_deref( -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[D:%.*]], i8* nonnull align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) ; CHECK-NEXT: ret i8* [[D]] ; call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 %d, i8* align 1 %s, i64 16, i1 false) @@ -146,7 +155,7 @@ } define i8* @llvm_memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) { ; CHECK-LABEL: @llvm_memset_const_size_set_deref( -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 dereferenceable(16) [[S:%.*]], i8 [[C:%.*]], i64 16, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[S:%.*]], i8 [[C:%.*]], i64 16, i1 false) ; CHECK-NEXT: ret i8* [[S]] ; call void @llvm.memset.p0i8.i64(i8* align 1 %s, i8 %c, i64 16, i1 false) Index: test/Transforms/InstCombine/memchr.ll =================================================================== --- test/Transforms/InstCombine/memchr.ll +++ test/Transforms/InstCombine/memchr.ll @@ -50,7 +50,7 @@ define void @test4(i32 %chr) { ; CHECK-LABEL: @test4( -; CHECK-NEXT: [[DST:%.*]] = call i8* @memchr(i8* dereferenceable(14) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14) +; CHECK-NEXT: [[DST:%.*]] = call i8* @memchr(i8* nonnull dereferenceable(14) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14) ; CHECK-NEXT: store i8* [[DST]], i8** @chp, align 4 ; CHECK-NEXT: ret void ; @@ -148,7 +148,7 @@ ; No 64 bits here define i1 @test12(i32 %C) { ; CHECK-LABEL: @test12( -; CHECK-NEXT: [[DST:%.*]] = call i8* @memchr(i8* dereferenceable(3) getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i32 0, i32 0), i32 [[C:%.*]], i32 3) +; CHECK-NEXT: [[DST:%.*]] = call i8* @memchr(i8* nonnull dereferenceable(3) getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i32 0, i32 0), i32 [[C:%.*]], i32 3) ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8* [[DST]], null ; CHECK-NEXT: ret i1 [[CMP]] ; @@ -185,7 +185,7 @@ define i1 @test15(i32 %C) { ; CHECK-LABEL: @test15( -; CHECK-NEXT: [[DST:%.*]] = call i8* @memchr(i8* dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i32 0, i32 0), i32 [[C:%.*]], i32 3) +; CHECK-NEXT: [[DST:%.*]] = call i8* @memchr(i8* nonnull dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i32 0, i32 0), i32 [[C:%.*]], i32 3) ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8* [[DST]], null ; CHECK-NEXT: ret i1 [[CMP]] ; @@ -202,3 +202,43 @@ %res = tail call i8* @memchr(i8* getelementptr ([1 x i8], [1 x i8]* @s, i64 0, i64 0), i32 0, i32 1) ret i8* %res } + +define i8* @test16(i8* %str, i32 %c, i32 %n) { +; CHECK-LABEL: @test16( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memchr(i8* [[STR:%.*]], i32 [[C:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memchr(i8* %str, i32 %c, i32 %n) + ret i8* %ret +} + +define i8* @test17(i8* %str, i32 %c, i32 %n) { +; CHECK-LABEL: @test17( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memchr(i8* [[STR:%.*]], i32 [[C:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memchr(i8* nonnull %str, i32 %c, i32 %n) + ret i8* %ret +} + +define i8* @test18(i8* %str, i32 %c) { +; CHECK-LABEL: @test18( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memchr(i8* nonnull dereferenceable(5) [[STR:%.*]], i32 [[C:%.*]], i32 5) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memchr(i8* %str, i32 %c, i32 5) + ret i8* %ret +} + +define i8* @test19(i8* %str, i32 %c) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @test19( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memchr(i8* dereferenceable(5) [[STR:%.*]], i32 [[C:%.*]], i32 5) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memchr(i8* %str, i32 %c, i32 5) + ret i8* %ret +} Index: test/Transforms/InstCombine/memcmp-constant-fold.ll =================================================================== --- test/Transforms/InstCombine/memcmp-constant-fold.ll +++ test/Transforms/InstCombine/memcmp-constant-fold.ll @@ -55,7 +55,7 @@ define i1 @memcmp_3bytes_aligned_constant_i32(i8* align 4 %x) { ; ALL-LABEL: @memcmp_3bytes_aligned_constant_i32( -; ALL-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(3) bitcast (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @intbuf, i64 0, i64 1) to i8*), i8* dereferenceable(3) bitcast ([2 x i32]* @intbuf to i8*), i64 3) +; ALL-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(3) bitcast (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @intbuf, i64 0, i64 1) to i8*), i8* nonnull dereferenceable(3) bitcast ([2 x i32]* @intbuf to i8*), i64 3) ; ALL-NEXT: [[CMPEQ0:%.*]] = icmp eq i32 [[CALL]], 0 ; ALL-NEXT: ret i1 [[CMPEQ0]] ; @@ -68,7 +68,7 @@ define i1 @memcmp_4bytes_one_unaligned_i8(i8* align 4 %x, i8* align 1 %y) { ; ALL-LABEL: @memcmp_4bytes_one_unaligned_i8( -; ALL-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(4) [[X:%.*]], i8* dereferenceable(4) [[Y:%.*]], i64 4) +; ALL-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(4) [[X:%.*]], i8* nonnull dereferenceable(4) [[Y:%.*]], i64 4) ; ALL-NEXT: [[CMPEQ0:%.*]] = icmp eq i32 [[CALL]], 0 ; ALL-NEXT: ret i1 [[CMPEQ0]] ; Index: test/Transforms/InstCombine/memcpy-from-global.ll =================================================================== --- test/Transforms/InstCombine/memcpy-from-global.ll +++ test/Transforms/InstCombine/memcpy-from-global.ll @@ -78,7 +78,7 @@ ; CHECK-LABEL: @test2( ; CHECK-NEXT: [[B1:%.*]] = alloca [124 x i8], align 8 ; CHECK-NEXT: [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 dereferenceable(124) [[B1_SUB]], i8* align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 dereferenceable(124) [[B1_SUB]], i8* nonnull align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false) ; CHECK-NEXT: call void @bar(i8* nonnull [[B1_SUB]]) ; CHECK-NEXT: ret void ; @@ -234,7 +234,7 @@ ; CHECK-LABEL: @test8( ; CHECK-NEXT: [[AL:%.*]] = alloca [[U:%.*]], align 16 ; CHECK-NEXT: [[A:%.*]] = bitcast %U* [[AL]] to i8* -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(20) [[A]], i8* align 4 dereferenceable(20) bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*), i64 20, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(20) [[A]], i8* nonnull align 4 dereferenceable(20) bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*), i64 20, i1 false) ; CHECK-NEXT: call void @bar(i8* nonnull [[A]]) #2 ; CHECK-NEXT: ret void ; @@ -294,8 +294,8 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CC:%.*]] = alloca [1000000 x i8], align 16 ; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1000000 x i8], [1000000 x i8]* [[CC]], i64 0, i64 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(3) [[ARRAYDECAY]], i8* align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false) -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 dereferenceable(1000000) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* nonnull align 16 dereferenceable(1000000) [[ARRAYDECAY]], i64 1000000, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(3) [[ARRAYDECAY]], i8* nonnull align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(1000000) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* nonnull align 16 dereferenceable(1000000) [[ARRAYDECAY]], i64 1000000, i1 false) ; CHECK-NEXT: ret void ; entry: @@ -311,7 +311,7 @@ define void @test10_same_global() { ; CHECK-LABEL: @test10_same_global( ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 dereferenceable(3) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(3) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* nonnull align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false) ; CHECK-NEXT: ret void ; entry: Index: test/Transforms/InstCombine/memcpy-to-load.ll =================================================================== --- test/Transforms/InstCombine/memcpy-to-load.ll +++ test/Transforms/InstCombine/memcpy-to-load.ll @@ -34,7 +34,7 @@ define void @copy_3_bytes(i8* %d, i8* %s) { ; ALL-LABEL: @copy_3_bytes( -; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(3) [[D:%.*]], i8* align 1 dereferenceable(3) [[S:%.*]], i32 3, i1 false) +; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(3) [[D:%.*]], i8* nonnull align 1 dereferenceable(3) [[S:%.*]], i32 3, i1 false) ; ALL-NEXT: ret void ; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 3, i1 false) @@ -57,7 +57,7 @@ define void @copy_5_bytes(i8* %d, i8* %s) { ; ALL-LABEL: @copy_5_bytes( -; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(5) [[D:%.*]], i8* align 1 dereferenceable(5) [[S:%.*]], i32 5, i1 false) +; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(5) [[D:%.*]], i8* nonnull align 1 dereferenceable(5) [[S:%.*]], i32 5, i1 false) ; ALL-NEXT: ret void ; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 5, i1 false) @@ -78,7 +78,7 @@ define void @copy_16_bytes(i8* %d, i8* %s) { ; ALL-LABEL: @copy_16_bytes( -; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i32 16, i1 false) +; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(16) [[D:%.*]], i8* nonnull align 1 dereferenceable(16) [[S:%.*]], i32 16, i1 false) ; ALL-NEXT: ret void ; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 16, i1 false) Index: test/Transforms/InstCombine/memcpy.ll =================================================================== --- test/Transforms/InstCombine/memcpy.ll +++ test/Transforms/InstCombine/memcpy.ll @@ -29,7 +29,7 @@ define void @test3(i8* %d, i8* %s) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(17179869184) [[D:%.*]], i8* align 4 dereferenceable(17179869184) [[S:%.*]], i64 17179869184, i1 false) +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 dereferenceable(17179869184) [[D:%.*]], i8* nonnull align 4 dereferenceable(17179869184) [[S:%.*]], i64 17179869184, i1 false) ; CHECK-NEXT: ret void ; tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %d, i8* align 4 %s, i64 17179869184, i1 false) Index: test/Transforms/InstCombine/memcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/memcpy_chk-1.ll +++ test/Transforms/InstCombine/memcpy_chk-1.ll @@ -18,7 +18,7 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) ; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) ; %dst = bitcast %struct.T1* @t1 to i8* @@ -29,7 +29,7 @@ define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) ; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) ; %dst = bitcast %struct.T1* @t1 to i8* @@ -65,7 +65,7 @@ define i8* @test_simplify_return_indcall(i8* ()* %alloc) { ; CHECK-LABEL: @test_simplify_return_indcall( ; CHECK-NEXT: [[DST:%.*]] = call i8* [[ALLOC:%.*]]() -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(1824) [[DST]], i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(1824) [[DST]], i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) ; CHECK-NEXT: ret i8* [[DST]] ; %src = bitcast %struct.T2* @t2 to i8* Index: test/Transforms/InstCombine/memmove_chk-1.ll =================================================================== --- test/Transforms/InstCombine/memmove_chk-1.ll +++ test/Transforms/InstCombine/memmove_chk-1.ll @@ -18,7 +18,7 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) ; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) ; %dst = bitcast %struct.T1* @t1 to i8* @@ -30,7 +30,7 @@ define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) ; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) ; %dst = bitcast %struct.T1* @t1 to i8* Index: test/Transforms/InstCombine/mempcpy.ll =================================================================== --- test/Transforms/InstCombine/mempcpy.ll +++ test/Transforms/InstCombine/mempcpy.ll @@ -45,7 +45,7 @@ define i8* @memcpy_big_const_n(i8* %d, i8* nocapture readonly %s) { ; CHECK-LABEL: @memcpy_big_const_n( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(1024) [[D:%.*]], i8* align 1 dereferenceable(1024) [[S:%.*]], i64 1024, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(1024) [[D:%.*]], i8* nonnull align 1 dereferenceable(1024) [[S:%.*]], i64 1024, i1 false) ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[D]], i64 1024 ; CHECK-NEXT: ret i8* [[TMP1]] ; Index: test/Transforms/InstCombine/memrchr.ll =================================================================== --- test/Transforms/InstCombine/memrchr.ll +++ test/Transforms/InstCombine/memrchr.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + + +declare i8* @memrchr(i8*, i32, i32) + +define i8* @test1(i8* %str, i32 %c, i32 %n) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* [[STR:%.*]], i32 [[C:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memrchr(i8* %str, i32 %c, i32 %n) + ret i8* %ret +} + +define i8* @test2(i8* %str, i32 %c, i32 %n) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* nonnull [[STR:%.*]], i32 [[C:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memrchr(i8* nonnull %str, i32 %c, i32 %n) + ret i8* %ret +} + +define i8* @test3(i8* %str, i32 %c) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* [[STR:%.*]], i32 [[C:%.*]], i32 5) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memrchr(i8* %str, i32 %c, i32 5) + ret i8* %ret +} + +define i8* @test4(i8* %str, i32 %c) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @test4( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* [[STR:%.*]], i32 [[C:%.*]], i32 5) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memrchr(i8* %str, i32 %c, i32 5) + ret i8* %ret +} + +define i8* @test5(i8* %str, i32 %c) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* [[STR:%.*]], i32 [[C:%.*]], i32 0) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @memrchr(i8* %str, i32 %c, i32 0) + ret i8* %ret +} Index: test/Transforms/InstCombine/memset-1.ll =================================================================== --- test/Transforms/InstCombine/memset-1.ll +++ test/Transforms/InstCombine/memset-1.ll @@ -49,7 +49,7 @@ define i8* @notmalloc_memset(i32 %size, i8*(i32)* %notmalloc) { ; CHECK-LABEL: @notmalloc_memset( ; CHECK-NEXT: [[CALL1:%.*]] = call i8* [[NOTMALLOC:%.*]](i32 [[SIZE:%.*]]) #0 -; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 [[CALL1]], i8 0, i32 [[SIZE]], i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 [[CALL1]], i8 0, i32 [[SIZE]], i1 false) #0 ; CHECK-NEXT: ret i8* [[CALL1]] ; %call1 = call i8* %notmalloc(i32 %size) #1 @@ -68,7 +68,7 @@ ; CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[IF_END:%.*]] ; CHECK: if.end: ; CHECK-NEXT: [[BC:%.*]] = bitcast i8* [[CALL]] to float* -; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 [[CALL]], i8 0, i32 [[SIZE]], i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 [[CALL]], i8 0, i32 [[SIZE]], i1 false) #0 ; CHECK-NEXT: br label [[CLEANUP]] ; CHECK: cleanup: ; CHECK-NEXT: [[RETVAL_0:%.*]] = phi float* [ [[BC]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ] @@ -93,7 +93,7 @@ ; CHECK-LABEL: @buffer_is_modified_then_memset( ; CHECK-NEXT: [[PTR:%.*]] = tail call i8* @malloc(i32 [[SIZE:%.*]]) #0 ; CHECK-NEXT: store i8 1, i8* [[PTR]], align 1 -; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 [[PTR]], i8 0, i32 [[SIZE]], i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 [[PTR]], i8 0, i32 [[SIZE]], i1 false) #0 ; CHECK-NEXT: ret i8* [[PTR]] ; %ptr = tail call i8* @malloc(i32 %size) #1 @@ -102,6 +102,103 @@ ret i8* %memset } +define i8* @memset_size_select(i1 %b, i8* %ptr) { +; CHECK-LABEL: @memset_size_select( +; CHECK-NEXT: [[SIZE:%.*]] = select i1 [[B:%.*]], i32 10, i32 50 +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(10) [[PTR:%.*]], i8 0, i32 [[SIZE]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %size = select i1 %b, i32 10, i32 50 + %memset = tail call i8* @memset(i8* nonnull %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + + +define i8* @memset_size_select2(i1 %b, i8* %ptr) { +; CHECK-LABEL: @memset_size_select2( +; CHECK-NEXT: [[SIZE:%.*]] = select i1 [[B:%.*]], i32 10, i32 50 +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(80) [[PTR:%.*]], i8 0, i32 [[SIZE]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %size = select i1 %b, i32 10, i32 50 + %memset = tail call i8* @memset(i8* nonnull dereferenceable(80) %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + +define i8* @memset_size_select3(i1 %b, i8* %ptr) { +; CHECK-LABEL: @memset_size_select3( +; CHECK-NEXT: [[SIZE:%.*]] = select i1 [[B:%.*]], i32 10, i32 50 +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(40) [[PTR:%.*]], i8 0, i32 [[SIZE]], i1 false) +; CHECK-NEXT: ret i8* [[PTR]] +; + %size = select i1 %b, i32 10, i32 50 + %memset = tail call i8* @memset(i8* dereferenceable_or_null(40) %ptr, i32 0, i32 %size) + ret i8* %memset +} + +define i8* @memset_size_select4(i1 %b, i8* %ptr) { +; CHECK-LABEL: @memset_size_select4( +; CHECK-NEXT: [[SIZE:%.*]] = select i1 [[B:%.*]], i32 10, i32 50 +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(40) [[PTR:%.*]], i8 0, i32 [[SIZE]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %size = select i1 %b, i32 10, i32 50 + %memset = tail call i8* @memset(i8* nonnull dereferenceable_or_null(40) %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + +define i8* @memset_size_ashr(i1 %b, i8* %ptr, i32 %v) { +; CHECK-LABEL: @memset_size_ashr( +; CHECK-NEXT: [[SIZE:%.*]] = ashr i32 -2, [[V:%.*]] +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(1) [[PTR:%.*]], i8 0, i32 [[SIZE]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %size = ashr i32 -2, %v + %memset = tail call i8* @memset(i8* nonnull %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + +define i8* @memset_attrs1(i1 %b, i8* %ptr, i32 %size) { +; CHECK-LABEL: @memset_attrs1( +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 dereferenceable_or_null(40) [[PTR:%.*]], i8 0, i32 [[SIZE:%.*]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %memset = tail call i8* @memset(i8* dereferenceable_or_null(40) %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + +; be sure to drop nonnull since size is unknown and can be 0 +; do not change dereferenceable attribute +define i8* @memset_attrs2(i1 %b, i8* %ptr, i32 %size) { +; CHECK-LABEL: @memset_attrs2( +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 dereferenceable(40) [[PTR:%.*]], i8 0, i32 [[SIZE:%.*]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %memset = tail call i8* @memset(i8* nonnull dereferenceable(40) %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + +; size is unknown, just copy attrs, no changes in attrs +define i8* @memset_attrs3(i1 %b, i8* %ptr, i32 %size) { +; CHECK-LABEL: @memset_attrs3( +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 dereferenceable_or_null(40) [[PTR:%.*]], i8 0, i32 [[SIZE:%.*]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %memset = tail call i8* @memset(i8* nonnull dereferenceable_or_null(40) %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + +; be sure to drop nonnull since size is unknown and can be 0 +define i8* @memset_attrs4(i1 %b, i8* %ptr, i32 %size) { +; CHECK-LABEL: @memset_attrs4( +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 [[PTR:%.*]], i8 0, i32 [[SIZE:%.*]], i1 false) #0 +; CHECK-NEXT: ret i8* [[PTR]] +; + %memset = tail call i8* @memset(i8* nonnull %ptr, i32 0, i32 %size) #1 + ret i8* %memset +} + + attributes #0 = { nounwind ssp uwtable } attributes #1 = { nounwind } attributes #2 = { nounwind readnone } Index: test/Transforms/InstCombine/memset_chk-1.ll =================================================================== --- test/Transforms/InstCombine/memset_chk-1.ll +++ test/Transforms/InstCombine/memset_chk-1.ll @@ -14,7 +14,7 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) ; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) ; %dst = bitcast %struct.T* @t to i8* @@ -25,7 +25,7 @@ define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) ; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) ; %dst = bitcast %struct.T* @t to i8* @@ -36,7 +36,7 @@ define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) ; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) ; %dst = bitcast %struct.T* @t to i8* @@ -73,11 +73,11 @@ define i32 @test_rauw(i8* %a, i8* %b, i8** %c) { ; CHECK-LABEL: @test_rauw( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL49:%.*]] = call i64 @strlen(i8* [[A:%.*]]) +; CHECK-NEXT: [[CALL49:%.*]] = call i64 @strlen(i8* nonnull dereferenceable(1) [[A:%.*]]) ; CHECK-NEXT: [[ADD180:%.*]] = add i64 [[CALL49]], 1 ; CHECK-NEXT: [[YO107:%.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* [[B:%.*]], i1 false, i1 false, i1 false) ; CHECK-NEXT: [[CALL50:%.*]] = call i8* @__memmove_chk(i8* [[B]], i8* [[A]], i64 [[ADD180]], i64 [[YO107]]) -; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(i8* [[B]]) +; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(i8* nonnull dereferenceable(1) [[B]]) ; CHECK-NEXT: [[STRCHR2:%.*]] = getelementptr i8, i8* [[B]], i64 [[STRLEN]] ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i8** [[C:%.*]] to i64* ; CHECK-NEXT: [[D1:%.*]] = load i64, i64* [[TMP0]], align 8 Index: test/Transforms/InstCombine/objsize.ll =================================================================== --- test/Transforms/InstCombine/objsize.ll +++ test/Transforms/InstCombine/objsize.ll @@ -163,7 +163,7 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = tail call noalias dereferenceable_or_null(20) i8* @malloc(i32 20) #0 ; CHECK-NEXT: [[TMP1:%.*]] = load i8*, i8** @s, align 8 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(10) [[TMP0]], i8* align 1 dereferenceable(10) [[TMP1]], i32 10, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(10) [[TMP0]], i8* nonnull align 1 dereferenceable(10) [[TMP1]], i32 10, i1 false) ; CHECK-NEXT: ret i8* [[TMP0]] ; entry: Index: test/Transforms/InstCombine/printf-1.ll =================================================================== --- test/Transforms/InstCombine/printf-1.ll +++ test/Transforms/InstCombine/printf-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the printf library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -22,110 +23,164 @@ define void @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify1( +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt) ret void -; CHECK-NEXT: ret void } ; Check printf("x") -> putchar('x'), even for '%'. define void @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify2( +; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt) -; CHECK-NEXT: call i32 @putchar(i32 104) ret void -; CHECK-NEXT: ret void } ; Special case: printf("%%") -> putchar('%'). define void @test_simplify2b() { ; CHECK-LABEL: @test_simplify2b( +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify2b( +; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [3 x i8], [3 x i8]* @h2, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt) -; CHECK-NEXT: call i32 @putchar(i32 37) ret void -; CHECK-NEXT: ret void } define void @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify3( +; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [2 x i8], [2 x i8]* @percent, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt) -; CHECK-NEXT: call i32 @putchar(i32 37) ret void -; CHECK-NEXT: ret void } ; Check printf("foo\n") -> puts("foo"). define void @test_simplify4() { ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0)) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify4( +; CHECK-IPRINTF-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0)) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt) -; CHECK-NEXT: call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[$STR]], i32 0, i32 0)) ret void -; CHECK-NEXT: ret void } ; Check printf("%c", chr) -> putchar(chr). define void @test_simplify5() { ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify5( +; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [3 x i8], [3 x i8]* @percent_c, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt, i8 104) -; CHECK-NEXT: call i32 @putchar(i32 104) ret void -; CHECK-NEXT: ret void } ; Check printf("%s\n", str) -> puts(str). define void @test_simplify6() { ; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0)) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify6( +; CHECK-IPRINTF-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0)) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [4 x i8], [4 x i8]* @percent_s, i32 0, i32 0 %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt, i8* %str) -; CHECK-NEXT: call i32 @puts(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0)) ret void -; CHECK-NEXT: ret void } ; Check printf(format, ...) -> iprintf(format, ...) if no floating point. define void @test_simplify7() { +; CHECK-LABEL: @test_simplify7( +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) +; CHECK-NEXT: ret void +; ; CHECK-IPRINTF-LABEL: @test_simplify7( +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @iprintf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [3 x i8], [3 x i8]* @percent_d, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt, i32 187) -; CHECK-IPRINTF-NEXT: call i32 (i8*, ...) @iprintf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) ret void -; CHECK-IPRINTF-NEXT: ret void } define void @test_no_simplify1() { +; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) +; CHECK-NEXT: ret void +; ; CHECK-IPRINTF-LABEL: @test_no_simplify1( +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [3 x i8], [3 x i8]* @percent_f, i32 0, i32 0 call i32 (i8*, ...) @printf(i8* %fmt, double 1.87) -; CHECK-IPRINTF-NEXT: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) ret void -; CHECK-IPRINTF-NEXT: ret void } define void @test_no_simplify2(i8* %fmt, double %d) { ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]]) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_no_simplify2( +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]]) +; CHECK-IPRINTF-NEXT: ret void +; call i32 (i8*, ...) @printf(i8* %fmt, double %d) -; CHECK-NEXT: call i32 (i8*, ...) @printf(i8* %fmt, double %d) ret void -; CHECK-NEXT: ret void } define i32 @test_no_simplify3() { ; CHECK-LABEL: @test_no_simplify3( +; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([2 x i8], [2 x i8]* @h, i32 0, i32 0)) +; CHECK-NEXT: ret i32 [[RET]] +; +; CHECK-IPRINTF-LABEL: @test_no_simplify3( +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @iprintf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @h, i32 0, i32 0)) +; CHECK-IPRINTF-NEXT: ret i32 [[TMP1]] +; %fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0 %ret = call i32 (i8*, ...) @printf(i8* %fmt) -; CHECK-NEXT: call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @h, i32 0, i32 0)) ret i32 %ret -; CHECK-NEXT: ret i32 %ret } Index: test/Transforms/InstCombine/printf-2.ll =================================================================== --- test/Transforms/InstCombine/printf-2.ll +++ test/Transforms/InstCombine/printf-2.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the printf library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -16,38 +17,42 @@ define void @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) +; CHECK-NEXT: ret void +; %fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0 call void (i8*, ...) @printf(i8* %fmt) -; CHECK-NEXT: call i32 @putchar(i32 104) ret void -; CHECK-NEXT: ret void } define void @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0)) +; CHECK-NEXT: ret void +; %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 call void (i8*, ...) @printf(i8* %fmt) -; CHECK-NEXT: call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0)) ret void -; CHECK-NEXT: ret void } define void @test_simplify6() { ; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0)) +; CHECK-NEXT: ret void +; %fmt = getelementptr [4 x i8], [4 x i8]* @percent_s, i32 0, i32 0 %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 call void (i8*, ...) @printf(i8* %fmt, i8* %str) -; CHECK-NEXT: call i32 @puts(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0)) ret void -; CHECK-NEXT: ret void } define void @test_simplify7() { ; CHECK-LABEL: @test_simplify7( +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 97) +; CHECK-NEXT: ret void +; %fmt = getelementptr [3 x i8], [3 x i8]* @format_str, i32 0, i32 0 %str = getelementptr [2 x i8], [2 x i8]* @charstr, i32 0, i32 0 call void (i8*, ...) @printf(i8* %fmt, i8* %str) -; CHECK-NEXT: call i32 @putchar(i32 97) ret void -; CHECK-NEXT: ret void } Index: test/Transforms/InstCombine/snprintf.ll =================================================================== --- test/Transforms/InstCombine/snprintf.ll +++ test/Transforms/InstCombine/snprintf.ll @@ -10,13 +10,14 @@ define void @test_not_const_fmt(i8* %buf, i8* %fmt) #0 { ; CHECK-LABEL: @test_not_const_fmt( -; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 32, i8* [[FMT:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) [[BUF:%.*]], i64 32, i8* [[FMT:%.*]]) ; CHECK-NEXT: ret void ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* %fmt) #2 ret void } +; size is '0', do not add nonnull attribute define void @test_not_const_fmt_zero_size_return_value(i8* %buf, i8* %fmt) #0 { ; CHECK-LABEL: @test_not_const_fmt_zero_size_return_value( ; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 0, i8* [[FMT:%.*]]) @@ -26,6 +27,25 @@ ret void } +; size is '0', remove nonnull attribute +define void @test_nonnull_not_const_fmt_zero_size(i8* %buf, i8* %fmt) #0 { +; CHECK-LABEL: @test_nonnull_not_const_fmt_zero_size( +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 0, i8* [[FMT:%.*]]) +; CHECK-NEXT: ret void +; + %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull %buf, i64 0, i8* %fmt) #2 + ret void +} + +; size is unknown, remove nonnull attribute +define void @test_nonnull_not_const_fmt_non_const_size(i8* %buf, i64 %n, i8* %fmt) #0 { +; CHECK-LABEL: @test_nonnull_not_const_fmt_non_const_size( +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 [[N:%.*]], i8* [[FMT:%.*]]) +; CHECK-NEXT: ret void +; + %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull %buf, i64 %n, i8* %fmt) #2 + ret void +} define void @test_not_const_size(i8* %buf, i64 %size) #0 { ; CHECK-LABEL: @test_not_const_size( @@ -47,7 +67,7 @@ define void @test_percentage(i8* %buf) #0 { ; CHECK-LABEL: @test_percentage( -; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 32, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) [[BUF:%.*]], i64 32, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) ; CHECK-NEXT: ret void ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) #2 @@ -92,7 +112,7 @@ define i32 @test_char_wrong_size(i8* %buf) #0 { ; CHECK-LABEL: @test_char_wrong_size( -; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0), i32 65) +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) [[BUF:%.*]], i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0), i32 65) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0), i32 65) #2 @@ -120,7 +140,7 @@ define i32 @test_str_wrong_size(i8* %buf) #0 { ; CHECK-LABEL: @test_str_wrong_size( -; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) [[BUF:%.*]], i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 Index: test/Transforms/InstCombine/sprintf-1.ll =================================================================== --- test/Transforms/InstCombine/sprintf-1.ll +++ test/Transforms/InstCombine/sprintf-1.ll @@ -21,11 +21,11 @@ define void @test_simplify1(i8* %dst) { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(13) [[DST:%.*]], i8* align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(13) [[DST:%.*]], i8* nonnull align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false) ; CHECK-NEXT: ret void ; ; CHECK-IPRINTF-LABEL: @test_simplify1( -; CHECK-IPRINTF-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(13) [[DST:%.*]], i8* align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false) +; CHECK-IPRINTF-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(13) [[DST:%.*]], i8* nonnull align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false) ; CHECK-IPRINTF-NEXT: ret void ; %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 @@ -85,13 +85,13 @@ define void @test_simplify5(i8* %dst, i8* %str) { ; CHECK-LABEL: @test_simplify5( -; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* [[STR:%.*]]) +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]]) ; CHECK-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false) ; CHECK-NEXT: ret void ; ; CHECK-IPRINTF-LABEL: @test_simplify5( -; CHECK-IPRINTF-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* [[STR:%.*]]) +; CHECK-IPRINTF-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]]) ; CHECK-IPRINTF-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1 ; CHECK-IPRINTF-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false) ; CHECK-IPRINTF-NEXT: ret void @@ -105,7 +105,7 @@ define void @test_simplify6(i8* %dst) { ; CHECK-LABEL: @test_simplify6( -; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) ; CHECK-NEXT: ret void ; ; CHECK-IPRINTF-LABEL: @test_simplify6( @@ -119,11 +119,11 @@ define void @test_no_simplify1(i8* %dst) { ; CHECK-LABEL: @test_no_simplify1( -; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) ; CHECK-NEXT: ret void ; ; CHECK-IPRINTF-LABEL: @test_no_simplify1( -; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) ; CHECK-IPRINTF-NEXT: ret void ; %fmt = getelementptr [3 x i8], [3 x i8]* @percent_f, i32 0, i32 0 @@ -133,11 +133,11 @@ define void @test_no_simplify2(i8* %dst, i8* %fmt, double %d) { ; CHECK-LABEL: @test_no_simplify2( -; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* [[FMT:%.*]], double [[D:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]]) ; CHECK-NEXT: ret void ; ; CHECK-IPRINTF-LABEL: @test_no_simplify2( -; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* [[FMT:%.*]], double [[D:%.*]]) +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]]) ; CHECK-IPRINTF-NEXT: ret void ; call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double %d) Index: test/Transforms/InstCombine/stpcpy-1.ll =================================================================== --- test/Transforms/InstCombine/stpcpy-1.ll +++ test/Transforms/InstCombine/stpcpy-1.ll @@ -14,7 +14,7 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 5) ; @@ -27,7 +27,7 @@ define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0)) +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0)) ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @a, i32 0, i32 [[STRLEN]] ; CHECK-NEXT: ret i8* [[TMP1]] ; @@ -38,6 +38,18 @@ ret i8* %ret } +define void @test_simplify3(i8* %dst) { +; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(80) [[DST:%.*]], i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret void +; + + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + + call i8* @stpcpy(i8* dereferenceable(80) %dst, i8* %src) + ret void +} + define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( ; CHECK-NEXT: [[RET:%.*]] = call i8* @stpcpy(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8], [32 x i8]* @b, i32 0, i32 0)) Index: test/Transforms/InstCombine/stpcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/stpcpy_chk-1.ll +++ test/Transforms/InstCombine/stpcpy_chk-1.ll @@ -14,7 +14,7 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -26,7 +26,7 @@ define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -38,7 +38,7 @@ define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -82,7 +82,7 @@ define i8* @test_simplify6() { ; CHECK-LABEL: @test_simplify6( -; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)) +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)) ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 [[STRLEN]] ; CHECK-NEXT: ret i8* [[TMP1]] ; Index: test/Transforms/InstCombine/strchr-1.ll =================================================================== --- test/Transforms/InstCombine/strchr-1.ll +++ test/Transforms/InstCombine/strchr-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strchr library call simplifier works correctly. ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -11,9 +12,10 @@ declare i8* @strchr(i8*, i32) define void @test_simplify1() { -; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 6) -; CHECK-NOT: call i8* @strchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 6), i8** @chp, align 4 +; CHECK-NEXT: ret void +; %str = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strchr(i8* %str, i32 119) @@ -22,9 +24,10 @@ } define void @test_simplify2() { -; CHECK: store i8* null, i8** @chp, align 4 -; CHECK-NOT: call i8* @strchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: store i8* null, i8** @chp, align 4 +; CHECK-NEXT: ret void +; %str = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 %dst = call i8* @strchr(i8* %str, i32 119) @@ -33,9 +36,10 @@ } define void @test_simplify3() { -; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13) -; CHECK-NOT: call i8* @strchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13), i8** @chp, align 4 +; CHECK-NEXT: ret void +; %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strchr(i8* %src, i32 0) @@ -44,9 +48,11 @@ } define void @test_simplify4(i32 %chr) { -; CHECK: call i8* @memchr -; CHECK-NOT: call i8* @strchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: [[MEMCHR:%.*]] = call i8* @memchr(i8* nonnull dereferenceable(14) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14) +; CHECK-NEXT: store i8* [[MEMCHR]], i8** @chp, align 4 +; CHECK-NEXT: ret void +; %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strchr(i8* %src, i32 %chr) @@ -55,9 +61,10 @@ } define void @test_simplify5() { -; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13) -; CHECK-NOT: call i8* @strchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13), i8** @chp, align 4 +; CHECK-NEXT: ret void +; %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strchr(i8* %src, i32 65280) @@ -67,11 +74,12 @@ ; Check transformation strchr(p, 0) -> p + strlen(p) define void @test_simplify6(i8* %str) { -; CHECK: %strlen = call i32 @strlen(i8* %str) -; CHECK-NOT: call i8* @strchr -; CHECK: %strchr = getelementptr i8, i8* %str, i32 %strlen -; CHECK: store i8* %strchr, i8** @chp, align 4 -; CHECK: ret void +; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]]) +; CHECK-NEXT: [[STRCHR:%.*]] = getelementptr i8, i8* [[STR]], i32 [[STRLEN]] +; CHECK-NEXT: store i8* [[STRCHR]], i8** @chp, align 4 +; CHECK-NEXT: ret void +; %dst = call i8* @strchr(i8* %str, i32 0) store i8* %dst, i8** @chp @@ -80,17 +88,38 @@ ; Check transformation strchr("\r\n", C) != nullptr -> (C & 9217) != 0 define i1 @test_simplify7(i32 %C) { -; CHECK-LABEL: @test_simplify7 -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 %C to i16 -; CHECK-NEXT: [[TRUNC_AND:%.*]] = and i16 [[TRUNC]], 255 -; CHECK-NEXT: %memchr.bounds = icmp ult i16 [[TRUNC_AND]], 16 -; CHECK-NEXT: [[SHL:%.*]] = shl i16 1, [[TRUNC_AND]] -; CHECK-NEXT: [[AND:%.*]] = and i16 [[SHL]], 9217 -; CHECK-NEXT: %memchr.bits = icmp ne i16 [[AND]], 0 -; CHECK-NEXT: %memchr1 = and i1 %memchr.bounds, %memchr.bits -; CHECK-NEXT: ret i1 %memchr1 +; CHECK-LABEL: @test_simplify7( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i16 +; CHECK-NEXT: [[TMP2:%.*]] = and i16 [[TMP1]], 255 +; CHECK-NEXT: [[MEMCHR_BOUNDS:%.*]] = icmp ult i16 [[TMP2]], 16 +; CHECK-NEXT: [[TMP3:%.*]] = shl i16 1, [[TMP2]] +; CHECK-NEXT: [[TMP4:%.*]] = and i16 [[TMP3]], 9217 +; CHECK-NEXT: [[MEMCHR_BITS:%.*]] = icmp ne i16 [[TMP4]], 0 +; CHECK-NEXT: [[MEMCHR1:%.*]] = and i1 [[MEMCHR_BOUNDS]], [[MEMCHR_BITS]] +; CHECK-NEXT: ret i1 [[MEMCHR1]] +; %dst = call i8* @strchr(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @newlines, i64 0, i64 0), i32 %C) %cmp = icmp ne i8* %dst, null ret i1 %cmp } + +define i8* @test1(i8* %str, i32 %c) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strchr(i8* nonnull dereferenceable(1) [[STR:%.*]], i32 [[C:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @strchr(i8* %str, i32 %c) + ret i8* %ret +} + +define i8* @test2(i8* %str, i32 %c) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strchr(i8* [[STR:%.*]], i32 [[C:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @strchr(i8* %str, i32 %c) + ret i8* %ret +} Index: test/Transforms/InstCombine/strcmp-1.ll =================================================================== --- test/Transforms/InstCombine/strcmp-1.ll +++ test/Transforms/InstCombine/strcmp-1.ll @@ -97,12 +97,12 @@ ; CHECK: ret i32 %memcmp ; NOBCMP-LABEL: @test5( ; NOBCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) -; NOBCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; NOBCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull dereferenceable(5) [[STR2]], i32 5) ; NOBCMP-NEXT: ret i32 [[MEMCMP]] ; ; BCMP-LABEL: @test5( ; BCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) -; BCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; BCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull dereferenceable(5) [[STR2]], i32 5) ; BCMP-NEXT: ret i32 [[MEMCMP]] ; %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -131,13 +131,13 @@ define i1 @test7(i1 %b) { ; NOBCMP-LABEL: @test7( ; NOBCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) -; NOBCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; NOBCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull dereferenceable(5) [[STR2]], i32 5) ; NOBCMP-NEXT: [[RES:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; NOBCMP-NEXT: ret i1 [[RES]] ; ; BCMP-LABEL: @test7( ; BCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) -; BCMP-NEXT: [[BCMP:%.*]] = call i32 @bcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; BCMP-NEXT: [[BCMP:%.*]] = call i32 @bcmp(i8* nonnull dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull dereferenceable(5) [[STR2]], i32 5) ; BCMP-NEXT: [[RES:%.*]] = icmp eq i32 [[BCMP]], 0 ; BCMP-NEXT: ret i1 [[RES]] ; Index: test/Transforms/InstCombine/strcmp-memcmp.ll =================================================================== --- test/Transforms/InstCombine/strcmp-memcmp.ll +++ test/Transforms/InstCombine/strcmp-memcmp.ll @@ -11,7 +11,7 @@ define i32 @strcmp_memcmp([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -28,7 +28,7 @@ define i32 @strcmp_memcmp2([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp2( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -43,7 +43,7 @@ define i32 @strcmp_memcmp3([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp3( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -58,7 +58,7 @@ define i32 @strcmp_memcmp4([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp4( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -73,7 +73,7 @@ define i32 @strcmp_memcmp5([5 x i8]* dereferenceable (5) %buf) { ; CHECK-LABEL: @strcmp_memcmp5( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [5 x i8], [5 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -88,7 +88,7 @@ define i32 @strcmp_memcmp6([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp6( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -103,7 +103,7 @@ define i32 @strcmp_memcmp7([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp7( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[MEMCMP_LOBIT:%.*]] = lshr i32 [[MEMCMP]], 31 ; CHECK-NEXT: ret i32 [[MEMCMP_LOBIT]] ; @@ -117,7 +117,7 @@ define i32 @strcmp_memcmp8([4 x i8]* dereferenceable (4) %buf) { ; CHECK-LABEL: @strcmp_memcmp8( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -132,7 +132,7 @@ define i32 @strcmp_memcmp9([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp9( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -148,7 +148,7 @@ define i32 @strncmp_memcmp([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[STRING]], i8* dereferenceable(2) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 2) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[STRING]], i8* nonnull dereferenceable(2) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 2) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -165,7 +165,7 @@ define i32 @strncmp_memcmp2([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp2( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -180,7 +180,7 @@ define i32 @strncmp_memcmp3([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp3( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -195,7 +195,7 @@ define i32 @strncmp_memcmp4([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp4( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -210,7 +210,7 @@ define i32 @strncmp_memcmp5([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp5( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -226,7 +226,7 @@ define i32 @strncmp_memcmp6([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp6( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -241,7 +241,7 @@ define i32 @strncmp_memcmp7([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp7( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -256,7 +256,7 @@ define i32 @strncmp_memcmp8([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp8( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(3) [[STRING]], i8* dereferenceable(3) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 3) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(3) [[STRING]], i8* nonnull dereferenceable(3) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 3) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -271,7 +271,7 @@ define i32 @strncmp_memcmp9([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp9( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -286,7 +286,7 @@ define i32 @strncmp_memcmp10([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp10( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[MEMCMP_LOBIT:%.*]] = lshr i32 [[MEMCMP]], 31 ; CHECK-NEXT: ret i32 [[MEMCMP_LOBIT]] ; @@ -300,7 +300,7 @@ define i32 @strncmp_memcmp11([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp11( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -315,7 +315,7 @@ define i32 @strncmp_memcmp12([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp12( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -330,7 +330,7 @@ define i32 @strncmp_memcmp13([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp13( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[STRING]], i8* dereferenceable(2) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 2) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[STRING]], i8* nonnull dereferenceable(2) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 2) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -345,7 +345,7 @@ define i32 @strncmp_memcmp14([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp14( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -361,7 +361,7 @@ define i32 @strcmp_memcmp_bad([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp_bad( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull dereferenceable(1) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CALL]], 3 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -376,7 +376,7 @@ define i32 @strcmp_memcmp_bad2([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp_bad2( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]]) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(1) [[STRING]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 3 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -391,7 +391,7 @@ define i32 @strcmp_memcmp_bad3([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strcmp_memcmp_bad3( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull dereferenceable(1) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) ; CHECK-NEXT: ret i32 [[CALL]] ; %string = getelementptr inbounds [12 x i8], [12 x i8]* %buf, i64 0, i64 0 @@ -402,7 +402,7 @@ define i32 @strcmp_memcmp_bad4(i8* nocapture readonly %buf) { ; CHECK-LABEL: @strcmp_memcmp_bad4( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @strcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* [[BUF:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @strcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(1) [[BUF:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -417,7 +417,7 @@ define i32 @strcmp_memcmp_bad5([3 x i8]* dereferenceable (3) %buf) { ; CHECK-LABEL: @strcmp_memcmp_bad5( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [3 x i8], [3 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull dereferenceable(1) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -432,7 +432,7 @@ define i32 @strcmp_memcmp_bad6([4 x i8]* dereferenceable (4) %buf, i8* nocapture readonly %k) { ; CHECK-LABEL: @strcmp_memcmp_bad6( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull [[STRING]], i8* [[K:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull dereferenceable(1) [[STRING]], i8* nonnull dereferenceable(1) [[K:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -446,7 +446,7 @@ define i32 @strcmp_memcmp_bad7(i8* nocapture readonly %k) { ; CHECK-LABEL: @strcmp_memcmp_bad7( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @strcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* [[K:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @strcmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(1) [[K:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -460,7 +460,7 @@ define i32 @strcmp_memcmp_bad8([4 x i8]* dereferenceable (4) %buf) { ; CHECK-LABEL: @strcmp_memcmp_bad8( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull dereferenceable(1) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) ; CHECK-NEXT: tail call void @use(i32 [[CALL]]) ; CHECK-NEXT: ret i32 0 ; @@ -473,7 +473,7 @@ define i32 @strncmp_memcmp_bad([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp_bad( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 5) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(1) [[STRING]], i64 5) ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CALL]], 3 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -489,7 +489,7 @@ define i32 @strncmp_memcmp_bad1([12 x i8]* dereferenceable (12) %buf) { ; CHECK-LABEL: @strncmp_memcmp_bad1( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 5) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(1) [[STRING]], i64 5) ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 3 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -504,7 +504,7 @@ define i32 @strncmp_memcmp_bad2([12 x i8]* dereferenceable (12) %buf, i64 %n) { ; CHECK-LABEL: @strncmp_memcmp_bad2( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 [[N:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* [[STRING]], i64 [[N:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 1 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -518,7 +518,7 @@ define i32 @strncmp_memcmp_bad3(i8* nocapture readonly %k) { ; CHECK-LABEL: @strncmp_memcmp_bad3( -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @strncmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* [[K:%.*]], i64 2) +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @strncmp(i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(1) [[K:%.*]], i64 2) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] @@ -532,7 +532,7 @@ define i32 @strncmp_memcmp_bad4([4 x i8]* dereferenceable (4) %buf) { ; CHECK-LABEL: @strncmp_memcmp_bad4( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 2) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strncmp(i8* nonnull dereferenceable(1) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 2) ; CHECK-NEXT: tail call void @use(i32 [[CALL]]) ; CHECK-NEXT: ret i32 0 ; @@ -545,7 +545,7 @@ define i32 @strcmp_memcmp_msan([12 x i8]* dereferenceable (12) %buf) sanitize_memory { ; CHECK-LABEL: @strcmp_memcmp_msan( ; CHECK-NEXT: [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(i8* nonnull dereferenceable(1) [[STRING]], i8* nonnull dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0)) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] Index: test/Transforms/InstCombine/strcpy-1.ll =================================================================== --- test/Transforms/InstCombine/strcpy-1.ll +++ test/Transforms/InstCombine/strcpy-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strcpy library call simplifier works correctly. ; rdar://6839935 ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -14,32 +15,50 @@ define void @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 call i8* @strcpy(i8* %dst, i8* %src) -; CHECK: @llvm.memcpy.p0i8.p0i8.i32 ret void } define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0) +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %ret = call i8* @strcpy(i8* %dst, i8* %dst) -; CHECK: ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0) ret i8* %ret } + +define void @test_simplify3(i8* %dst) { +; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(80) [[DST:%.*]], i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret void +; + + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + + call i8* @strcpy(i8* dereferenceable(80) %dst, i8* %src) + ret void +} + define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strcpy(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @b, i32 0, i32 0)) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [32 x i8], [32 x i8]* @b, i32 0, i32 0 %ret = call i8* @strcpy(i8* %dst, i8* %src) -; CHECK: call i8* @strcpy ret i8* %ret } Index: test/Transforms/InstCombine/strcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/strcpy_chk-1.ll +++ test/Transforms/InstCombine/strcpy_chk-1.ll @@ -14,7 +14,7 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -26,7 +26,7 @@ define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -38,7 +38,7 @@ define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -52,7 +52,7 @@ define i8* @test_simplify4() { ; CHECK-LABEL: @test_simplify4( -; CHECK-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0)) +; CHECK-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0)) ; CHECK-NEXT: ret i8* [[STRCPY]] ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 Index: test/Transforms/InstCombine/strcspn-1.ll =================================================================== --- test/Transforms/InstCombine/strcspn-1.ll +++ test/Transforms/InstCombine/strcspn-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strcspn library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -14,44 +15,48 @@ define i64 @test_simplify1(i8* %str) { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]]) +; CHECK-NEXT: ret i64 [[STRLEN]] +; %pat = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 %ret = call i64 @strcspn(i8* %str, i8* %pat) -; CHECK-NEXT: [[VAR:%[a-z]+]] = call i64 @strlen(i8* %str) ret i64 %ret -; CHECK-NEXT: ret i64 [[VAR]] } ; Check strcspn("", s) -> 0. define i64 @test_simplify2(i8* %pat) { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: ret i64 0 +; %str = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 %ret = call i64 @strcspn(i8* %str, i8* %pat) ret i64 %ret -; CHECK-NEXT: ret i64 0 } ; Check strcspn(s1, s2), where s1 and s2 are constants. define i64 @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: ret i64 0 +; %str = getelementptr [6 x i8], [6 x i8]* @abcba, i32 0, i32 0 %pat = getelementptr [4 x i8], [4 x i8]* @abc, i32 0, i32 0 %ret = call i64 @strcspn(i8* %str, i8* %pat) ret i64 %ret -; CHECK-NEXT: ret i64 0 } ; Check cases that shouldn't be simplified. define i64 @test_no_simplify1(i8* %str, i8* %pat) { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i64 @strcspn(i8* [[STR:%.*]], i8* [[PAT:%.*]]) +; CHECK-NEXT: ret i64 [[RET]] +; %ret = call i64 @strcspn(i8* %str, i8* %pat) -; CHECK-NEXT: %ret = call i64 @strcspn(i8* %str, i8* %pat) ret i64 %ret -; CHECK-NEXT: ret i64 %ret } Index: test/Transforms/InstCombine/strlen-1.ll =================================================================== --- test/Transforms/InstCombine/strlen-1.ll +++ test/Transforms/InstCombine/strlen-1.ll @@ -100,7 +100,7 @@ define i32 @test_simplify9(i1 %x) { ; CHECK-LABEL: @test_simplify9( -; CHECK-NEXT: [[TMP1:%.*]] = select i1 %x, i32 5, i32 6 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i32 5, i32 6 ; CHECK-NEXT: ret i32 [[TMP1]] ; %hello = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -115,7 +115,7 @@ define i32 @test_simplify10(i32 %x) { ; CHECK-LABEL: @test_simplify10( -; CHECK-NEXT: [[TMP1:%.*]] = sub i32 5, %x +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 5, [[X:%.*]] ; CHECK-NEXT: ret i32 [[TMP1]] ; %hello_p = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 %x @@ -127,7 +127,7 @@ define i32 @test_simplify11(i32 %x) { ; CHECK-LABEL: @test_simplify11( -; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 7 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 7 ; CHECK-NEXT: [[TMP1:%.*]] = sub nuw nsw i32 9, [[AND]] ; CHECK-NEXT: ret i32 [[TMP1]] ; @@ -141,7 +141,7 @@ define i32 @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( -; CHECK-NEXT: [[A_L:%.*]] = call i32 @strlen(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0)) +; CHECK-NEXT: [[A_L:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0)) ; CHECK-NEXT: ret i32 [[A_L]] ; %a_p = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 @@ -153,8 +153,8 @@ define i32 @test_no_simplify2(i32 %x) { ; CHECK-LABEL: @test_no_simplify2( -; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 %x -; CHECK-NEXT: [[HELLO_L:%.*]] = call i32 @strlen(i8* nonnull [[HELLO_P]]) +; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 [[X:%.*]] +; CHECK-NEXT: [[HELLO_L:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[HELLO_P]]) ; CHECK-NEXT: ret i32 [[HELLO_L]] ; %hello_p = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 %x @@ -164,7 +164,7 @@ define i32 @test_no_simplify2_no_null_opt(i32 %x) #0 { ; CHECK-LABEL: @test_no_simplify2_no_null_opt( -; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 %x +; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 [[X:%.*]] ; CHECK-NEXT: [[HELLO_L:%.*]] = call i32 @strlen(i8* [[HELLO_P]]) ; CHECK-NEXT: ret i32 [[HELLO_L]] ; @@ -177,9 +177,9 @@ define i32 @test_no_simplify3(i32 %x) { ; CHECK-LABEL: @test_no_simplify3( -; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 15 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 15 ; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [13 x i8], [13 x i8]* @null_hello_mid, i32 0, i32 [[AND]] -; CHECK-NEXT: [[HELLO_L:%.*]] = call i32 @strlen(i8* nonnull [[HELLO_P]]) +; CHECK-NEXT: [[HELLO_L:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[HELLO_P]]) ; CHECK-NEXT: ret i32 [[HELLO_L]] ; %and = and i32 %x, 15 @@ -190,7 +190,7 @@ define i32 @test_no_simplify3_on_null_opt(i32 %x) #0 { ; CHECK-LABEL: @test_no_simplify3_on_null_opt( -; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 15 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 15 ; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [13 x i8], [13 x i8]* @null_hello_mid, i32 0, i32 [[AND]] ; CHECK-NEXT: [[HELLO_L:%.*]] = call i32 @strlen(i8* [[HELLO_P]]) ; CHECK-NEXT: ret i32 [[HELLO_L]] @@ -201,4 +201,22 @@ ret i32 %hello_l } +define i32 @test1(i8* %str) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[LEN:%.*]] = tail call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]]) #1 +; CHECK-NEXT: ret i32 [[LEN]] +; + %len = tail call i32 @strlen(i8* %str) nounwind + ret i32 %len +} + +define i32 @test2(i8* %str) #0 { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[LEN:%.*]] = tail call i32 @strlen(i8* [[STR:%.*]]) #1 +; CHECK-NEXT: ret i32 [[LEN]] +; + %len = tail call i32 @strlen(i8* %str) nounwind + ret i32 %len +} + attributes #0 = { "null-pointer-is-valid"="true" } Index: test/Transforms/InstCombine/strncat-2.ll =================================================================== --- test/Transforms/InstCombine/strncat-2.ll +++ test/Transforms/InstCombine/strncat-2.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strncat libcall simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -7,13 +8,15 @@ @hello = constant [6 x i8] c"hello\00" @empty = constant [1 x i8] c"\00" @a = common global [32 x i8] zeroinitializer, align 1 - declare i8* @strncat(i8*, i8*, i32) define void @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NOT: call i8* @strncat -; CHECK: ret void +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0)) +; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 [[STRLEN]] +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) [[ENDPTR]], i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -23,7 +26,8 @@ define void @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: ret void +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0 @@ -33,7 +37,8 @@ define void @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: ret void +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -43,11 +48,66 @@ define void @test_nosimplify1() { ; CHECK-LABEL: @test_nosimplify1( -; CHECK: call i8* @strncat -; CHECK: ret void +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncat(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 1) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 call i8* @strncat(i8* %dst, i8* %src, i32 1) ret void } + +; strncat(nonnull x, nonnull y, n) -> strncat(nonnull x, y, n) +define i8* @test1(i8* %str1, i8* %str2, i32 %n) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[TEMP1:%.*]] = call i8* @strncat(i8* nonnull dereferenceable(1) [[STR1:%.*]], i8* [[STR2:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[TEMP1]] +; + + %temp1 = call i8* @strncat(i8* nonnull %str1, i8* nonnull %str2, i32 %n) + ret i8* %temp1 +} + +; strncat(x, y, 0) -> x +define i8* @test2(i8* %str1, i8* %str2, i32 %n) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: ret i8* [[STR1:%.*]] +; + + %temp1 = call i8* @strncat(i8* %str1, i8* %str2, i32 0) + ret i8* %temp1 +} + +; strncat(x, y, 5) -> strncat(nonnull x, nonnull y, 5) +define i8* @test3(i8* %str1, i8* %str2, i32 %n) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[TEMP1:%.*]] = call i8* @strncat(i8* nonnull dereferenceable(1) [[STR1:%.*]], i8* nonnull dereferenceable(1) [[STR2:%.*]], i32 5) +; CHECK-NEXT: ret i8* [[TEMP1]] +; + + %temp1 = call i8* @strncat(i8* %str1, i8* %str2, i32 5) + ret i8* %temp1 +} + +define i8* @test4(i8* %str1, i8* %str2, i32 %n) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @test4( +; CHECK-NEXT: [[TEMP1:%.*]] = call i8* @strncat(i8* [[STR1:%.*]], i8* [[STR2:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[TEMP1]] +; + + %temp1 = call i8* @strncat(i8* %str1, i8* %str2, i32 %n) + ret i8* %temp1 +} + +define i8* @test5(i8* %str, i32 %n) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]]) +; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr i8, i8* [[STR]], i32 [[STRLEN]] +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) [[ENDPTR]], i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret i8* [[STR]] +; + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + %temp1 = call i8* @strncat(i8* %str, i8* %src, i32 10) + ret i8* %temp1 +} Index: test/Transforms/InstCombine/strncat-3.ll =================================================================== --- test/Transforms/InstCombine/strncat-3.ll +++ test/Transforms/InstCombine/strncat-3.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strncat libcall simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -12,8 +13,9 @@ define void @test_nosimplify1() { ; CHECK-LABEL: @test_nosimplify1( -; CHECK: call i16* @strncat -; CHECK: ret void +; CHECK-NEXT: [[TMP1:%.*]] = call i16* @strncat(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 13) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 Index: test/Transforms/InstCombine/strncmp-1.ll =================================================================== --- test/Transforms/InstCombine/strncmp-1.ll +++ test/Transforms/InstCombine/strncmp-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strncmp library call simplifier works correctly. ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -13,10 +14,11 @@ ; strncmp("", x, n) -> -*x define i32 @test1(i8* %str2) { ; CHECK-LABEL: @test1( -; CHECK: %strcmpload = load i8, i8* %str -; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: %2 = sub nsw i32 0, %1 -; CHECK: ret i32 %2 +; CHECK-NEXT: [[STRCMPLOAD:%.*]] = load i8, i8* [[STR2:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] +; CHECK-NEXT: ret i32 [[TMP2]] +; %str1 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0 %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 10) @@ -26,9 +28,10 @@ ; strncmp(x, "", n) -> *x define i32 @test2(i8* %str1) { ; CHECK-LABEL: @test2( -; CHECK: %strcmpload = load i8, i8* %str1 -; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: ret i32 %1 +; CHECK-NEXT: [[STRCMPLOAD:%.*]] = load i8, i8* [[STR1:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; CHECK-NEXT: ret i32 [[TMP1]] +; %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0 %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 10) @@ -38,7 +41,8 @@ ; strncmp(x, y, n) -> cnst define i32 @test3() { ; CHECK-LABEL: @test3( -; CHECK: ret i32 -1 +; CHECK-NEXT: ret i32 -1 +; %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0 %str2 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -48,7 +52,8 @@ define i32 @test4() { ; CHECK-LABEL: @test4( -; CHECK: ret i32 1 +; CHECK-NEXT: ret i32 1 +; %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0 %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0 @@ -58,7 +63,8 @@ define i32 @test5() { ; CHECK-LABEL: @test5( -; CHECK: ret i32 0 +; CHECK-NEXT: ret i32 0 +; %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0 %str2 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -69,12 +75,13 @@ ; strncmp(x,y,1) -> memcmp(x,y,1) define i32 @test6(i8* %str1, i8* %str2) { ; CHECK-LABEL: @test6( -; CHECK: [[LOAD1:%[a-z]+]] = load i8, i8* %str1, align 1 -; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 -; CHECK: [[LOAD2:%[a-z]+]] = load i8, i8* %str2, align 1 -; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 -; CHECK: [[RET:%[a-z]+]] = sub nsw i32 [[ZEXT1]], [[ZEXT2]] -; CHECK: ret i32 [[RET]] +; CHECK-NEXT: [[LHSC:%.*]] = load i8, i8* [[STR1:%.*]], align 1 +; CHECK-NEXT: [[LHSV:%.*]] = zext i8 [[LHSC]] to i32 +; CHECK-NEXT: [[RHSC:%.*]] = load i8, i8* [[STR2:%.*]], align 1 +; CHECK-NEXT: [[RHSV:%.*]] = zext i8 [[RHSC]] to i32 +; CHECK-NEXT: [[CHARDIFF:%.*]] = sub nsw i32 [[LHSV]], [[RHSV]] +; CHECK-NEXT: ret i32 [[CHARDIFF]] +; %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1) ret i32 %temp1 @@ -83,7 +90,8 @@ ; strncmp(x,y,0) -> 0 define i32 @test7(i8* %str1, i8* %str2) { ; CHECK-LABEL: @test7( -; CHECK: ret i32 0 +; CHECK-NEXT: ret i32 0 +; %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 0) ret i32 %temp1 @@ -92,8 +100,51 @@ ; strncmp(x,x,n) -> 0 define i32 @test8(i8* %str, i32 %n) { ; CHECK-LABEL: @test8( -; CHECK: ret i32 0 +; CHECK-NEXT: ret i32 0 +; %temp1 = call i32 @strncmp(i8* %str, i8* %str, i32 %n) ret i32 %temp1 } + +; strncmp(nonnull x, nonnull y, n) -> strncmp(x, y, n) +define i32 @test9(i8* %str1, i8* %str2, i32 %n) { +; CHECK-LABEL: @test9( +; CHECK-NEXT: [[TEMP1:%.*]] = call i32 @strncmp(i8* [[STR1:%.*]], i8* [[STR2:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i32 [[TEMP1]] +; + + %temp1 = call i32 @strncmp(i8* nonnull %str1, i8* nonnull %str2, i32 %n) + ret i32 %temp1 +} + +; strncmp(nonnull x, nonnull y, 0) -> 0 +define i32 @test10(i8* %str1, i8* %str2, i32 %n) { +; CHECK-LABEL: @test10( +; CHECK-NEXT: ret i32 0 +; + + %temp1 = call i32 @strncmp(i8* nonnull %str1, i8* nonnull %str2, i32 0) + ret i32 %temp1 +} + +; strncmp(x, y, 5) -> strncmp(nonnull x, nonnull y, 5) +define i32 @test11(i8* %str1, i8* %str2, i32 %n) { +; CHECK-LABEL: @test11( +; CHECK-NEXT: [[TEMP1:%.*]] = call i32 @strncmp(i8* nonnull dereferenceable(1) [[STR1:%.*]], i8* nonnull dereferenceable(1) [[STR2:%.*]], i32 5) +; CHECK-NEXT: ret i32 [[TEMP1]] +; + + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 5) + ret i32 %temp1 +} + +define i32 @test12(i8* %str1, i8* %str2, i32 %n) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @test12( +; CHECK-NEXT: [[TEMP1:%.*]] = call i32 @strncmp(i8* [[STR1:%.*]], i8* [[STR2:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i32 [[TEMP1]] +; + + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 %n) + ret i32 %temp1 +} Index: test/Transforms/InstCombine/strncpy-1.ll =================================================================== --- test/Transforms/InstCombine/strncpy-1.ll +++ test/Transforms/InstCombine/strncpy-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strncpy library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -17,8 +18,15 @@ define i32 @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NOT: call i8* @strncpy -; CHECK: call i32 @puts +; CHECK-NEXT: [[TARGET:%.*]] = alloca [1024 x i8], align 1 +; CHECK-NEXT: [[ARG1:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[TARGET]], i32 0, i32 0 +; CHECK-NEXT: store i8 0, i8* [[ARG1]], align 1 +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) [[ARG1]], i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(42) [[ARG1]], i8 0, i32 42, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(42) [[ARG1]], i8 0, i32 42, i1 false) +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) [[ARG1]]) +; CHECK-NEXT: ret i32 0 +; %target = alloca [1024 x i8] %arg1 = getelementptr [1024 x i8], [1024 x i8]* %target, i32 0, i32 0 store i8 0, i8* %arg1 @@ -40,11 +48,13 @@ define void @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull align 1 dereferenceable(32) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8 0, i32 32, i1 false) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 call i8* @strncpy(i8* %dst, i8* %src, i32 32) -; CHECK: call void @llvm.memset.p0i8.i32 ret void } @@ -52,23 +62,56 @@ define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0) +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 %ret = call i8* @strncpy(i8* %dst, i8* %src, i32 0) ret i8* %ret -; CHECK: ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0) } ; Check strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant]. define void @test_simplify4() { ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 call i8* @strncpy(i8* %dst, i8* %src, i32 6) -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 + ret void +} + +define void @test_simplify5(i8* %dst) { +; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncpy(i8* nonnull dereferenceable(8) [[DST:%.*]], i8* nonnull dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 32) +; CHECK-NEXT: ret void +; + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + call i8* @strncpy(i8* dereferenceable(8) %dst, i8* %src, i32 32) + ret void +} + +define void @test_simplify6(i8* %dst) { +; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncpy(i8* nonnull dereferenceable(80) [[DST:%.*]], i8* nonnull dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 32) +; CHECK-NEXT: ret void +; + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + call i8* @strncpy(i8* dereferenceable(80) %dst, i8* %src, i32 32) + ret void +} + +define void @test_simplify7(i8* %dst, i32 %n) { +; CHECK-LABEL: @test_simplify7( +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncpy(i8* nonnull dereferenceable(80) [[DST:%.*]], i8* getelementptr inbounds ([1 x i8], [1 x i8]* @null, i32 0, i32 0), i32 [[N:%.*]]) +; CHECK-NEXT: ret void +; + %src = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 + call i8* @strncpy(i8* dereferenceable(80) %dst, i8* %src, i32 %n) ret void } @@ -76,20 +119,33 @@ define void @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncpy(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @b, i32 0, i32 0), i32 32) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [32 x i8], [32 x i8]* @b, i32 0, i32 0 call i8* @strncpy(i8* %dst, i8* %src, i32 32) -; CHECK: call i8* @strncpy ret void } define void @test_no_simplify2() { ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncpy(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 8) +; CHECK-NEXT: ret void +; %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 call i8* @strncpy(i8* %dst, i8* %src, i32 8) -; CHECK: call i8* @strncpy ret void } + +define i8* @test1(i8* %dst, i8* %src, i32 %n) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strncpy(i8* nonnull dereferenceable(1) [[DST:%.*]], i8* [[SRC:%.*]], i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + %ret = call i8* @strncpy(i8* nonnull %dst, i8* nonnull %src, i32 %n) + ret i8* %ret +} Index: test/Transforms/InstCombine/strncpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/strncpy_chk-1.ll +++ test/Transforms/InstCombine/strncpy_chk-1.ll @@ -14,7 +14,7 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -26,7 +26,7 @@ define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 @@ -38,7 +38,7 @@ define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: [[STRNCPY:%.*]] = call i8* @strncpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 12) +; CHECK-NEXT: [[STRNCPY:%.*]] = call i8* @strncpy(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 12) ; CHECK-NEXT: ret i8* [[STRNCPY]] ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 Index: test/Transforms/InstCombine/strpbrk-1.ll =================================================================== --- test/Transforms/InstCombine/strpbrk-1.ll +++ test/Transforms/InstCombine/strpbrk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strpbrk library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -14,55 +15,60 @@ define i8* @test_simplify1(i8* %str) { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: ret i8* null +; %pat = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 %ret = call i8* @strpbrk(i8* %str, i8* %pat) ret i8* %ret -; CHECK-NEXT: ret i8* null } ; Check strpbrk("", s) -> NULL. define i8* @test_simplify2(i8* %pat) { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: ret i8* null +; %str = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 %ret = call i8* @strpbrk(i8* %str, i8* %pat) ret i8* %ret -; CHECK-NEXT: ret i8* null } ; Check strpbrk(s1, s2), where s1 and s2 are constants. define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: ret i8* getelementptr inbounds ([12 x i8], [12 x i8]* @hello, i32 0, i32 6) +; %str = getelementptr [12 x i8], [12 x i8]* @hello, i32 0, i32 0 %pat = getelementptr [2 x i8], [2 x i8]* @w, i32 0, i32 0 %ret = call i8* @strpbrk(i8* %str, i8* %pat) ret i8* %ret -; CHECK-NEXT: ret i8* getelementptr inbounds ([12 x i8], [12 x i8]* @hello, i32 0, i32 6) } ; Check strpbrk(s, "a") -> strchr(s, 'a'). define i8* @test_simplify4(i8* %str) { ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: [[STRCHR:%.*]] = call i8* @strchr(i8* nonnull dereferenceable(1) [[STR:%.*]], i32 119) +; CHECK-NEXT: ret i8* [[STRCHR]] +; %pat = getelementptr [2 x i8], [2 x i8]* @w, i32 0, i32 0 %ret = call i8* @strpbrk(i8* %str, i8* %pat) -; CHECK-NEXT: [[VAR:%[a-z]+]] = call i8* @strchr(i8* %str, i32 119) ret i8* %ret -; CHECK-NEXT: ret i8* [[VAR]] } ; Check cases that shouldn't be simplified. define i8* @test_no_simplify1(i8* %str, i8* %pat) { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strpbrk(i8* [[STR:%.*]], i8* [[PAT:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; %ret = call i8* @strpbrk(i8* %str, i8* %pat) -; CHECK-NEXT: %ret = call i8* @strpbrk(i8* %str, i8* %pat) ret i8* %ret -; CHECK-NEXT: ret i8* %ret } Index: test/Transforms/InstCombine/strrchr-1.ll =================================================================== --- test/Transforms/InstCombine/strrchr-1.ll +++ test/Transforms/InstCombine/strrchr-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strrchr library call simplifier works correctly. ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -10,9 +11,10 @@ declare i8* @strrchr(i8*, i32) define void @test_simplify1() { -; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 6) -; CHECK-NOT: call i8* @strrchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 6), i8** @chp, align 4 +; CHECK-NEXT: ret void +; %str = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strrchr(i8* %str, i32 119) @@ -21,9 +23,10 @@ } define void @test_simplify2() { -; CHECK: store i8* null, i8** @chp, align 4 -; CHECK-NOT: call i8* @strrchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: store i8* null, i8** @chp, align 4 +; CHECK-NEXT: ret void +; %str = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 %dst = call i8* @strrchr(i8* %str, i32 119) @@ -32,9 +35,10 @@ } define void @test_simplify3() { -; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13) -; CHECK-NOT: call i8* @strrchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13), i8** @chp, align 4 +; CHECK-NEXT: ret void +; %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strrchr(i8* %src, i32 0) @@ -43,9 +47,10 @@ } define void @test_simplify4() { -; CHECK: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13) -; CHECK-NOT: call i8* @strrchr -; CHECK: ret void +; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 13), i8** @chp, align 4 +; CHECK-NEXT: ret void +; %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strrchr(i8* %src, i32 65280) @@ -55,11 +60,33 @@ define void @test_nosimplify1(i32 %chr) { ; CHECK-LABEL: @test_nosimplify1( -; CHECK: call i8* @strrchr -; CHECK: ret void +; CHECK-NEXT: [[DST:%.*]] = call i8* @strrchr(i8* nonnull dereferenceable(1) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]]) +; CHECK-NEXT: store i8* [[DST]], i8** @chp, align 4 +; CHECK-NEXT: ret void +; %src = getelementptr [14 x i8], [14 x i8]* @hello, i32 0, i32 0 %dst = call i8* @strrchr(i8* %src, i32 %chr) store i8* %dst, i8** @chp ret void } + +define i8* @test1(i8* %str, i32 %c) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strrchr(i8* nonnull dereferenceable(1) [[STR:%.*]], i32 [[C:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @strrchr(i8* %str, i32 %c) + ret i8* %ret +} + +define i8* @test2(i8* %str, i32 %c) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strrchr(i8* [[STR:%.*]], i32 [[C:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + + %ret = call i8* @strrchr(i8* %str, i32 %c) + ret i8* %ret +} Index: test/Transforms/InstCombine/strstr-1.ll =================================================================== --- test/Transforms/InstCombine/strstr-1.ll +++ test/Transforms/InstCombine/strstr-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strstr library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -15,51 +16,75 @@ define i8* @test_simplify1(i8* %str) { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: ret i8* [[STR:%.*]] +; %pat = getelementptr inbounds [1 x i8], [1 x i8]* @.str, i32 0, i32 0 %ret = call i8* @strstr(i8* %str, i8* %pat) ret i8* %ret -; CHECK-NEXT: ret i8* %str } ; Check strstr(str, "a") -> strchr(str, 'a'). define i8* @test_simplify2(i8* %str) { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: [[STRCHR:%.*]] = call i8* @strchr(i8* nonnull dereferenceable(1) [[STR:%.*]], i32 97) +; CHECK-NEXT: ret i8* [[STRCHR]] +; %pat = getelementptr inbounds [2 x i8], [2 x i8]* @.str1, i32 0, i32 0 %ret = call i8* @strstr(i8* %str, i8* %pat) ret i8* %ret -; CHECK-NEXT: @strchr(i8* %str, i32 97) } ; Check strstr("abcde", "bcd") -> "abcde" + 1. define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: ret i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i64 0, i64 1) +; %str = getelementptr inbounds [6 x i8], [6 x i8]* @.str2, i32 0, i32 0 %pat = getelementptr inbounds [4 x i8], [4 x i8]* @.str3, i32 0, i32 0 %ret = call i8* @strstr(i8* %str, i8* %pat) ret i8* %ret -; CHECK-NEXT: getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i64 0, i64 1) } ; Check strstr(str, str) -> str. define i8* @test_simplify4(i8* %str) { ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: ret i8* [[STR:%.*]] +; %ret = call i8* @strstr(i8* %str, i8* %str) ret i8* %ret -; CHECK-NEXT: ret i8* %str } ; Check strstr(str, pat) == str -> strncmp(str, pat, strlen(str)) == 0. define i1 @test_simplify5(i8* %str, i8* %pat) { ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(i8* nonnull dereferenceable(1) [[PAT:%.*]]) +; CHECK-NEXT: [[STRNCMP:%.*]] = call i32 @strncmp(i8* [[STR:%.*]], i8* [[PAT]], i64 [[STRLEN]]) +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[STRNCMP]], 0 +; CHECK-NEXT: ret i1 [[CMP1]] +; %ret = call i8* @strstr(i8* %str, i8* %pat) %cmp = icmp eq i8* %ret, %str ret i1 %cmp -; CHECK: [[LEN:%[a-z]+]] = call {{i[0-9]+}} @strlen(i8* %pat) -; CHECK: [[NCMP:%[a-z]+]] = call {{i[0-9]+}} @strncmp(i8* %str, i8* %pat, {{i[0-9]+}} [[LEN]]) -; CHECK: icmp eq {{i[0-9]+}} [[NCMP]], 0 -; CHECK: ret i1 } + +define i8* @test1(i8* %str1, i8* %str2) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strstr(i8* nonnull dereferenceable(1) [[STR1:%.*]], i8* nonnull dereferenceable(1) [[STR2:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + %ret = call i8* @strstr(i8* %str1, i8* %str2) + ret i8* %ret +} + +define i8* @test2(i8* %str1, i8* %str2) "null-pointer-is-valid"="true" { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @strstr(i8* [[STR1:%.*]], i8* [[STR2:%.*]]) +; CHECK-NEXT: ret i8* [[RET]] +; + %ret = call i8* @strstr(i8* %str1, i8* %str2) + ret i8* %ret +} \ No newline at end of file