Index: include/llvm/Transforms/Utils/SimplifyLibCalls.h =================================================================== --- include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -134,9 +134,9 @@ Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemChr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B); - Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); - Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); - Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); + Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); + Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); Value *optimizeRealloc(CallInst *CI, IRBuilder<> &B); Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B); // Wrapper for all String/Memory Library Call Optimizations Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -178,6 +178,25 @@ return true; } +static bool isPositiveSize(Value *Arg) { + return isa(Arg) && cast(Arg)->getZExtValue() > 0; +} + +static bool setNonNullParam(CallInst *CI, unsigned ArgNo) { + Function *F = CI->getFunction(); + if (!F || F->nullPointerIsDefined()) + return false; + + if (CI->getArgOperand(ArgNo)->getType()->getPointerAddressSpace()) + return false; + + if (!CI->paramHasAttr(ArgNo, Attribute::NonNull)) { + CI->addParamAttr(ArgNo, Attribute::NonNull); + return true; + } + return false; +} + //===----------------------------------------------------------------------===// // String and Memory Library Call Optimizations //===----------------------------------------------------------------------===// @@ -187,6 +206,8 @@ Value *Dst = CI->getArgOperand(0); Value *Src = CI->getArgOperand(1); + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); if (Len == 0) @@ -226,6 +247,7 @@ Value *Src = CI->getArgOperand(1); uint64_t Len; + setNonNullParam(CI, 0); // We don't do anything if length is not constant. if (ConstantInt *LengthArg = dyn_cast(CI->getArgOperand(2))) Len = LengthArg->getZExtValue(); @@ -244,6 +266,9 @@ if (SrcLen == 0 || Len == 0) return Dst; + // Non-zero length case + setNonNullParam(CI, 1); + // We don't optimize this case. if (Len < SrcLen) return nullptr; @@ -365,6 +390,8 @@ TLI); } + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -424,6 +451,9 @@ TLI); } + // Non-zero length case + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -432,6 +462,8 @@ if (Dst == Src) // strcpy(x,x) -> x return Src; + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); // See if we can get the length of the input string. uint64_t Len = GetStringLength(Src); if (Len == 0) @@ -474,6 +506,7 @@ Value *Src = CI->getArgOperand(1); Value *LenOp = CI->getArgOperand(2); + setNonNullParam(CI, 0); // See if we can get the length of the input string. uint64_t SrcLen = GetStringLength(Src); if (SrcLen == 0) @@ -495,6 +528,10 @@ if (Len == 0) return Dst; // strncpy(x, y, 0) -> x + // Non-zero length case + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); + // Let strncpy handle the zero padding if (Len > SrcLen + 1) return nullptr; @@ -597,7 +634,11 @@ } Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) { - return optimizeStringLength(CI, B, 8); + if (Value *V = optimizeStringLength(CI, B, 8)) + return V; + + setNonNullParam(CI, 0); + return nullptr; } Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilder<> &B) { @@ -744,6 +785,9 @@ Value *StrChr = emitStrChr(CI->getArgOperand(0), ToFindStr[0], B, TLI); return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : nullptr; } + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -905,17 +949,39 @@ return ConstantInt::get(CI->getType(), Ret); } + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } -Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B, + bool isIntrinsic) { + if (isIntrinsic) { + if (!isPositiveSize(CI->getArgOperand(2))) + return nullptr; + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); + return nullptr; + } + // memcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n) B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, CI->getArgOperand(2)); return CI->getArgOperand(0); } -Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B, + bool isIntrinsic) { + if (isIntrinsic) { + if (!isPositiveSize(CI->getArgOperand(2))) + return nullptr; + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); + return nullptr; + } + // memmove(x, y, n) -> llvm.memmove(align 1 x, align 1 y, n) B.CreateMemMove(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, CI->getArgOperand(2)); @@ -968,7 +1034,16 @@ return Calloc; } -Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B, + bool isIntrinsic) { + if (isIntrinsic) { + if (!isPositiveSize(CI->getArgOperand(2))) + return nullptr; + + setNonNullParam(CI, 0); + return nullptr; + } + if (auto *Calloc = foldMallocMemset(CI, B)) return Calloc; @@ -1880,7 +1955,11 @@ if (!getConstantStringInfo(CI->getArgOperand(0), Str)) return nullptr; - return convertStrToNumber(CI, Str, 10); + if (Value *V = convertStrToNumber(CI, Str, 10)) + return V; + + setNonNullParam(CI, 0); + return nullptr; } Value *LibCallSimplifier::optimizeStrtol(CallInst *CI, IRBuilder<> &B) { @@ -1891,10 +1970,11 @@ if (!isa(CI->getArgOperand(1))) return nullptr; - if (ConstantInt *CInt = dyn_cast(CI->getArgOperand(2))) { - return convertStrToNumber(CI, Str, CInt->getSExtValue()); - } + if (ConstantInt *CInt = dyn_cast(CI->getArgOperand(2))) + if (Value *V = convertStrToNumber(CI, Str, CInt->getSExtValue())) + return V; + setNonNullParam(CI, 0); return nullptr; } @@ -2016,6 +2096,8 @@ B.Insert(New); return New; } + + setNonNullParam(CI, 0); return nullptr; } @@ -2095,6 +2177,9 @@ B.Insert(New); return New; } + + setNonNullParam(CI, 0); + setNonNullParam(CI, 1); return nullptr; } @@ -2182,6 +2267,7 @@ return V; } + setNonNullParam(CI, 2); return nullptr; } @@ -2363,6 +2449,7 @@ return B.CreateIntCast(Res, CI->getType(), true); } + setNonNullParam(CI, 0); return nullptr; } @@ -2574,6 +2661,12 @@ case Intrinsic::sqrt: return optimizeSqrt(CI, Builder); // TODO: Use foldMallocMemset() with memset intrinsic. + case Intrinsic::memset: + return optimizeMemSet(CI, Builder, true); + case Intrinsic::memcpy: + return optimizeMemCpy(CI, Builder, true); + case Intrinsic::memmove: + return optimizeMemMove(CI, Builder, true); default: return nullptr; } 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 getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i32 [[T0ARG]], i32 [[U0ARG]]) ; CHECK: ret define void @test13() { entry: @@ -271,8 +271,8 @@ %arrayidx6 = getelementptr inbounds [3 x i8], [3 x i8]* %u, i64 0, i64 0 %tmp5 = load i8, i8* %arrayidx6, align 1 %conv7 = zext i8 %tmp5 to i32 - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32 %conv, i32 %conv7) + %call = call i32 (i8*, ...) @printf(i8* nonnull getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32 %conv, i32 %conv7) ret void } -declare i32 @printf(i8*, ...) +declare i32 @printf(i8*, ...) \ No newline at end of file Index: test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll =================================================================== --- test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll +++ test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll @@ -6,7 +6,7 @@ ; it has a TBAA tag which declares that it is unrelated. ; CHECK: @foo -; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %p, i8* align 1 %q, i64 16, i1 false), !tbaa !0 +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 %p, i8* nonnull align 1 %q, i64 16, i1 false), !tbaa !0 ; CHECK-NEXT: store i8 2, i8* %s, align 1, !tbaa [[TAGA:!.*]] ; CHECK-NEXT: ret void define void @foo(i8* nocapture %p, i8* nocapture %q, i8* nocapture %s) nounwind { @@ -24,4 +24,4 @@ !1 = !{!3, !3, i64 0} !2 = !{!4, !4, i64 0} !3 = !{!"A", !0} -!4 = !{!"B", !0} +!4 = !{!"B", !0} \ No newline at end of file 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 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 @@ -13,12 +13,12 @@ bb: %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) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull %tmp2, i8* nonnull %arg1, i64 1024, i1 false) ; CHECK: call void @llvm.memcpy %tmp3 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 false, i1 true) %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 %arg2, i8* nonnull %tmp2, i64 1023) ; CHECK-NOT: call ret i8* %tmp4 Index: test/Transforms/InstCombine/ARM/strcmp.ll =================================================================== --- test/Transforms/InstCombine/ARM/strcmp.ll +++ test/Transforms/InstCombine/ARM/strcmp.ll @@ -61,7 +61,7 @@ ; (This transform is rather difficult to trigger in a useful manner) define arm_aapcscc i32 @test5(i1 %b) { ; CHECK-LABEL: @test5( -; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) +; CHECK: %memcmp = call i32 @memcmp(i8* nonnull getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull %str2, i32 5) ; CHECK: ret i32 %memcmp %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -132,7 +132,7 @@ ; (This transform is rather difficult to trigger in a useful manner) define arm_aapcs_vfpcc i32 @test5_vfp(i1 %b) { ; CHECK-LABEL: @test5_vfp( -; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) +; CHECK: %memcmp = call i32 @memcmp(i8* nonnull getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull %str2, i32 5) ; CHECK: ret i32 %memcmp %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 Index: test/Transforms/InstCombine/align-addr.ll =================================================================== --- test/Transforms/InstCombine/align-addr.ll +++ test/Transforms/InstCombine/align-addr.ll @@ -91,7 +91,7 @@ ; CHECK-LABEL: @test3( %a4.cast = bitcast %struct.s* %a4 to i8* call void @llvm.memset.p0i8.i64(i8* %a4.cast, i8 0, i64 16, i1 false) -; CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 %a4.cast, i8 0, i64 16, i1 false) +; CHECK: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 %a4.cast, i8 0, i64 16, i1 false) call void @use(i8* %a4.cast) ret void } Index: test/Transforms/InstCombine/getelementptr.ll =================================================================== --- test/Transforms/InstCombine/getelementptr.ll +++ test/Transforms/InstCombine/getelementptr.ll @@ -451,7 +451,7 @@ define i32 @test28() nounwind { entry: %orientations = alloca [1 x [1 x %struct.x]] - %tmp3 = call i32 @puts( i8* getelementptr ([6 x i8], [6 x i8]* @.str, i32 0, i32 0) ) nounwind + %tmp3 = call i32 @puts( i8* nonnull getelementptr ([6 x i8], [6 x i8]* @.str, i32 0, i32 0) ) nounwind %tmp45 = getelementptr inbounds [1 x [1 x %struct.x]], [1 x [1 x %struct.x]]* %orientations, i32 1, i32 0, i32 0 %orientations62 = getelementptr [1 x [1 x %struct.x]], [1 x [1 x %struct.x]]* %orientations, i32 0, i32 0, i32 0 br label %bb10 @@ -461,7 +461,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 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 @@ -618,11 +618,11 @@ ; Instcombine should be able to fold this getelementptr. define i32 @test35() nounwind { - call i32 (i8*, ...) @printf(i8* getelementptr ([17 x i8], [17 x i8]* @"\01LC8", i32 0, i32 0), + call i32 (i8*, ...) @printf(i8* nonnull getelementptr ([17 x i8], [17 x i8]* @"\01LC8", i32 0, i32 0), 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 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/memcmp-constant-fold.ll =================================================================== --- test/Transforms/InstCombine/memcmp-constant-fold.ll +++ test/Transforms/InstCombine/memcmp-constant-fold.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S -data-layout=e-n32 | FileCheck %s --check-prefix=ALL --check-prefix=LE ; RUN: opt < %s -instcombine -S -data-layout=E-n32 | FileCheck %s --check-prefix=ALL --check-prefix=BE @@ -9,13 +10,13 @@ define i1 @memcmp_4bytes_unaligned_constant_i8(i8* align 4 %x) { ; LE-LABEL: @memcmp_4bytes_unaligned_constant_i8( -; LE-NEXT: [[TMP1:%.*]] = bitcast i8* %x to i32* +; LE-NEXT: [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32* ; LE-NEXT: [[LHSV:%.*]] = load i32, i32* [[TMP1]], align 4 ; LE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[LHSV]], 16777216 ; LE-NEXT: ret i1 [[TMP2]] ; ; BE-LABEL: @memcmp_4bytes_unaligned_constant_i8( -; BE-NEXT: [[TMP1:%.*]] = bitcast i8* %x to i32* +; BE-NEXT: [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32* ; BE-NEXT: [[LHSV:%.*]] = load i32, i32* [[TMP1]], align 4 ; BE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[LHSV]], 1 ; BE-NEXT: ret i1 [[TMP2]] @@ -32,13 +33,13 @@ define i1 @memcmp_4bytes_unaligned_constant_i16(i8* align 4 %x) { ; LE-LABEL: @memcmp_4bytes_unaligned_constant_i16( -; LE-NEXT: [[TMP1:%.*]] = bitcast i8* %x to i32* +; LE-NEXT: [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32* ; LE-NEXT: [[RHSV:%.*]] = load i32, i32* [[TMP1]], align 4 ; LE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[RHSV]], 131073 ; LE-NEXT: ret i1 [[TMP2]] ; ; BE-LABEL: @memcmp_4bytes_unaligned_constant_i16( -; BE-NEXT: [[TMP1:%.*]] = bitcast i8* %x to i32* +; BE-NEXT: [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32* ; BE-NEXT: [[RHSV:%.*]] = load i32, i32* [[TMP1]], align 4 ; BE-NEXT: [[TMP2:%.*]] = icmp eq i32 [[RHSV]], 65538 ; BE-NEXT: ret i1 [[TMP2]] @@ -54,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* bitcast (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @intbuf, i64 0, i64 1) to i8*), i8* bitcast ([2 x i32]* @intbuf to i8*), i64 3) +; ALL-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull bitcast (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @intbuf, i64 0, i64 1) to i8*), i8* nonnull bitcast ([2 x i32]* @intbuf to i8*), i64 3) ; ALL-NEXT: [[CMPEQ0:%.*]] = icmp eq i32 [[CALL]], 0 ; ALL-NEXT: ret i1 [[CMPEQ0]] ; @@ -67,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* %x, i8* %y, i64 4) +; ALL-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull [[X:%.*]], i8* nonnull [[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 @@ -60,7 +60,7 @@ ; CHECK-NEXT: getelementptr inbounds [124 x i8], [124 x i8]* ; use @G instead of %A -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 %{{.*}}, i8* align 16 getelementptr inbounds (%T, %T* @G, i64 0, i32 0) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 %{{.*}}, i8* nonnull align 16 getelementptr inbounds (%T, %T* @G, i64 0, i32 0) call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false) call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %b, i8* align 4 %a, i64 124, i1 false) call void @bar(i8* %b) @@ -103,7 +103,7 @@ ; CHECK-NEXT: addrspacecast ; use @G instead of %A -; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* align 4 %{{.*}}, +; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* nonnull align 4 %{{.*}}, call void @llvm.memcpy.p1i8.p0i8.i64(i8 addrspace(1)* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false) call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* align 4 %b, i8 addrspace(1)* align 4 %a, i64 124, i1 false) call void @bar_as1(i8 addrspace(1)* %b) 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 [[D:%.*]], i8* align 1 [[S:%.*]], i32 3, i1 false) +; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 [[D:%.*]], i8* nonnull align 1 [[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 [[D:%.*]], i8* align 1 [[S:%.*]], i32 5, i1 false) +; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 [[D:%.*]], i8* nonnull align 1 [[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 [[D:%.*]], i8* align 1 [[S:%.*]], i32 16, i1 false) +; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 [[D:%.*]], i8* nonnull align 1 [[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 @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind @@ -17,7 +18,7 @@ define void @test2(i8* %a) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %a, i32 100, i1 true) +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[A:%.*]], i8* [[A]], i32 100, i1 true) ; CHECK-NEXT: ret void ; tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %a, i32 100, i1 true) @@ -28,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 %d, i8* align 4 %s, i64 17179869184, i1 false) +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 [[D:%.*]], i8* nonnull align 4 [[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 @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test lib call simplification of __memcpy_chk calls with various values ; for dstlen and len. ; @@ -17,22 +18,24 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 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* %src = bitcast %struct.T2* @t2 to i8* -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 1824) ret i8* %ret } define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 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* %src = bitcast %struct.T3* @t3 to i8* -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 2848) ret i8* %ret } @@ -41,36 +44,39 @@ define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__memcpy_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = bitcast %struct.T3* @t3 to i8* %src = bitcast %struct.T1* @t1 to i8* -; CHECK-NEXT: %ret = call i8* @__memcpy_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 2848, i64 1824) ret i8* %ret } define i8* @test_no_simplify2() { ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__memcpy_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = bitcast %struct.T1* @t1 to i8* %src = bitcast %struct.T2* @t2 to i8* -; CHECK-NEXT: %ret = call i8* @__memcpy_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1024, i64 0) ret i8* %ret } 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* nonnull align 1 [[DST]], i8* nonnull align 4 bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT: ret i8* [[DST]] +; %src = bitcast %struct.T2* @t2 to i8* -; CHECK-NEXT: %dst = call i8* %alloc() %dst = call i8* %alloc() -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64 %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 1824) -; CHECK-NEXT: ret i8* %dst ret i8* %ret } Index: test/Transforms/InstCombine/memmove_chk-1.ll =================================================================== --- test/Transforms/InstCombine/memmove_chk-1.ll +++ test/Transforms/InstCombine/memmove_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test lib call simplification of __memmove_chk calls with various values ; for dstlen and len. ; @@ -17,22 +18,24 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 4 bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 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* %src = bitcast %struct.T2* @t2 to i8* -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 1824) ret i8* %ret } define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 4 bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 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* %src = bitcast %struct.T3* @t3 to i8* -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 2848) ret i8* %ret } @@ -41,22 +44,24 @@ define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__memmove_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = bitcast %struct.T3* @t3 to i8* %src = bitcast %struct.T1* @t1 to i8* -; CHECK-NEXT: %ret = call i8* @__memmove_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 2848, i64 1824) ret i8* %ret } define i8* @test_no_simplify2() { ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__memmove_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = bitcast %struct.T1* @t1 to i8* %src = bitcast %struct.T2* @t2 to i8* -; CHECK-NEXT: %ret = call i8* @__memmove_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1024, i64 0) ret i8* %ret } Index: test/Transforms/InstCombine/memset_chk-1.ll =================================================================== --- test/Transforms/InstCombine/memset_chk-1.ll +++ test/Transforms/InstCombine/memset_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test lib call simplification of __memset_chk calls with various values ; for dstlen and len. ; @@ -13,30 +14,33 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 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* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 1824) ret i8* %ret } define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 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* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 3648) ret i8* %ret } define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 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* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 -1) ret i8* %ret } @@ -45,41 +49,55 @@ define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 400) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = bitcast %struct.T* @t to i8* -; CHECK-NEXT: %ret = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 400) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 400) ret i8* %ret } define i8* @test_no_simplify2() { ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 0) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = bitcast %struct.T* @t to i8* -; CHECK-NEXT: %ret = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 0) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 0) ret i8* %ret } ; Test that RAUW in SimplifyLibCalls for __memset_chk generates valid IR define i32 @test_rauw(i8* %a, i8* %b, i8** %c) { -; CHECK-LABEL: test_rauw +; CHECK-LABEL: @test_rauw( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL49:%.*]] = call i64 @strlen(i8* nonnull [[A:%.*]]) +; CHECK-NEXT: [[ADD180:%.*]] = add i64 [[CALL49]], 1 +; CHECK-NEXT: [[YO107:%.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* [[B:%.*]], 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* nonnull [[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 +; CHECK-NEXT: [[SUB183:%.*]] = ptrtoint i8* [[B]] to i64 +; CHECK-NEXT: [[SUB184:%.*]] = sub i64 [[D1]], [[SUB183]] +; CHECK-NEXT: [[ADD52_I_I:%.*]] = add nsw i64 [[SUB184]], 1 +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[STRCHR2]], i8 0, i64 [[ADD52_I_I]], i1 false) +; CHECK-NEXT: ret i32 4 +; entry: %call49 = call i64 @strlen(i8* %a) %add180 = add i64 %call49, 1 %yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false, i1 false) %call50 = call i8* @__memmove_chk(i8* %b, i8* %a, i64 %add180, i64 %yo107) -; CHECK: %strlen = call i64 @strlen(i8* %b) -; CHECK-NEXT: %strchr2 = getelementptr i8, i8* %b, i64 %strlen %call51i = call i8* @strrchr(i8* %b, i32 0) %d = load i8*, i8** %c, align 8 %sub182 = ptrtoint i8* %d to i64 %sub183 = ptrtoint i8* %b to i64 %sub184 = sub i64 %sub182, %sub183 %add52.i.i = add nsw i64 %sub184, 1 -; CHECK: call void @llvm.memset.p0i8.i64(i8* align 1 %strchr2 %call185 = call i8* @__memset_chk(i8* %call51i, i32 0, i64 %add52.i.i, i64 -1) ret i32 4 } @@ -94,6 +112,20 @@ ; FIXME: memset(malloc(x), 0, x) -> calloc(1, x) define float* @pr25892(i64 %size) #0 { +; CHECK-LABEL: @pr25892( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @malloc(i64 [[SIZE:%.*]]) #3 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[CALL]], null +; CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[IF_END:%.*]] +; CHECK: if.end: +; CHECK-NEXT: [[BC:%.*]] = bitcast i8* [[CALL]] to float* +; CHECK-NEXT: [[CALL2:%.*]] = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull [[CALL]], i1 false, i1 false) +; CHECK-NEXT: [[CALL3:%.*]] = tail call i8* @__memset_chk(i8* nonnull [[CALL]], i32 0, i64 [[SIZE]], i64 [[CALL2]]) #3 +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: cleanup: +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi float* [ [[BC]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret float* [[RETVAL_0]] +; entry: %call = tail call i8* @malloc(i64 %size) #1 %cmp = icmp eq i8* %call, null @@ -107,19 +139,6 @@ %retval.0 = phi float* [ %bc, %if.end ], [ null, %entry ] ret float* %retval.0 -; CHECK-LABEL: @pr25892( -; CHECK: entry: -; CHECK-NEXT: %call = tail call i8* @malloc(i64 %size) -; CHECK-NEXT: %cmp = icmp eq i8* %call, null -; CHECK-NEXT: br i1 %cmp, label %cleanup, label %if.end -; CHECK: if.end: -; CHECK-NEXT: %bc = bitcast i8* %call to float* -; CHECK-NEXT: %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false) -; CHECK-NEXT: %call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2) -; CHECK-NEXT: br label %cleanup -; CHECK: cleanup: -; CHECK-NEXT: %retval.0 = phi float* [ %bc, %if.end ], [ null, %entry ] -; CHECK-NEXT: ret float* %retval.0 } declare noalias i8* @malloc(i64) #1 Index: test/Transforms/InstCombine/objsize.ll =================================================================== --- test/Transforms/InstCombine/objsize.ll +++ test/Transforms/InstCombine/objsize.ll @@ -114,7 +114,7 @@ %1 = bitcast %struct.data* %0 to i8* %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false) nounwind ; CHECK-NOT: @llvm.objectsize -; CHECK: @llvm.memset.p0i8.i32(i8* align 8 %1, i8 0, i32 1824, i1 false) +; CHECK: @llvm.memset.p0i8.i32(i8* nonnull align 8 %1, i8 0, i32 1824, i1 false) %3 = call i8* @__memset_chk(i8* %1, i32 0, i32 1824, i32 %2) nounwind store i8* %1, i8** %esc ret i32 0 @@ -130,7 +130,7 @@ %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false) %2 = load i8*, i8** @s, align 8 ; CHECK-NOT: @llvm.objectsize -; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 1 %1, i32 10, i1 false) +; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 %0, i8* nonnull align 1 %1, i32 10, i1 false) %3 = tail call i8* @__memcpy_chk(i8* %0, i8* %2, i32 10, i32 %1) nounwind ret i8* %0 } 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 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 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 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 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 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 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 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 [[FMT:%.*]], double [[D:%.*]]) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_no_simplify2( +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull [[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 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 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 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/puts-1.ll =================================================================== --- test/Transforms/InstCombine/puts-1.ll +++ test/Transforms/InstCombine/puts-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the puts library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -12,20 +13,22 @@ define void @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 10) +; CHECK-NEXT: ret void +; %str = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0 call i32 @puts(i8* %str) -; CHECK-NEXT: call i32 @putchar(i32 10) ret void -; CHECK-NEXT: ret void } ; Don't simplify if the return value is used. define i32 @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i32 @puts(i8* nonnull getelementptr inbounds ([1 x i8], [1 x i8]* @empty, i32 0, i32 0)) +; CHECK-NEXT: ret i32 [[RET]] +; %str = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0 %ret = call i32 @puts(i8* %str) -; CHECK-NEXT: call i32 @puts(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @empty, i32 0, i32 0)) ret i32 %ret -; CHECK-NEXT: ret i32 %ret } Index: test/Transforms/InstCombine/snprintf.ll =================================================================== --- test/Transforms/InstCombine/snprintf.ll +++ test/Transforms/InstCombine/snprintf.ll @@ -10,7 +10,7 @@ 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* [[BUF:%.*]], i64 32, i8* nonnull [[FMT:%.*]]) ; CHECK-NEXT: ret void ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* %fmt) #2 @@ -19,7 +19,7 @@ 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:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 0, i8* nonnull [[FMT:%.*]]) ; CHECK-NEXT: ret void ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 0, i8* %fmt) #2 @@ -29,7 +29,7 @@ define void @test_not_const_size(i8* %buf, i64 %size) #0 { ; CHECK-LABEL: @test_not_const_size( -; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 [[SIZE:%.*]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 [[SIZE:%.*]], i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) ; CHECK-NEXT: ret void ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 %size, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 @@ -47,7 +47,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* [[BUF:%.*]], i64 32, i8* nonnull 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 @@ -64,7 +64,7 @@ define i32 @test_percentage_return_value() #0 { ; CHECK-LABEL: @test_percentage_return_value( -; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, 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* null, i64 0, i8* nonnull getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) #3 @@ -92,7 +92,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* [[BUF:%.*]], i64 1, i8* nonnull 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 +120,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* [[BUF:%.*]], i64 1, i8* nonnull 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 @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the sprintf library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -20,81 +21,125 @@ define void @test_simplify1(i8* %dst) { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 [[DST:%.*]], i8* nonnull align 1 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* nonnull align 1 [[DST:%.*]], i8* nonnull align 1 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 call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt) -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %dst, i8* align 1 getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false) ret void -; CHECK-NEXT: ret void } define void @test_simplify2(i8* %dst) { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify2( +; CHECK-IPRINTF-NEXT: store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0 call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt) -; CHECK-NEXT: store i8 0, i8* %dst, align 1 ret void -; CHECK-NEXT: ret void } define void @test_simplify3(i8* %dst) { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify3( +; CHECK-IPRINTF-NEXT: store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [7 x i8], [7 x i8]* @null_hello, i32 0, i32 0 call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt) -; CHECK-NEXT: store i8 0, i8* %dst, align 1 ret void -; CHECK-NEXT: ret void } ; Check sprintf(dst, "%c", chr) -> *(i8*)dst = chr; *((i8*)dst + 1) = 0. define void @test_simplify4(i8* %dst) { ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: store i8 104, i8* [[DST:%.*]], align 1 +; CHECK-NEXT: [[NUL:%.*]] = getelementptr i8, i8* [[DST]], i32 1 +; CHECK-NEXT: store i8 0, i8* [[NUL]], align 1 +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify4( +; CHECK-IPRINTF-NEXT: store i8 104, i8* [[DST:%.*]], align 1 +; CHECK-IPRINTF-NEXT: [[NUL:%.*]] = getelementptr i8, i8* [[DST]], i32 1 +; CHECK-IPRINTF-NEXT: store i8 0, i8* [[NUL]], align 1 +; CHECK-IPRINTF-NEXT: ret void +; %fmt = getelementptr [3 x i8], [3 x i8]* @percent_c, i32 0, i32 0 call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8 104) -; CHECK-NEXT: store i8 104, i8* %dst, align 1 -; CHECK-NEXT: [[NUL:%[a-z0-9]+]] = getelementptr i8, i8* %dst, i32 1 -; CHECK-NEXT: store i8 0, i8* [[NUL]], align 1 ret void -; CHECK-NEXT: ret void } ; Check sprintf(dst, "%s", str) -> llvm.memcpy(dest, str, strlen(str) + 1, 1). define void @test_simplify5(i8* %dst, i8* %str) { ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull [[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* nonnull [[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 +; %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0 call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8* %str) -; CHECK-NEXT: [[STRLEN:%[a-z0-9]+]] = call i32 @strlen(i8* %str) -; CHECK-NEXT: [[LENINC:%[a-z0-9]+]] = 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) ret void -; CHECK-NEXT: ret void } ; Check sprintf(dst, format, ...) -> siprintf(str, format, ...) if no floating. define void @test_simplify6(i8* %dst) { +; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull [[DST:%.*]], i8* nonnull 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( +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @siprintf(i8* [[DST:%.*]], 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*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i32 187) -; CHECK-IPRINTF-NEXT: call i32 (i8*, i8*, ...) @siprintf(i8* %dst, 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(i8* %dst) { +; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull [[DST:%.*]], i8* nonnull 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* nonnull [[DST:%.*]], i8* nonnull 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*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double 1.87) -; CHECK-IPRINTF-NEXT: 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) ret void -; CHECK-IPRINTF-NEXT: ret void } 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* nonnull [[DST:%.*]], i8* nonnull [[FMT:%.*]], double [[D:%.*]]) +; CHECK-NEXT: ret void +; +; CHECK-IPRINTF-LABEL: @test_no_simplify2( +; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* nonnull [[DST:%.*]], i8* nonnull [[FMT:%.*]], double [[D:%.*]]) +; CHECK-IPRINTF-NEXT: ret void +; call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double %d) -; CHECK-NEXT: call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double %d) ret void -; CHECK-NEXT: ret void } Index: test/Transforms/InstCombine/stpcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/stpcpy_chk-1.ll +++ test/Transforms/InstCombine/stpcpy_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test lib call simplification of __stpcpy_chk calls with various values ; for src, dst, and slen. ; @@ -13,33 +14,36 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 60) ret i8* %ret } define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 12) ret i8* %ret } define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 -1) ret i8* %ret } @@ -48,11 +52,12 @@ define i8* @test_simplify4() { ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: [[STPCPY:%.*]] = call i8* @stpcpy(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: ret i8* [[STPCPY]] +; %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 -; CHECK-NEXT: %stpcpy = call i8* @stpcpy(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: ret i8* %stpcpy %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 -1) ret i8* %ret } @@ -61,12 +66,13 @@ define i8* @test_simplify5() { ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT: [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 [[LEN]]) +; 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) -; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 %len) ret i8* %ret @@ -76,11 +82,12 @@ define i8* @test_simplify6() { ; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* nonnull 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]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 -; CHECK-NEXT: %strlen = call i32 @strlen(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)) -; CHECK-NEXT: %1 = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 %strlen -; CHECK-NEXT: ret i8* %1 %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %dst, i32 %len) ret i8* %ret @@ -90,11 +97,12 @@ define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__stpcpy_chk(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 8) +; 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 -; CHECK-NEXT: %ret = call i8* @__stpcpy_chk(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 8) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 8) ret i8* %ret } Index: test/Transforms/InstCombine/str-int-2.ll =================================================================== --- test/Transforms/InstCombine/str-int-2.ll +++ test/Transforms/InstCombine/str-int-2.ll @@ -79,7 +79,7 @@ define i64 @strtol_not_const_base(i32 %b) #0 { ; CHECK-LABEL: @strtol_not_const_base( -; CHECK-NEXT: [[CALL:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i8** null, i32 [[B:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = call i64 @strtol(i8* nocapture nonnull getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i8** null, i32 [[B:%.*]]) ; CHECK-NEXT: ret i64 [[CALL]] ; %call = call i64 @strtol(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8** null, i32 %b) #2 @@ -97,7 +97,7 @@ define i64 @strtol_big_overflow() #0 { ; CHECK-LABEL: @strtol_big_overflow( -; CHECK-NEXT: [[CALL:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([24 x i8], [24 x i8]* @.str.3, i64 0, i64 0), i8** null, i32 10) +; CHECK-NEXT: [[CALL:%.*]] = call i64 @strtol(i8* nocapture nonnull getelementptr inbounds ([24 x i8], [24 x i8]* @.str.3, i64 0, i64 0), i8** null, i32 10) ; CHECK-NEXT: ret i64 [[CALL]] ; %call = call i64 @strtol(i8* nocapture getelementptr inbounds ([24 x i8], [24 x i8]* @.str.3, i64 0, i64 0), i8** null, i32 10) #2 Index: test/Transforms/InstCombine/str-int.ll =================================================================== --- test/Transforms/InstCombine/str-int.ll +++ test/Transforms/InstCombine/str-int.ll @@ -79,7 +79,7 @@ define i32 @strtol_not_const_base(i32 %b) #0 { ; CHECK-LABEL: @strtol_not_const_base( -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtol(i8* nocapture getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i8** null, i32 [[B:%.*]]) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtol(i8* nocapture nonnull getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i8** null, i32 [[B:%.*]]) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = call i32 @strtol(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8** null, i32 %b) #2 @@ -88,7 +88,7 @@ define i32 @strtol_long_int() #0 { ; CHECK-LABEL: @strtol_long_int( -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtol(i8* nocapture getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0), i8** null, i32 10) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtol(i8* nocapture nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0), i8** null, i32 10) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = call i32 @strtol(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i8** null, i32 10) #3 @@ -98,7 +98,7 @@ define i32 @strtol_big_overflow() #0 { ; CHECK-LABEL: @strtol_big_overflow( -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtol(i8* nocapture getelementptr inbounds ([24 x i8], [24 x i8]* @.str.3, i64 0, i64 0), i8** null, i32 10) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtol(i8* nocapture nonnull getelementptr inbounds ([24 x i8], [24 x i8]* @.str.3, i64 0, i64 0), i8** null, i32 10) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = call i32 @strtol(i8* nocapture getelementptr inbounds ([24 x i8], [24 x i8]* @.str.3, i32 0, i32 0), i8** null, i32 10) #2 @@ -116,7 +116,7 @@ define i32 @atoll_test() #0 { ; CHECK-LABEL: @atoll_test( -; CHECK-NEXT: [[CALL:%.*]] = call i32 @atoll(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.5, i64 0, i64 0)) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @atoll(i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @.str.5, i64 0, i64 0)) ; CHECK-NEXT: ret i32 [[CALL]] ; %call = call i32 @atoll(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.5, i32 0, i32 0)) #3 @@ -125,7 +125,7 @@ define i32 @strtoll_test() #0 { ; CHECK-LABEL: @strtoll_test( -; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtoll(i8* nocapture getelementptr inbounds ([11 x i8], [11 x i8]* @.str.7, i64 0, i64 0), i8** null, i32 10) +; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtoll(i8* nocapture nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @.str.7, i64 0, i64 0), i8** null, i32 10) ; CHECK-NEXT: ret i32 [[CALL]] ; ; CHECK-NEXT 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* 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 [[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,14 +88,15 @@ ; 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: %memchr.bounds = icmp ult i16 [[TRUNC]], 16 -; CHECK-NEXT: [[SHL:%.*]] = shl i16 1, [[TRUNC]] -; 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: [[MEMCHR_BOUNDS:%.*]] = icmp ult i16 [[TMP1]], 16 +; CHECK-NEXT: [[TMP2:%.*]] = shl i16 1, [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = and i16 [[TMP2]], 9217 +; CHECK-NEXT: [[MEMCHR_BITS:%.*]] = icmp ne i16 [[TMP3]], 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 Index: test/Transforms/InstCombine/strcmp-1.ll =================================================================== --- test/Transforms/InstCombine/strcmp-1.ll +++ test/Transforms/InstCombine/strcmp-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test that the strcmp library call simplifier works correctly. ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -13,10 +14,11 @@ ; strcmp("", x) -> -*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 @strcmp(i8* %str1, i8* %str2) @@ -27,9 +29,10 @@ ; strcmp(x, "") -> *x define i32 @test2(i8* %str1) { ; CHECK-LABEL: @test2( -; CHECK: %strcmpload = load i8, i8* %str -; 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 @strcmp(i8* %str1, i8* %str2) @@ -39,7 +42,8 @@ ; strcmp(x, y) -> 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 @@ -49,7 +53,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 @@ -61,8 +66,10 @@ ; (This transform is rather difficult to trigger in a useful manner) define i32 @test5(i1 %b) { ; CHECK-LABEL: @test5( -; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) -; CHECK: ret i32 %memcmp +; 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* nonnull getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* nonnull [[STR2]], i32 5) +; CHECK-NEXT: ret i32 [[MEMCMP]] +; %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 %temp1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0 @@ -75,7 +82,8 @@ ; strcmp(x,x) -> 0 define i32 @test6(i8* %str) { ; CHECK-LABEL: @test6( -; CHECK: ret i32 0 +; CHECK-NEXT: ret i32 0 +; %temp1 = call i32 @strcmp(i8* %str, i8* %str) ret i32 %temp1 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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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 [[STRING]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 2) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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 [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 3) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 2) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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 [[STRING]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) +; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* nonnull 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 [[STRING]], i8* nonnull 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 getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* nonnull 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 getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* nonnull 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 [[STRING]], i8* nonnull [[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 getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* nonnull 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 getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 5) ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 3 ; 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 getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[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 [[STRING]], i8* nonnull 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 [[STRING]], i8* nonnull 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_chk-1.ll =================================================================== --- test/Transforms/InstCombine/strcpy_chk-1.ll +++ test/Transforms/InstCombine/strcpy_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test lib call simplification of __strcpy_chk calls with various values ; for src, dst, and slen. ; @@ -13,33 +14,36 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 60) ret i8* %ret } define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 12) ret i8* %ret } define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1) ret i8* %ret } @@ -48,11 +52,12 @@ define i8* @test_simplify4() { ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull 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 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 -; 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: ret i8* %strcpy %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1) ret i8* %ret } @@ -61,12 +66,13 @@ define i8* @test_simplify5() { ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT: [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 [[LEN]]) +; CHECK-NEXT: ret i8* [[TMP1]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) -; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len) -; CHECK-NEXT: ret i8* %1 %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 %len) ret i8* %ret @@ -76,11 +82,12 @@ define i8* @test_simplify6() { ; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) +; CHECK-NEXT: [[RET:%.*]] = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i32 [[LEN]]) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) -; CHECK-NEXT: %ret = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i32 %len) -; CHECK-NEXT: ret i8* %ret %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__strcpy_chk(i8* %dst, i8* %dst, i32 %len) ret i8* %ret @@ -90,11 +97,12 @@ define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__strcpy_chk(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 8) +; 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 -; CHECK-NEXT: %ret = call i8* @__strcpy_chk(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 8) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 8) ret i8* %ret } 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 [[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 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 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,7 +153,7 @@ 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_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: ret i32 [[HELLO_L]] ; @@ -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,7 +177,7 @@ 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: ret i32 [[HELLO_L]] @@ -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]] Index: test/Transforms/InstCombine/strncpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/strncpy_chk-1.ll +++ test/Transforms/InstCombine/strncpy_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Test lib call simplification of __strncpy_chk calls with various values ; for len and dstlen. ; @@ -13,33 +14,36 @@ define i8* @test_simplify1() { ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 60) ret i8* %ret } define i8* @test_simplify2() { ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 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 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 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) %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 12) ret i8* %ret } define i8* @test_simplify3() { ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT: [[STRNCPY:%.*]] = call i8* @strncpy(i8* nonnull 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: ret i8* [[STRNCPY]] +; %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 -; 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: ret i8* %strncpy %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 60) ret i8* %ret } @@ -48,22 +52,24 @@ define i8* @test_no_simplify1() { ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__strncpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 8, i32 4) +; CHECK-NEXT: ret i8* [[RET]] +; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %ret = call i8* @__strncpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 8, i32 4) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 8, i32 4) ret i8* %ret } define i8* @test_no_simplify2() { ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT: [[RET:%.*]] = call i8* @__strncpy_chk(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 8, i32 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 -; CHECK-NEXT: %ret = call i8* @__strncpy_chk(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 8, i32 0) -; CHECK-NEXT: ret i8* %ret %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 8, i32 0) 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,57 @@ 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* [[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 [[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 } Index: test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll =================================================================== --- test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll +++ test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll @@ -1,9 +1,16 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -basicaa -memcpyopt -instcombine -S < %s | FileCheck %s target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" define void @foo([8 x i64]* noalias nocapture sret dereferenceable(64) %sret) { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry-block: +; CHECK-NEXT: [[SRET1:%.*]] = bitcast [8 x i64]* [[SRET:%.*]] to i8* +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 8 [[SRET1]], i8 0, i64 64, i1 false) +; CHECK-NEXT: ret void +; entry-block: %a = alloca [8 x i64], align 8 %a.cast = bitcast [8 x i64]* %a to i8* @@ -14,14 +21,23 @@ call void @llvm.lifetime.end.p0i8(i64 64, i8* %a.cast) ret void -; CHECK-LABEL: @foo( -; CHECK: %[[sret_cast:[^=]+]] = bitcast [8 x i64]* %sret to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 %[[sret_cast]], i8 0, i64 64 -; CHECK-NOT: call void @llvm.memcpy -; CHECK: ret void } define void @bar([8 x i64]* noalias nocapture sret dereferenceable(64) %sret, [8 x i64]* noalias nocapture dereferenceable(64) %out) { +; CHECK-LABEL: @bar( +; CHECK-NEXT: entry-block: +; CHECK-NEXT: [[A:%.*]] = alloca [8 x i64], align 8 +; CHECK-NEXT: [[A_CAST:%.*]] = bitcast [8 x i64]* [[A]] to i8* +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 64, i8* [[A_CAST]]) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 8 [[A_CAST]], i8 0, i64 64, i1 false) +; CHECK-NEXT: [[SRET_CAST:%.*]] = bitcast [8 x i64]* [[SRET:%.*]] to i8* +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 8 [[SRET_CAST]], i8 0, i64 64, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 8 [[A_CAST]], i8 42, i64 32, i1 false) +; CHECK-NEXT: [[OUT_CAST:%.*]] = bitcast [8 x i64]* [[OUT:%.*]] to i8* +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 [[OUT_CAST]], i8* nonnull align 8 [[A_CAST]], i64 64, i1 false) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 64, i8* [[A_CAST]]) +; CHECK-NEXT: ret void +; entry-block: %a = alloca [8 x i64], align 8 %a.cast = bitcast [8 x i64]* %a to i8* @@ -35,17 +51,6 @@ call void @llvm.lifetime.end.p0i8(i64 64, i8* %a.cast) ret void -; CHECK-LABEL: @bar( -; CHECK: %[[a:[^=]+]] = alloca [8 x i64] -; CHECK: %[[a_cast:[^=]+]] = bitcast [8 x i64]* %[[a]] to i8* -; CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[a_cast]], i8 0, i64 64 -; CHECK: %[[sret_cast:[^=]+]] = bitcast [8 x i64]* %sret to i8* -; CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[sret_cast]], i8 0, i64 64 -; CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[a_cast]], i8 42, i64 32 -; CHECK: %[[out_cast:[^=]+]] = bitcast [8 x i64]* %out to i8* -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[out_cast]], i8* align 8 %[[a_cast]], i64 64 -; CHECK-NOT: call void @llvm.memcpy -; CHECK: ret void } declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind