@@ -175,6 +175,76 @@ define void @partial_promotion_of_alloca() {
175
175
ret void
176
176
}
177
177
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
+
178
248
declare void @use (ptr )
179
249
180
250
!0 = !{}
0 commit comments