@@ -139,6 +139,37 @@ define void @test6_memcpy(ptr %src, ptr %dest) nounwind {
139
139
ret void
140
140
}
141
141
142
+ ; When forwarding to memcpy(arg+1, arg+1), we don't need to create this memcpy.
143
+ define void @test6_memcpy_forward_back (ptr %arg ) nounwind {
144
+ ; CHECK-LABEL: @test6_memcpy_forward_back(
145
+ ; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1
146
+ ; CHECK-NEXT: ret void
147
+ ;
148
+ %tmp = alloca [16 x i8 ], align 1
149
+ %src = getelementptr inbounds i8 , ptr %arg , i64 1
150
+ %dest = getelementptr inbounds i8 , ptr %arg , i64 1
151
+ call void @llvm.memcpy.inline.p0.p0.i32 (ptr align 1 %tmp , ptr align 1 %src , i32 16 , i1 false )
152
+ call void @llvm.memcpy.inline.p0.p0.i32 (ptr align 1 %dest , ptr align 1 %tmp , i32 16 , i1 false )
153
+ ret void
154
+ }
155
+
156
+ ; We have to retain this `memcpy(arg+2, arg+1)` forwarding.
157
+ define void @test6_memcpy_forward_not_back (ptr %arg ) nounwind {
158
+ ; CHECK-LABEL: @test6_memcpy_forward_not_back(
159
+ ; CHECK-NEXT: [[TMP:%.*]] = alloca [16 x i8], align 1
160
+ ; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1
161
+ ; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2
162
+ ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[SRC]], i32 16, i1 false)
163
+ ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[DEST]], ptr align 1 [[TMP]], i32 16, i1 false)
164
+ ; CHECK-NEXT: ret void
165
+ ;
166
+ %tmp = alloca [16 x i8 ], align 1
167
+ %src = getelementptr inbounds i8 , ptr %arg , i64 1
168
+ %dest = getelementptr inbounds i8 , ptr %arg , i64 2
169
+ call void @llvm.memcpy.inline.p0.p0.i32 (ptr align 1 %tmp , ptr align 1 %src , i32 16 , i1 false )
170
+ call void @llvm.memcpy.inline.p0.p0.i32 (ptr align 1 %dest , ptr align 1 %tmp , i32 16 , i1 false )
171
+ ret void
172
+ }
142
173
143
174
@x = external global %0
144
175
0 commit comments