Skip to content

Commit 6106422

Browse files
committed
[SROA] Escaping readonly nocapture tests. NFC
1 parent 1a5e18a commit 6106422

File tree

2 files changed

+362
-4
lines changed

2 files changed

+362
-4
lines changed

llvm/test/Transforms/SROA/non-capturing-call-readonly.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,12 @@ define i32 @alloca_used_in_maybe_throwing_call(ptr %data, i64 %n) personality pt
364364
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
365365
; CHECK: exit:
366366
; CHECK-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(ptr [[RETVAL]])
367-
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[UW:%.*]]
367+
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[UW:%.*]]
368368
; CHECK: cont:
369369
; CHECK-NEXT: br label [[END:%.*]]
370370
; CHECK: uw:
371371
; CHECK-NEXT: [[I1:%.*]] = landingpad { ptr, i32 }
372-
; CHECK-NEXT: catch ptr null
372+
; CHECK-NEXT: catch ptr null
373373
; CHECK-NEXT: br label [[END]]
374374
; CHECK: end:
375375
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
@@ -424,10 +424,10 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(ptr %data, i64 %n
424424
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
425425
; CHECK: exit:
426426
; CHECK-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(ptr [[RETVAL]])
427-
; CHECK-NEXT: to label [[END:%.*]] unwind label [[UW:%.*]]
427+
; CHECK-NEXT: to label [[END:%.*]] unwind label [[UW:%.*]]
428428
; CHECK: uw:
429429
; CHECK-NEXT: [[I1:%.*]] = landingpad { ptr, i32 }
430-
; CHECK-NEXT: catch ptr null
430+
; CHECK-NEXT: catch ptr null
431431
; CHECK-NEXT: br label [[END]]
432432
; CHECK: end:
433433
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -passes=sroa -S | FileCheck %s
3+
4+
declare void @callee(ptr nocapture readonly %p)
5+
6+
define i32 @simple() {
7+
; CHECK-LABEL: @simple(
8+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
9+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
10+
; CHECK-NEXT: call void @callee(ptr [[A]])
11+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
12+
; CHECK-NEXT: ret i32 [[L1]]
13+
;
14+
%a = alloca i32
15+
store i32 0, ptr %a
16+
call void @callee(ptr %a)
17+
%l1 = load i32, ptr %a
18+
ret i32 %l1
19+
}
20+
21+
define i32 @smallbig() {
22+
; CHECK-LABEL: @smallbig(
23+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
24+
; CHECK-NEXT: store i8 0, ptr [[A]], align 1
25+
; CHECK-NEXT: call void @callee(ptr [[A]])
26+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
27+
; CHECK-NEXT: ret i32 [[L1]]
28+
;
29+
%a = alloca i32
30+
store i8 0, ptr %a
31+
call void @callee(ptr %a)
32+
%l1 = load i32, ptr %a
33+
ret i32 %l1
34+
}
35+
36+
define i32 @twoalloc() {
37+
; CHECK-LABEL: @twoalloc(
38+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
39+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
40+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
41+
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
42+
; CHECK-NEXT: call void @callee(ptr [[A]])
43+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
44+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
45+
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
46+
; CHECK-NEXT: ret i32 [[R]]
47+
;
48+
%a = alloca {i32, i32}
49+
store i32 0, ptr %a
50+
%b = getelementptr i32, ptr %a, i32 1
51+
store i32 1, ptr %b
52+
call void @callee(ptr %a)
53+
%l1 = load i32, ptr %a
54+
%l2 = load i32, ptr %b
55+
%r = add i32 %l1, %l2
56+
ret i32 %r
57+
}
58+
59+
define i32 @twostore() {
60+
; CHECK-LABEL: @twostore(
61+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
62+
; CHECK-NEXT: store i32 1, ptr [[A]], align 4
63+
; CHECK-NEXT: call void @callee(ptr [[A]])
64+
; CHECK-NEXT: store i32 2, ptr [[A]], align 4
65+
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 4
66+
; CHECK-NEXT: ret i32 [[L]]
67+
;
68+
%a = alloca i32
69+
store i32 1, ptr %a
70+
call void @callee(ptr %a)
71+
store i32 2, ptr %a
72+
%l = load i32, ptr %a
73+
ret i32 %l
74+
}
75+
76+
define float @differenttype() {
77+
; CHECK-LABEL: @differenttype(
78+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
79+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
80+
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
81+
; CHECK-NEXT: call void @callee(ptr [[A]])
82+
; CHECK-NEXT: [[L2:%.*]] = load float, ptr [[B]], align 4
83+
; CHECK-NEXT: ret float [[L2]]
84+
;
85+
%a = alloca {i32, i32}
86+
%b = getelementptr i32, ptr %a, i32 1
87+
store i32 1, ptr %b
88+
call void @callee(ptr %a)
89+
%l2 = load float, ptr %b
90+
ret float %l2
91+
}
92+
93+
define i32 @twoalloc_store64(i64 %x) {
94+
; CHECK-LABEL: @twoalloc_store64(
95+
; CHECK-NEXT: [[A:%.*]] = alloca i64, align 8
96+
; CHECK-NEXT: store i64 [[X:%.*]], ptr [[A]], align 4
97+
; CHECK-NEXT: call void @callee(ptr [[A]])
98+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
99+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
100+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
101+
; CHECK-NEXT: ret i32 [[L2]]
102+
;
103+
%a = alloca i64
104+
store i64 %x, ptr %a
105+
call void @callee(ptr %a)
106+
%l1 = load i32, ptr %a
107+
%b = getelementptr i32, ptr %a, i32 1
108+
%l2 = load i32, ptr %b
109+
ret i32 %l2
110+
}
111+
112+
define i32 @twocalls() {
113+
; CHECK-LABEL: @twocalls(
114+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
115+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
116+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
117+
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
118+
; CHECK-NEXT: call void @callee(ptr [[A]])
119+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
120+
; CHECK-NEXT: call void @callee(ptr [[A]])
121+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
122+
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
123+
; CHECK-NEXT: ret i32 [[R]]
124+
;
125+
%a = alloca {i32, i32}
126+
store i32 0, ptr %a
127+
%b = getelementptr i32, ptr %a, i32 1
128+
store i32 1, ptr %b
129+
call void @callee(ptr %a)
130+
%l1 = load i32, ptr %a
131+
call void @callee(ptr %a)
132+
%l2 = load i32, ptr %b
133+
%r = add i32 %l1, %l2
134+
ret i32 %r
135+
}
136+
137+
define i32 @volatile() {
138+
; CHECK-LABEL: @volatile(
139+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
140+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
141+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
142+
; CHECK-NEXT: store volatile i32 1, ptr [[B]], align 4
143+
; CHECK-NEXT: call void @callee(ptr [[A]])
144+
; CHECK-NEXT: [[L1:%.*]] = load volatile i32, ptr [[A]], align 4
145+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
146+
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
147+
; CHECK-NEXT: ret i32 [[R]]
148+
;
149+
%a = alloca {i32, i32}
150+
store i32 0, ptr %a
151+
%b = getelementptr i32, ptr %a, i32 1
152+
store volatile i32 1, ptr %b
153+
call void @callee(ptr %a)
154+
%l1 = load volatile i32, ptr %a
155+
%l2 = load i32, ptr %b
156+
%r = add i32 %l1, %l2
157+
ret i32 %r
158+
}
159+
160+
define i32 @atomic() {
161+
; CHECK-LABEL: @atomic(
162+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
163+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
164+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
165+
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
166+
; CHECK-NEXT: call void @callee(ptr [[A]])
167+
; CHECK-NEXT: [[L1:%.*]] = load atomic i32, ptr [[A]] seq_cst, align 4
168+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
169+
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
170+
; CHECK-NEXT: ret i32 [[R]]
171+
;
172+
%a = alloca {i32, i32}
173+
store i32 0, ptr %a
174+
%b = getelementptr i32, ptr %a, i32 1
175+
store i32 1, ptr %b
176+
call void @callee(ptr %a)
177+
%l1 = load atomic i32, ptr %a seq_cst, align 4
178+
%l2 = load i32, ptr %b
179+
%r = add i32 %l1, %l2
180+
ret i32 %r
181+
}
182+
183+
define i32 @notdominating() {
184+
; CHECK-LABEL: @notdominating(
185+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
186+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
187+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
188+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
189+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
190+
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
191+
; CHECK-NEXT: call void @callee(ptr [[A]])
192+
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
193+
; CHECK-NEXT: ret i32 [[R]]
194+
;
195+
%a = alloca {i32, i32}
196+
%b = getelementptr i32, ptr %a, i32 1
197+
%l1 = load i32, ptr %a
198+
%l2 = load i32, ptr %b
199+
store i32 0, ptr %a
200+
store i32 1, ptr %b
201+
call void @callee(ptr %a)
202+
%r = add i32 %l1, %l2
203+
ret i32 %r
204+
}
205+
206+
declare void @callee_notreadonly(ptr %p)
207+
define i32 @notreadonly() {
208+
; CHECK-LABEL: @notreadonly(
209+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
210+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
211+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
212+
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
213+
; CHECK-NEXT: call void @callee_notreadonly(ptr [[A]])
214+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
215+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
216+
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
217+
; CHECK-NEXT: ret i32 [[R]]
218+
;
219+
%a = alloca {i32, i32}
220+
store i32 0, ptr %a
221+
%b = getelementptr i32, ptr %a, i32 1
222+
store i32 1, ptr %b
223+
call void @callee_notreadonly(ptr %a)
224+
%l1 = load i32, ptr %a
225+
%l2 = load i32, ptr %b
226+
%r = add i32 %l1, %l2
227+
ret i32 %r
228+
}
229+
230+
declare void @callee_multiuse(ptr nocapture readonly %p, ptr nocapture readonly %q)
231+
define i32 @multiuse() {
232+
; CHECK-LABEL: @multiuse(
233+
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
234+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
235+
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
236+
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
237+
; CHECK-NEXT: call void @callee_multiuse(ptr [[A]], ptr [[A]])
238+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
239+
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
240+
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
241+
; CHECK-NEXT: ret i32 [[R]]
242+
;
243+
%a = alloca {i32, i32}
244+
store i32 0, ptr %a
245+
%b = getelementptr i32, ptr %a, i32 1
246+
store i32 1, ptr %b
247+
call void @callee_multiuse(ptr %a, ptr %a)
248+
%l1 = load i32, ptr %a
249+
%l2 = load i32, ptr %b
250+
%r = add i32 %l1, %l2
251+
ret i32 %r
252+
}
253+
254+
define i32 @memcpyed(ptr %src) {
255+
; CHECK-LABEL: @memcpyed(
256+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
257+
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
258+
; CHECK-NEXT: call void @callee(ptr [[A]])
259+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A]], ptr [[SRC:%.*]], i64 4, i1 false)
260+
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
261+
; CHECK-NEXT: ret i32 [[L1]]
262+
;
263+
%a = alloca i32
264+
store i32 0, ptr %a
265+
call void @callee(ptr %a)
266+
call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %src, i64 4, i1 false)
267+
%l1 = load i32, ptr %a
268+
ret i32 %l1
269+
}
270+
271+
define ptr @memcpyedsplit(ptr %src) {
272+
; CHECK-LABEL: @memcpyedsplit(
273+
; CHECK-NEXT: [[A:%.*]] = alloca { i64, i64 }, align 8
274+
; CHECK-NEXT: store i8 1, ptr [[A]], align 1
275+
; CHECK-NEXT: [[B:%.*]] = getelementptr i64, ptr [[A]], i32 1
276+
; CHECK-NEXT: store ptr null, ptr [[B]], align 8
277+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A]], ptr [[SRC:%.*]], i64 16, i1 false)
278+
; CHECK-NEXT: call void @callee(ptr [[A]])
279+
; CHECK-NEXT: [[L1:%.*]] = load ptr, ptr [[B]], align 8
280+
; CHECK-NEXT: ret ptr [[L1]]
281+
;
282+
%a = alloca { i64, i64 }
283+
store i8 1, ptr %a
284+
%b = getelementptr i64, ptr %a, i32 1
285+
store ptr null, ptr %b
286+
call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %src, i64 16, i1 false)
287+
call void @callee(ptr %a)
288+
%l1 = load ptr, ptr %b
289+
ret ptr %l1
290+
}
291+
292+
; This struct contains padding bits. The load should not be replaced by poison.
293+
%struct.LoadImmediateInfo = type { i32 }
294+
define void @incompletestruct(i1 %b, i1 %c) {
295+
; CHECK-LABEL: @incompletestruct(
296+
; CHECK-NEXT: entry:
297+
; CHECK-NEXT: [[LII:%.*]] = alloca [[STRUCT_LOADIMMEDIATEINFO:%.*]], align 4
298+
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[LII]])
299+
; CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[LII]], align 4
300+
; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 [[BF_LOAD]], -262144
301+
; CHECK-NEXT: [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072
302+
; CHECK-NEXT: [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]]
303+
; CHECK-NEXT: store i32 [[BF_SET12]], ptr [[LII]], align 4
304+
; CHECK-NEXT: call void @callee(ptr [[LII]])
305+
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[LII]])
306+
; CHECK-NEXT: ret void
307+
;
308+
entry:
309+
%LII = alloca %struct.LoadImmediateInfo, align 4
310+
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %LII)
311+
%bf.load = load i32, ptr %LII, align 4
312+
%bf.clear4 = and i32 %bf.load, -262144
313+
%bf.set5 = select i1 %b, i32 196608, i32 131072
314+
%bf.set12 = or disjoint i32 %bf.set5, %bf.clear4
315+
store i32 %bf.set12, ptr %LII, align 4
316+
call void @callee(ptr %LII)
317+
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %LII)
318+
ret void
319+
}
320+
321+
define void @incompletestruct_bb(i1 %b, i1 %c) {
322+
; CHECK-LABEL: @incompletestruct_bb(
323+
; CHECK-NEXT: entry:
324+
; CHECK-NEXT: [[LII:%.*]] = alloca [[STRUCT_LOADIMMEDIATEINFO:%.*]], align 4
325+
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
326+
; CHECK: if.then:
327+
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[LII]])
328+
; CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[LII]], align 4
329+
; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 [[BF_LOAD]], -262144
330+
; CHECK-NEXT: [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072
331+
; CHECK-NEXT: [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]]
332+
; CHECK-NEXT: store i32 [[BF_SET12]], ptr [[LII]], align 4
333+
; CHECK-NEXT: call void @callee(ptr [[LII]])
334+
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[LII]])
335+
; CHECK-NEXT: br label [[IF_END]]
336+
; CHECK: if.end:
337+
; CHECK-NEXT: ret void
338+
;
339+
entry:
340+
%LII = alloca %struct.LoadImmediateInfo, align 4
341+
br i1 %c, label %if.then, label %if.end
342+
343+
if.then: ; preds = %entry
344+
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %LII)
345+
%bf.load = load i32, ptr %LII, align 4
346+
%bf.clear4 = and i32 %bf.load, -262144
347+
%bf.set5 = select i1 %b, i32 196608, i32 131072
348+
%bf.set12 = or disjoint i32 %bf.set5, %bf.clear4
349+
store i32 %bf.set12, ptr %LII, align 4
350+
call void @callee(ptr %LII)
351+
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %LII)
352+
br label %if.end
353+
354+
if.end: ; preds = %if.then, %entry
355+
ret void
356+
}
357+
358+
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)

0 commit comments

Comments
 (0)