llvm.org GIT mirror llvm / f6b0f6c
[BuildLibCalls] Noalias annotation Summary: I think this is better solution than annotating callsites in IC/SLC. Reviewers: jdoerfert Reviewed By: jdoerfert Subscribers: MaskRay, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66217 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368875 91177308-0d34-0410-b5e6-96231b3b80d8 David Bolvansky 2 months ago
21 changed file(s) with 71 addition(s) and 136 deletion(s). Raw diff Collapse all Expand all
8787 return true;
8888 }
8989
90 static bool setDoesNotAlias(Function &F, unsigned ArgNo) {
91 if (F.hasParamAttribute(ArgNo, Attribute::NoAlias))
92 return false;
93 F.addParamAttr(ArgNo, Attribute::NoAlias);
94 ++NumNoAlias;
95 return true;
96 }
97
9098 static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) {
9199 if (F.hasParamAttribute(ArgNo, Attribute::ReadOnly))
92100 return false;
174182 return Changed;
175183 case LibFunc_strcpy:
176184 case LibFunc_strncpy:
185 Changed |= setDoesNotAlias(F, 0);
186 Changed |= setDoesNotAlias(F, 1);
187 LLVM_FALLTHROUGH;
177188 case LibFunc_strcat:
178189 case LibFunc_strncat:
179190 Changed |= setReturnedArg(F, 0);
248259 case LibFunc_sprintf:
249260 Changed |= setDoesNotThrow(F);
250261 Changed |= setDoesNotCapture(F, 0);
262 Changed |= setDoesNotAlias(F, 0);
251263 Changed |= setDoesNotCapture(F, 1);
252264 Changed |= setOnlyReadsMemory(F, 1);
253265 return Changed;
254266 case LibFunc_snprintf:
255267 Changed |= setDoesNotThrow(F);
256268 Changed |= setDoesNotCapture(F, 0);
269 Changed |= setDoesNotAlias(F, 0);
257270 Changed |= setDoesNotCapture(F, 2);
258271 Changed |= setOnlyReadsMemory(F, 2);
259272 return Changed;
290303 Changed |= setDoesNotCapture(F, 1);
291304 return Changed;
292305 case LibFunc_memcpy:
306 Changed |= setDoesNotAlias(F, 0);
307 Changed |= setDoesNotAlias(F, 1);
308 LLVM_FALLTHROUGH;
293309 case LibFunc_memmove:
294310 Changed |= setReturnedArg(F, 0);
295311 LLVM_FALLTHROUGH;
459459 if (Dst == Src) // strcpy(x,x) -> x
460460 return Src;
461461
462 CI->addParamAttr(0, Attribute::NoAlias);
463 CI->addParamAttr(1, Attribute::NoAlias);
464
465462 // See if we can get the length of the input string.
466463 uint64_t Len = GetStringLength(Src);
467464 if (Len == 0)
503500 Value *Dst = CI->getArgOperand(0);
504501 Value *Src = CI->getArgOperand(1);
505502 Value *LenOp = CI->getArgOperand(2);
506
507 CI->addParamAttr(0, Attribute::NoAlias);
508 CI->addParamAttr(1, Attribute::NoAlias);
509503
510504 // See if we can get the length of the input string.
511505 uint64_t SrcLen = GetStringLength(Src);
987981 Value *Size = CI->getArgOperand(2);
988982 if (ConstantInt *LenC = dyn_cast(Size))
989983 annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue());
990
991 CI->addParamAttr(0, Attribute::NoAlias);
992 CI->addParamAttr(1, Attribute::NoAlias);
993984
994985 if (isIntrinsic)
995986 return nullptr;
77
88 define void @foo(i8* nocapture %p, i8* nocapture %q, i8* nocapture %s) nounwind {
99 ; CHECK: @foo
10 ; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 1 dereferenceable(16) %p, i8* noalias align 1 dereferenceable(16) %q, i64 16, i1 false), !tbaa !0
10 ; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) %p, i8* align 1 dereferenceable(16) %q, i64 16, i1 false), !tbaa !0
1111 ; CHECK-NEXT: store i8 2, i8* %s, align 1, !tbaa [[TAGA:!.*]]
1212 ; CHECK-NEXT: ret void
1313 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 16, i1 false), !tbaa !2
9595 }
9696
9797 declare i8* @memcpy(i8*, i8*, i64)
98 ; CHECK-LABEL: declare i8* @memcpy(
98 ; CHECK-LABEL: i8* @memcpy(
9999
100100 ; The @test3 function checks that when we refine an indirect call to an
101101 ; intrinsic we still revisit the SCC pass. This also covers cases where the
1717 %tmp3 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 false, i1 true, i1 false)
1818 %tmp4 = call i8* @__strncpy_chk(i8* %arg2, i8* %tmp2, i64 1023, i64 %tmp3)
1919 ; CHECK-NOT: call
20 ; CHECK: call i8* @strncpy(i8* noalias %arg2, i8* noalias nonnull %tmp2, i64 1023)
20 ; CHECK: call i8* @strncpy(i8* %arg2, i8* nonnull %tmp2, i64 1023)
2121 ; CHECK-NOT: call
2222
2323 ret i8* %tmp4
627627 ; CHECK: declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) [[G2]]
628628 declare i32 @memcmp(i8*, i8*, i64)
629629
630 ; CHECK: declare i8* @memcpy(i8* returned, i8* nocapture readonly, i64) [[G1]]
630 ; CHECK: declare i8* @memcpy(i8* noalias returned, i8* noalias nocapture readonly, i64) [[G1]]
631631 declare i8* @memcpy(i8*, i8*, i64)
632632
633633 ; CHECK: declare i8* @mempcpy(i8*, i8* nocapture readonly, i64) [[G1]]
792792 ; CHECK: declare x86_fp80 @sinl(x86_fp80) [[G0]]
793793 declare x86_fp80 @sinl(x86_fp80)
794794
795 ; CHECK: declare i32 @snprintf(i8* nocapture, i64, i8* nocapture readonly, ...) [[G1]]
795 ; CHECK: declare i32 @snprintf(i8* noalias nocapture, i64, i8* nocapture readonly, ...) [[G1]]
796796 declare i32 @snprintf(i8*, i64, i8*, ...)
797797
798 ; CHECK: declare i32 @sprintf(i8* nocapture, i8* nocapture readonly, ...) [[G1]]
798 ; CHECK: declare i32 @sprintf(i8* noalias nocapture, i8* nocapture readonly, ...) [[G1]]
799799 declare i32 @sprintf(i8*, i8*, ...)
800800
801801 ; CHECK: declare double @sqrt(double) [[G0]]
843843 ; CHECK: declare i32 @strcoll(i8* nocapture, i8* nocapture) [[G2]]
844844 declare i32 @strcoll(i8*, i8*)
845845
846 ; CHECK: declare i8* @strcpy(i8* returned, i8* nocapture readonly) [[G1]]
846 ; CHECK: declare i8* @strcpy(i8* noalias returned, i8* noalias nocapture readonly) [[G1]]
847847 declare i8* @strcpy(i8*, i8*)
848848
849849 ; CHECK: declare i64 @strcspn(i8* nocapture, i8* nocapture) [[G2]]
864864 ; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[G2]]
865865 declare i32 @strncmp(i8*, i8*, i64)
866866
867 ; CHECK: declare i8* @strncpy(i8* returned, i8* nocapture readonly, i64) [[G1]]
867 ; CHECK: declare i8* @strncpy(i8* noalias returned, i8* noalias nocapture readonly, i64) [[G1]]
868868 declare i8* @strncpy(i8*, i8*, i64)
869869
870870 ; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[G1]]
+0
-78
test/Transforms/InstCombine/annotate-noalias.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -instcombine -S < %s | FileCheck %s
2
3
4 declare i8* @memcpy(i8* nocapture, i8* nocapture, i64)
5 declare i8* @strncpy(i8* nocapture, i8* nocapture, i64)
6 declare i8* @strcpy(i8* nocapture, i8* nocapture)
7
8 define i8* @memcpy_const_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s) {
9 ; CHECK-LABEL: @memcpy_const_size_noalias(
10 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 1 dereferenceable(16) [[D:%.*]], i8* noalias align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false)
11 ; CHECK-NEXT: ret i8* [[D]]
12 ;
13 %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 16)
14 ret i8* %call
15 }
16
17 define i8* @memcpy_const_zero_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s) {
18 ; CHECK-LABEL: @memcpy_const_zero_size_noalias(
19 ; CHECK-NEXT: ret i8* [[D:%.*]]
20 ;
21 %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 0)
22 ret i8* %call
23 }
24
25 define i8* @memcpy_nonconst_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s, i64 %n) {
26 ; CHECK-LABEL: @memcpy_nonconst_size_noalias(
27 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 1 [[D:%.*]], i8* noalias align 1 [[S:%.*]], i64 [[N:%.*]], i1 false)
28 ; CHECK-NEXT: ret i8* [[D]]
29 ;
30 %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 %n)
31 ret i8* %call
32 }
33
34 define i8* @strncpy_const_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s) {
35 ; CHECK-LABEL: @strncpy_const_size_noalias(
36 ; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @strncpy(i8* noalias [[D:%.*]], i8* noalias [[S:%.*]], i64 16)
37 ; CHECK-NEXT: ret i8* [[CALL]]
38 ;
39 %call = tail call i8* @strncpy(i8* %d, i8* %s, i64 16)
40 ret i8* %call
41 }
42
43 define i8* @strncpy_const_zero_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s) {
44 ; CHECK-LABEL: @strncpy_const_zero_size_noalias(
45 ; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @strncpy(i8* noalias [[D:%.*]], i8* noalias [[S:%.*]], i64 0)
46 ; CHECK-NEXT: ret i8* [[CALL]]
47 ;
48 %call = tail call i8* @strncpy(i8* %d, i8* %s, i64 0)
49 ret i8* %call
50 }
51
52 define i8* @strncpy_nonconst_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s, i64 %n) {
53 ; CHECK-LABEL: @strncpy_nonconst_size_noalias(
54 ; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @strncpy(i8* noalias [[D:%.*]], i8* noalias [[S:%.*]], i64 [[N:%.*]])
55 ; CHECK-NEXT: ret i8* [[CALL]]
56 ;
57 %call = tail call i8* @strncpy(i8* %d, i8* %s, i64 %n)
58 ret i8* %call
59 }
60
61 define i8* @strcpy_const_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s) {
62 ; CHECK-LABEL: @strcpy_const_size_noalias(
63 ; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @strcpy(i8* noalias [[D:%.*]], i8* noalias [[S:%.*]])
64 ; CHECK-NEXT: ret i8* [[CALL]]
65 ;
66 %call = tail call i8* @strcpy(i8* %d, i8* %s)
67 ret i8* %call
68 }
69
70 define i8* @strcpy_nonconst_size_noalias(i8* nocapture readonly %d, i8* nocapture readonly %s) {
71 ; CHECK-LABEL: @strcpy_nonconst_size_noalias(
72 ; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @strcpy(i8* noalias [[D:%.*]], i8* noalias [[S:%.*]])
73 ; CHECK-NEXT: ret i8* [[CALL]]
74 ;
75 %call = tail call i8* @strcpy(i8* %d, i8* %s)
76 ret i8* %call
77 }
8383
8484 define i8* @memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) {
8585 ; CHECK-LABEL: @memcpy_const_size_set_deref(
86 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 1 dereferenceable(64) [[D:%.*]], i8* noalias align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false)
86 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(64) [[D:%.*]], i8* align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false)
8787 ; CHECK-NEXT: ret i8* [[D]]
8888 ;
8989 %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 64)
119119
120120 define i8* @llvm_memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) {
121121 ; CHECK-LABEL: @llvm_memcpy_const_size_set_deref(
122 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 1 dereferenceable(16) [[D:%.*]], i8* noalias align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false)
122 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false)
123123 ; CHECK-NEXT: ret i8* [[D]]
124124 ;
125125 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %d, i8* align 1 %s, i64 16, i1 false)
1010
1111 define i8* @test_simplify1(i8* %mem1, i8* %mem2, i32 %size) {
1212 ; CHECK-LABEL: @test_simplify1(
13 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 [[MEM1:%.*]], i8* noalias align 1 [[MEM2:%.*]], i32 [[SIZE:%.*]], i1 false)
13 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[MEM1:%.*]], i8* align 1 [[MEM2:%.*]], i32 [[SIZE:%.*]], i1 false)
1414 ; CHECK-NEXT: ret i8* [[MEM1]]
1515 ;
1616 %ret = call i8* @memcpy(i8* %mem1, i8* %mem2, i32 %size)
2121
2222 define i8* @test_simplify2(i8* %mem1, i8* %mem2, i32 %size) {
2323 ; CHECK-LABEL: @test_simplify2(
24 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 [[MEM1:%.*]], i8* noalias align 1 [[MEM2:%.*]], i32 [[SIZE:%.*]], i1 false)
24 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[MEM1:%.*]], i8* align 1 [[MEM2:%.*]], i32 [[SIZE:%.*]], i1 false)
2525 ; CHECK-NEXT: ret i8* [[MEM1]]
2626 ;
2727 %ret = call i8* @memcpy(i8* %mem1, i8* %mem2, i32 %size) strictfp
7777 ; CHECK-LABEL: @test2(
7878 ; CHECK-NEXT: [[B1:%.*]] = alloca [124 x i8], align 8
7979 ; CHECK-NEXT: [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0
80 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nonnull align 8 dereferenceable(124) [[B1_SUB]], i8* noalias align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false)
80 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 dereferenceable(124) [[B1_SUB]], i8* align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false)
8181 ; CHECK-NEXT: call void @bar(i8* nonnull [[B1_SUB]])
8282 ; CHECK-NEXT: ret void
8383 ;
100100 ; CHECK-LABEL: @test2_no_null_opt(
101101 ; CHECK-NEXT: [[B1:%.*]] = alloca [124 x i8], align 8
102102 ; CHECK-NEXT: [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0
103 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 8 dereferenceable(124) [[B1_SUB]], i8* noalias align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false)
103 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 dereferenceable(124) [[B1_SUB]], i8* align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false)
104104 ; CHECK-NEXT: call void @bar(i8* [[B1_SUB]])
105105 ; CHECK-NEXT: ret void
106106 ;
124124 ; CHECK-NEXT: [[B1:%.*]] = alloca [124 x i8], align 8
125125 ; CHECK-NEXT: [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0
126126 ; CHECK-NEXT: [[B:%.*]] = addrspacecast i8* [[B1_SUB]] to i8 addrspace(1)*
127 ; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* noalias align 4 dereferenceable(124) [[B]], i8 addrspace(1)* noalias align 4 dereferenceable(124) addrspacecast (i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0) to i8 addrspace(1)*), i64 124, i1 false)
127 ; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* align 4 dereferenceable(124) [[B]], i8 addrspace(1)* align 4 dereferenceable(124) addrspacecast (i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0) to i8 addrspace(1)*), i64 124, i1 false)
128128 ; CHECK-NEXT: call void @bar_as1(i8 addrspace(1)* [[B]])
129129 ; CHECK-NEXT: ret void
130130 ;
233233 ; CHECK-LABEL: @test8(
234234 ; CHECK-NEXT: [[AL:%.*]] = alloca [[U:%.*]], align 16
235235 ; CHECK-NEXT: [[A:%.*]] = bitcast %U* [[AL]] to i8*
236 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nonnull align 16 dereferenceable(20) [[A]], i8* noalias align 4 dereferenceable(20) bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*), i64 20, i1 false)
236 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(20) [[A]], i8* align 4 dereferenceable(20) bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*), i64 20, i1 false)
237237 ; CHECK-NEXT: call void @bar(i8* nonnull [[A]]) #2
238238 ; CHECK-NEXT: ret void
239239 ;
249249 ; CHECK-LABEL: @test8_addrspacecast(
250250 ; CHECK-NEXT: [[AL:%.*]] = alloca [[U:%.*]], align 16
251251 ; CHECK-NEXT: [[A:%.*]] = bitcast %U* [[AL]] to i8*
252 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p1i8.i64(i8* noalias nonnull align 16 dereferenceable(20) [[A]], i8 addrspace(1)* noalias align 4 dereferenceable(20) addrspacecast (i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*) to i8 addrspace(1)*), i64 20, i1 false)
252 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p1i8.i64(i8* nonnull align 16 dereferenceable(20) [[A]], i8 addrspace(1)* align 4 dereferenceable(20) addrspacecast (i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*) to i8 addrspace(1)*), i64 20, i1 false)
253253 ; CHECK-NEXT: call void @bar(i8* nonnull [[A]]) #2
254254 ; CHECK-NEXT: ret void
255255 ;
293293 ; CHECK-NEXT: entry:
294294 ; CHECK-NEXT: [[CC:%.*]] = alloca [1000000 x i8], align 16
295295 ; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1000000 x i8], [1000000 x i8]* [[CC]], i64 0, i64 0
296 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nonnull align 16 dereferenceable(3) [[ARRAYDECAY]], i8* noalias align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false)
297 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 16 dereferenceable(1000000) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* noalias nonnull align 16 dereferenceable(1000000) [[ARRAYDECAY]], i64 1000000, i1 false)
296 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(3) [[ARRAYDECAY]], i8* align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false)
297 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 dereferenceable(1000000) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* nonnull align 16 dereferenceable(1000000) [[ARRAYDECAY]], i64 1000000, i1 false)
298298 ; CHECK-NEXT: ret void
299299 ;
300300 entry:
310310 define void @test10_same_global() {
311311 ; CHECK-LABEL: @test10_same_global(
312312 ; CHECK-NEXT: entry:
313 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 16 dereferenceable(3) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* noalias align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false)
313 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 dereferenceable(3) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false)
314314 ; CHECK-NEXT: ret void
315315 ;
316316 entry:
3333
3434 define void @copy_3_bytes(i8* %d, i8* %s) {
3535 ; ALL-LABEL: @copy_3_bytes(
36 ; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(3) [[D:%.*]], i8* noalias align 1 dereferenceable(3) [[S:%.*]], i32 3, i1 false)
36 ; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(3) [[D:%.*]], i8* align 1 dereferenceable(3) [[S:%.*]], i32 3, i1 false)
3737 ; ALL-NEXT: ret void
3838 ;
3939 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 3, i1 false)
5656
5757 define void @copy_5_bytes(i8* %d, i8* %s) {
5858 ; ALL-LABEL: @copy_5_bytes(
59 ; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(5) [[D:%.*]], i8* noalias align 1 dereferenceable(5) [[S:%.*]], i32 5, i1 false)
59 ; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(5) [[D:%.*]], i8* align 1 dereferenceable(5) [[S:%.*]], i32 5, i1 false)
6060 ; ALL-NEXT: ret void
6161 ;
6262 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 5, i1 false)
7777
7878 define void @copy_16_bytes(i8* %d, i8* %s) {
7979 ; ALL-LABEL: @copy_16_bytes(
80 ; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(16) [[D:%.*]], i8* noalias align 1 dereferenceable(16) [[S:%.*]], i32 16, i1 false)
80 ; ALL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i32 16, i1 false)
8181 ; ALL-NEXT: ret void
8282 ;
8383 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 16, i1 false)
2828
2929 define void @test3(i8* %d, i8* %s) {
3030 ; CHECK-LABEL: @test3(
31 ; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 4 dereferenceable(17179869184) [[D:%.*]], i8* noalias align 4 dereferenceable(17179869184) [[S:%.*]], i64 17179869184, i1 false)
31 ; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(17179869184) [[D:%.*]], i8* align 4 dereferenceable(17179869184) [[S:%.*]], i64 17179869184, i1 false)
3232 ; CHECK-NEXT: ret void
3333 ;
3434 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %d, i8* align 4 %s, i64 17179869184, i1 false)
1717
1818 define i8* @test_simplify1() {
1919 ; CHECK-LABEL: @test_simplify1(
20 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* noalias align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false)
20 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false)
2121 ; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*)
2222 ;
2323 %dst = bitcast %struct.T1* @t1 to i8*
2828
2929 define i8* @test_simplify2() {
3030 ; CHECK-LABEL: @test_simplify2(
31 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* noalias align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false)
31 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false)
3232 ; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*)
3333 ;
3434 %dst = bitcast %struct.T1* @t1 to i8*
6464 define i8* @test_simplify_return_indcall(i8* ()* %alloc) {
6565 ; CHECK-LABEL: @test_simplify_return_indcall(
6666 ; CHECK-NEXT: [[DST:%.*]] = call i8* [[ALLOC:%.*]]()
67 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias align 1 dereferenceable(1824) [[DST]], i8* noalias align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false)
67 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(1824) [[DST]], i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false)
6868 ; CHECK-NEXT: ret i8* [[DST]]
6969 ;
7070 %src = bitcast %struct.T2* @t2 to i8*
1818 define void @test2(i8* %A, i32 %N) {
1919 ;; dest can't alias source since we can't write to source!
2020 ; CHECK-LABEL: @test2(
21 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 [[A:%.*]], i8* noalias align 16 getelementptr inbounds ([33 x i8], [33 x i8]* @S, i64 0, i64 0), i32 [[N:%.*]], i1 false)
21 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[A:%.*]], i8* align 16 getelementptr inbounds ([33 x i8], [33 x i8]* @S, i64 0, i64 0), i32 [[N:%.*]], i1 false)
2222 ; CHECK-NEXT: ret void
2323 ;
2424 call void @llvm.memmove.p0i8.p0i8.i32(i8* %A, i8* getelementptr inbounds ([33 x i8], [33 x i8]* @S, i32 0, i32 0), i32 %N, i1 false)
162162 ; CHECK-NEXT: entry:
163163 ; CHECK-NEXT: [[TMP0:%.*]] = tail call noalias i8* @malloc(i32 20) #0
164164 ; CHECK-NEXT: [[TMP1:%.*]] = load i8*, i8** @s, align 8
165 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(10) [[TMP0]], i8* noalias align 1 dereferenceable(10) [[TMP1]], i32 10, i1 false)
165 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(10) [[TMP0]], i8* align 1 dereferenceable(10) [[TMP1]], i32 10, i1 false)
166166 ; CHECK-NEXT: ret i8* [[TMP0]]
167167 ;
168168 entry:
2020
2121 define void @test_simplify1(i8* %dst) {
2222 ; CHECK-LABEL: @test_simplify1(
23 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(13) [[DST:%.*]], i8* noalias align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false)
23 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(13) [[DST:%.*]], i8* align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false)
2424 ; CHECK-NEXT: ret void
2525 ;
2626 ; CHECK-IPRINTF-LABEL: @test_simplify1(
27 ; CHECK-IPRINTF-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(13) [[DST:%.*]], i8* noalias align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false)
27 ; CHECK-IPRINTF-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(13) [[DST:%.*]], i8* align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false)
2828 ; CHECK-IPRINTF-NEXT: ret void
2929 ;
3030 %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
8686 ; CHECK-LABEL: @test_simplify5(
8787 ; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* [[STR:%.*]])
8888 ; CHECK-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1
89 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 [[DST:%.*]], i8* noalias align 1 [[STR]], i32 [[LENINC]], i1 false)
89 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false)
9090 ; CHECK-NEXT: ret void
9191 ;
9292 ; CHECK-IPRINTF-LABEL: @test_simplify5(
9393 ; CHECK-IPRINTF-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* [[STR:%.*]])
9494 ; CHECK-IPRINTF-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1
95 ; CHECK-IPRINTF-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 [[DST:%.*]], i8* noalias align 1 [[STR]], i32 [[LENINC]], i1 false)
95 ; CHECK-IPRINTF-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false)
9696 ; CHECK-IPRINTF-NEXT: ret void
9797 ;
9898 %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; Test that the stpcpy library call simplifier works correctly.
12 ; RUN: opt < %s -instcombine -S | FileCheck %s
23 ;
1213
1314 define i8* @test_simplify1() {
1415 ; CHECK-LABEL: @test_simplify1(
16 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false)
17 ; CHECK-NEXT: ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 5)
18 ;
1519
1620 %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
1721 %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
1822
1923 %ret = call i8* @stpcpy(i8* %dst, i8* %src)
20 ; CHECK: @llvm.memcpy.p0i8.p0i8.i32
21 ; CHECK-NEXT: getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 5)
2224 ret i8* %ret
2325 }
2426
2527 define i8* @test_simplify2() {
2628 ; CHECK-LABEL: @test_simplify2(
29 ; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0))
30 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @a, i32 0, i32 [[STRLEN]]
31 ; CHECK-NEXT: ret i8* [[TMP1]]
32 ;
2733
2834 %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
2935
3036 %ret = call i8* @stpcpy(i8* %dst, i8* %dst)
31 ; CHECK: [[LEN:%[a-z]+]] = call i32 @strlen
32 ; CHECK-NEXT: getelementptr inbounds [32 x i8], [32 x i8]* @a, i32 0, i32 [[LEN]]
3337 ret i8* %ret
3438 }
3539
3640 define i8* @test_no_simplify1() {
3741 ; CHECK-LABEL: @test_no_simplify1(
42 ; CHECK-NEXT: [[RET:%.*]] = call i8* @stpcpy(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8], [32 x i8]* @b, i32 0, i32 0))
43 ; CHECK-NEXT: ret i8* [[RET]]
44 ;
3845
3946 %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
4047 %src = getelementptr [32 x i8], [32 x i8]* @b, i32 0, i32 0
4148
4249 %ret = call i8* @stpcpy(i8* %dst, i8* %src)
43 ; CHECK: call i8* @stpcpy
4450 ret i8* %ret
4551 }
1313
1414 define i8* @test_simplify1() {
1515 ; CHECK-LABEL: @test_simplify1(
16 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
16 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
1717 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)
1818 ;
1919 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
2525
2626 define i8* @test_simplify2() {
2727 ; CHECK-LABEL: @test_simplify2(
28 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
28 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
2929 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)
3030 ;
3131 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
3737
3838 define i8* @test_simplify3() {
3939 ; CHECK-LABEL: @test_simplify3(
40 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
40 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
4141 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)
4242 ;
4343 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
1313
1414 define i8* @test_simplify1() {
1515 ; CHECK-LABEL: @test_simplify1(
16 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
16 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
1717 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
1818 ;
1919 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
2525
2626 define i8* @test_simplify2() {
2727 ; CHECK-LABEL: @test_simplify2(
28 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
28 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
2929 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
3030 ;
3131 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
3737
3838 define i8* @test_simplify3() {
3939 ; CHECK-LABEL: @test_simplify3(
40 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
40 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
4141 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
4242 ;
4343 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
5151
5252 define i8* @test_simplify4() {
5353 ; CHECK-LABEL: @test_simplify4(
54 ; CHECK-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* noalias getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
54 ; 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))
5555 ; CHECK-NEXT: ret i8* [[STRCPY]]
5656 ;
5757 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
1313
1414 define i8* @test_simplify1() {
1515 ; CHECK-LABEL: @test_simplify1(
16 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
16 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
1717 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
1818 ;
1919 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
2525
2626 define i8* @test_simplify2() {
2727 ; CHECK-LABEL: @test_simplify2(
28 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
28 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
2929 ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
3030 ;
3131 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
3737
3838 define i8* @test_simplify3() {
3939 ; CHECK-LABEL: @test_simplify3(
40 ; CHECK-NEXT: [[STRNCPY:%.*]] = call i8* @strncpy(i8* noalias getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noalias getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 12)
40 ; 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)
4141 ; CHECK-NEXT: ret i8* [[STRNCPY]]
4242 ;
4343 %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
3333 ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(64) [[SRET_CAST]], i8 0, i64 64, i1 false)
3434 ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(32) [[A_CAST]], i8 42, i64 32, i1 false)
3535 ; CHECK-NEXT: [[OUT_CAST:%.*]] = bitcast [8 x i64]* [[OUT:%.*]] to i8*
36 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nonnull align 8 dereferenceable(64) [[OUT_CAST]], i8* noalias nonnull align 8 dereferenceable(64) [[A_CAST]], i64 64, i1 false)
36 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 dereferenceable(64) [[OUT_CAST]], i8* nonnull align 8 dereferenceable(64) [[A_CAST]], i64 64, i1 false)
3737 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 64, i8* nonnull [[A_CAST]])
3838 ; CHECK-NEXT: ret void
3939 ;