@@ -175,6 +175,76 @@ define void @partial_promotion_of_alloca() {
175175 ret void
176176}
177177
178+ define void @memcpy_after_laundering_alloca (ptr %ptr ) {
179+ ; CHECK-LABEL: @memcpy_after_laundering_alloca(
180+ ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca { i64, i64 }, align 8
181+ ; CHECK-NEXT: [[LAUNDER:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[ALLOCA]])
182+ ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[LAUNDER]], ptr [[PTR:%.*]], i64 16, i1 false)
183+ ; CHECK-NEXT: ret void
184+ ;
185+ %alloca = alloca { i64 , i64 }, align 8
186+ %launder = call ptr @llvm.launder.invariant.group.p0 (ptr %alloca )
187+ call void @llvm.memcpy.p0.p0.i64 (ptr %launder , ptr %ptr , i64 16 , i1 false )
188+ ret void
189+ }
190+
191+ define void @memcpy_after_laundering_alloca_slices (ptr %ptr ) {
192+ ; CHECK-LABEL: @memcpy_after_laundering_alloca_slices(
193+ ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca { [16 x i8], i64, [16 x i8] }, align 8
194+ ; CHECK-NEXT: [[LAUNDER:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[ALLOCA]])
195+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[LAUNDER]], i64 16
196+ ; CHECK-NEXT: store i64 0, ptr [[GEP]], align 4
197+ ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[LAUNDER]], ptr [[PTR:%.*]], i64 40, i1 false)
198+ ; CHECK-NEXT: ret void
199+ ;
200+ %alloca = alloca { [16 x i8 ], i64 , [16 x i8 ] }, align 8
201+ %launder = call ptr @llvm.launder.invariant.group.p0 (ptr %alloca )
202+ %gep = getelementptr i8 , ptr %launder , i64 16
203+ store i64 0 , ptr %gep
204+ call void @llvm.memcpy.p0.p0.i64 (ptr %launder , ptr %ptr , i64 40 , i1 false )
205+ ret void
206+ }
207+
208+ define void @launder_in_loop () {
209+ ; CHECK-LABEL: @launder_in_loop(
210+ ; CHECK-NEXT: [[STRUCT_PTR:%.*]] = alloca [[T:%.*]], i64 1, align 4
211+ ; CHECK-NEXT: br label [[HEADER:%.*]]
212+ ; CHECK: header:
213+ ; CHECK-NEXT: br i1 true, label [[BODY:%.*]], label [[EXIT:%.*]]
214+ ; CHECK: body:
215+ ; CHECK-NEXT: [[STRUCT_PTR_FRESH:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[STRUCT_PTR]])
216+ ; CHECK-NEXT: [[STRUCT:%.*]] = call [[T]] @[[MAKE_T:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]]()
217+ ; CHECK-NEXT: store [[T]] [[STRUCT]], ptr [[STRUCT_PTR_FRESH]], align 4, !invariant.group [[META0]]
218+ ; CHECK-NEXT: [[FIRST_PTR:%.*]] = getelementptr [[T]], ptr [[STRUCT_PTR_FRESH]], i32 0, i32 0
219+ ; CHECK-NEXT: [[FIRST:%.*]] = load i32, ptr [[FIRST_PTR]], align 4
220+ ; CHECK-NEXT: [[SECOND_PTR:%.*]] = getelementptr [[T]], ptr [[STRUCT_PTR_FRESH]], i32 0, i32 1
221+ ; CHECK-NEXT: [[SECOND:%.*]] = load i32, ptr [[SECOND_PTR]], align 4
222+ ; CHECK-NEXT: br label [[HEADER]]
223+ ; CHECK: exit:
224+ ; CHECK-NEXT: ret void
225+ ;
226+ %struct_ptr = alloca %t , i64 1 , align 4
227+ br label %header
228+
229+ header:
230+ br i1 true , label %body , label %exit
231+
232+ body: ; preds = %6
233+ %struct_ptr_fresh = call ptr @llvm.launder.invariant.group.p0 (ptr %struct_ptr )
234+ %struct = call %t @make_t ()
235+ store %t %struct , ptr %struct_ptr_fresh , align 4 , !invariant.group !0
236+ %first_ptr = getelementptr %t , ptr %struct_ptr_fresh , i32 0 , i32 0
237+ %first = load i32 , ptr %first_ptr , align 4
238+ %second_ptr = getelementptr %t , ptr %struct_ptr_fresh , i32 0 , i32 1
239+ %second = load i32 , ptr %second_ptr , align 4
240+ br label %header
241+
242+ exit:
243+ ret void
244+ }
245+
246+ declare %t @make_t ()
247+
178248declare void @use (ptr )
179249
180250!0 = !{}
0 commit comments