@@ -11,10 +11,17 @@ declare i32 @somevalue()
11
11
12
12
define void @f () {
13
13
; CHECK-LABEL: @f(
14
+ ; CHECK-NEXT: [[A:%.*]] = alloca [[T:%.*]], align 8
15
+ ; CHECK-NEXT: [[A1_I8_INV:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[A]])
16
+ ; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1
14
17
; CHECK-NEXT: [[SV1:%.*]] = call i32 @somevalue()
15
18
; CHECK-NEXT: [[SV2:%.*]] = call i32 @somevalue()
16
- ; CHECK-NEXT: call void @h(i32 [[SV1]])
17
- ; CHECK-NEXT: call void @h(i32 [[SV2]])
19
+ ; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+]]
20
+ ; CHECK-NEXT: store i32 [[SV2]], ptr [[A2]], align 4
21
+ ; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
22
+ ; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[A2]], align 4
23
+ ; CHECK-NEXT: call void @h(i32 [[V1]])
24
+ ; CHECK-NEXT: call void @h(i32 [[V2]])
18
25
; CHECK-NEXT: ret void
19
26
;
20
27
%a = alloca %t
@@ -44,7 +51,7 @@ define void @g() {
44
51
; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1
45
52
; CHECK-NEXT: [[SV1:%.*]] = call i32 @somevalue()
46
53
; CHECK-NEXT: [[SV2:%.*]] = call i32 @somevalue()
47
- ; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+ ]]
54
+ ; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
48
55
; CHECK-NEXT: store i32 [[SV2]], ptr [[A2]], align 4
49
56
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
50
57
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[A2]], align 4
@@ -81,6 +88,9 @@ define void @g() {
81
88
82
89
define void @store_and_launder () {
83
90
; CHECK-LABEL: @store_and_launder(
91
+ ; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4
92
+ ; CHECK-NEXT: store i32 0, ptr [[VALPTR]], align 4
93
+ ; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
84
94
; CHECK-NEXT: ret void
85
95
;
86
96
%valptr = alloca i32 , align 4
@@ -91,7 +101,10 @@ define void @store_and_launder() {
91
101
92
102
define i32 @launder_and_load () {
93
103
; CHECK-LABEL: @launder_and_load(
94
- ; CHECK-NEXT: ret i32 undef
104
+ ; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4
105
+ ; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
106
+ ; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[VALPTR]], align 4
107
+ ; CHECK-NEXT: ret i32 [[V2]]
95
108
;
96
109
%valptr = alloca i32 , align 4
97
110
%barr = call ptr @llvm.launder.invariant.group.p0 (ptr %valptr )
@@ -101,6 +114,9 @@ define i32 @launder_and_load() {
101
114
102
115
define void @launder_and_ptr_arith () {
103
116
; CHECK-LABEL: @launder_and_ptr_arith(
117
+ ; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4
118
+ ; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
119
+ ; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds i32, ptr [[VALPTR]], i32 0
104
120
; CHECK-NEXT: ret void
105
121
;
106
122
%valptr = alloca i32 , align 4
@@ -140,9 +156,13 @@ end:
140
156
141
157
define void @partial_promotion_of_alloca () {
142
158
; CHECK-LABEL: @partial_promotion_of_alloca(
143
- ; CHECK-NEXT: [[STRUCT_PTR_SROA_2:%.*]] = alloca i32, align 4
144
- ; CHECK-NEXT: store volatile i32 0, ptr [[STRUCT_PTR_SROA_2]], align 4
145
- ; CHECK-NEXT: [[STRUCT_PTR_SROA_2_0_STRUCT_PTR_SROA_2_4_LOAD_VAL:%.*]] = load volatile i32, ptr [[STRUCT_PTR_SROA_2]], align 4
159
+ ; CHECK-NEXT: [[STRUCT_PTR:%.*]] = alloca [[T:%.*]], align 4
160
+ ; CHECK-NEXT: [[FIELD_PTR:%.*]] = getelementptr inbounds [[T]], ptr [[STRUCT_PTR]], i32 0, i32 0
161
+ ; CHECK-NEXT: store i32 0, ptr [[FIELD_PTR]], align 4
162
+ ; CHECK-NEXT: [[VOLATILE_FIELD_PTR:%.*]] = getelementptr inbounds [[T]], ptr [[STRUCT_PTR]], i32 0, i32 1
163
+ ; CHECK-NEXT: store volatile i32 0, ptr [[VOLATILE_FIELD_PTR]], align 4, !invariant.group [[META0]]
164
+ ; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[STRUCT_PTR]])
165
+ ; CHECK-NEXT: [[LOAD_VAL:%.*]] = load volatile i32, ptr [[VOLATILE_FIELD_PTR]], align 4, !invariant.group [[META0]]
146
166
; CHECK-NEXT: ret void
147
167
;
148
168
%struct_ptr = alloca %t , align 4
@@ -155,6 +175,61 @@ define void @partial_promotion_of_alloca() {
155
175
ret void
156
176
}
157
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 @test_agg_store () {
209
+ ; CHECK-LABEL: @test_agg_store(
210
+ ; CHECK-NEXT: [[STRUCT_PTR:%.*]] = alloca [[T:%.*]], i64 1, align 4
211
+ ; CHECK-NEXT: [[STRUCT_PTR_FRESH:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[STRUCT_PTR]])
212
+ ; CHECK-NEXT: [[STRUCT:%.*]] = call [[T]] @[[MAKE_T:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]]()
213
+ ; CHECK-NEXT: store [[T]] [[STRUCT]], ptr [[STRUCT_PTR_FRESH]], align 4, !invariant.group [[META0]]
214
+ ; CHECK-NEXT: [[FIRST_PTR:%.*]] = getelementptr [[T]], ptr [[STRUCT_PTR_FRESH]], i32 0, i32 0
215
+ ; CHECK-NEXT: [[FIRST:%.*]] = load i32, ptr [[FIRST_PTR]], align 4
216
+ ; CHECK-NEXT: [[SECOND_PTR:%.*]] = getelementptr [[T]], ptr [[STRUCT_PTR_FRESH]], i32 0, i32 1
217
+ ; CHECK-NEXT: [[SECOND:%.*]] = load i32, ptr [[SECOND_PTR]], align 4
218
+ ; CHECK-NEXT: ret void
219
+ ;
220
+ %struct_ptr = alloca %t , i64 1 , align 4
221
+ %struct_ptr_fresh = call ptr @llvm.launder.invariant.group.p0 (ptr %struct_ptr )
222
+ %struct = call %t @make_t ()
223
+ store %t %struct , ptr %struct_ptr_fresh , align 4 , !invariant.group !0
224
+ %first_ptr = getelementptr %t , ptr %struct_ptr_fresh , i32 0 , i32 0
225
+ %first = load i32 , ptr %first_ptr , align 4
226
+ %second_ptr = getelementptr %t , ptr %struct_ptr_fresh , i32 0 , i32 1
227
+ %second = load i32 , ptr %second_ptr , align 4
228
+ ret void
229
+ }
230
+
231
+ declare %t @make_t ()
232
+
158
233
declare void @use (ptr )
159
234
160
235
!0 = !{}
0 commit comments