Skip to content

Commit 8fa440a

Browse files
committed
[LV] Add tests for speculatively loading ptrs with UB/poison ops.
Test cases for #142957.
1 parent d398f47 commit 8fa440a

File tree

1 file changed

+386
-0
lines changed

1 file changed

+386
-0
lines changed
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --filter-out-after "scalar.ph:" --version 5
2+
; RUN: opt -p loop-vectorize -force-widen-divrem-via-safe-divisor=false -force-vector-width=2 -S %s | FileCheck %s
3+
4+
target datalayout="p:16:16"
5+
6+
@src = global [16 x i64] zeroinitializer
7+
8+
; Test cases for https://github.com/llvm/llvm-project/issues/142957
9+
10+
; FIXME: Cannot speculatively execute %l, because %div may trigger UB and must be
11+
; predicated.
12+
define void @ptr_depends_on_sdiv(ptr noalias %dst, i16 noundef %off) {
13+
; CHECK-LABEL: define void @ptr_depends_on_sdiv(
14+
; CHECK-SAME: ptr noalias [[DST:%.*]], i16 noundef [[OFF:%.*]]) {
15+
; CHECK-NEXT: [[ENTRY:.*:]]
16+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
17+
; CHECK: [[VECTOR_PH]]:
18+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
19+
; CHECK: [[VECTOR_BODY]]:
20+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE4:.*]] ]
21+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ <i16 9, i16 10>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE4]] ]
22+
; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16
23+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]]
24+
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10)
25+
; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP0]], i32 0
26+
; CHECK-NEXT: br i1 [[TMP6]], label %[[PRED_SDIV_IF:.*]], label %[[PRED_SDIV_CONTINUE:.*]]
27+
; CHECK: [[PRED_SDIV_IF]]:
28+
; CHECK-NEXT: [[TMP2:%.*]] = sdiv i16 24316, [[OFF]]
29+
; CHECK-NEXT: br label %[[PRED_SDIV_CONTINUE]]
30+
; CHECK: [[PRED_SDIV_CONTINUE]]:
31+
; CHECK-NEXT: [[TMP3:%.*]] = phi i16 [ poison, %[[VECTOR_BODY]] ], [ [[TMP2]], %[[PRED_SDIV_IF]] ]
32+
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i1> [[TMP0]], i32 1
33+
; CHECK-NEXT: br i1 [[TMP14]], label %[[PRED_SDIV_IF1:.*]], label %[[PRED_SDIV_CONTINUE2:.*]]
34+
; CHECK: [[PRED_SDIV_IF1]]:
35+
; CHECK-NEXT: [[TMP18:%.*]] = sdiv i16 24316, [[OFF]]
36+
; CHECK-NEXT: br label %[[PRED_SDIV_CONTINUE2]]
37+
; CHECK: [[PRED_SDIV_CONTINUE2]]:
38+
; CHECK-NEXT: [[TMP13:%.*]] = add i16 [[OFFSET_IDX]], 16383
39+
; CHECK-NEXT: [[TMP7:%.*]] = shl i16 [[TMP3]], 14
40+
; CHECK-NEXT: [[TMP8:%.*]] = sub i16 [[TMP13]], [[TMP7]]
41+
; CHECK-NEXT: [[TMP20:%.*]] = getelementptr i64, ptr @src, i16 [[TMP8]]
42+
; CHECK-NEXT: [[TMP21:%.*]] = getelementptr i64, ptr [[TMP20]], i32 0
43+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP21]], align 1
44+
; CHECK-NEXT: [[TMP19:%.*]] = extractelement <2 x i1> [[TMP0]], i32 0
45+
; CHECK-NEXT: br i1 [[TMP19]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]]
46+
; CHECK: [[PRED_STORE_IF]]:
47+
; CHECK-NEXT: [[TMP10:%.*]] = add i16 [[OFFSET_IDX]], 0
48+
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP10]]
49+
; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 0
50+
; CHECK-NEXT: store i64 [[TMP9]], ptr [[TMP11]], align 1
51+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]]
52+
; CHECK: [[PRED_STORE_CONTINUE]]:
53+
; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i1> [[TMP0]], i32 1
54+
; CHECK-NEXT: br i1 [[TMP12]], label %[[PRED_STORE_IF3:.*]], label %[[PRED_STORE_CONTINUE4]]
55+
; CHECK: [[PRED_STORE_IF3]]:
56+
; CHECK-NEXT: [[TMP16:%.*]] = add i16 [[OFFSET_IDX]], 1
57+
; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP16]]
58+
; CHECK-NEXT: [[TMP15:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 1
59+
; CHECK-NEXT: store i64 [[TMP15]], ptr [[TMP17]], align 1
60+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE4]]
61+
; CHECK: [[PRED_STORE_CONTINUE4]]:
62+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2)
63+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
64+
; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
65+
; CHECK: [[MIDDLE_BLOCK]]:
66+
; CHECK-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]]
67+
; CHECK: [[SCALAR_PH]]:
68+
;
69+
entry:
70+
br label %loop.header
71+
72+
loop.header:
73+
%iv = phi i16 [ 9, %entry ], [ %iv.next, %loop.latch ]
74+
%cmp1 = icmp eq i16 %iv, 10
75+
br i1 %cmp1, label %if.then, label %loop.latch
76+
77+
if.then:
78+
%div = sdiv i16 24316, %off
79+
%add.iv = add i16 %iv, 16383
80+
%s = shl i16 %div, 14
81+
%sub6 = sub i16 %add.iv, %s
82+
%gep.src = getelementptr inbounds i64, ptr @src, i16 %sub6
83+
%l = load i64, ptr %gep.src, align 1
84+
%gep.dst = getelementptr inbounds i64, ptr %dst, i16 %iv
85+
store i64 %l, ptr %gep.dst, align 1
86+
br label %loop.latch
87+
88+
loop.latch:
89+
%iv.next = add i16 %iv, 1
90+
%ec = icmp eq i16 %iv.next, 11
91+
br i1 %ec, label %exit, label %loop.header
92+
93+
exit:
94+
ret void
95+
}
96+
97+
; FIXME: Cannot speculatively execute %l, because %off may be poison.
98+
define void @ptr_depends_on_possibly_poison_value(ptr noalias %dst, i16 %off) {
99+
; CHECK-LABEL: define void @ptr_depends_on_possibly_poison_value(
100+
; CHECK-SAME: ptr noalias [[DST:%.*]], i16 [[OFF:%.*]]) {
101+
; CHECK-NEXT: [[ENTRY:.*:]]
102+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
103+
; CHECK: [[VECTOR_PH]]:
104+
; CHECK-NEXT: [[TMP0:%.*]] = sub i16 1, [[OFF]]
105+
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], [[OFF]]
106+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
107+
; CHECK: [[VECTOR_BODY]]:
108+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ]
109+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ <i16 9, i16 10>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ]
110+
; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16
111+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]]
112+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10)
113+
; CHECK-NEXT: [[TMP3:%.*]] = add i16 [[OFFSET_IDX]], [[TMP1]]
114+
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i64, ptr @src, i16 [[TMP3]]
115+
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, ptr [[TMP4]], i32 0
116+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP5]], align 1
117+
; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP2]], i32 0
118+
; CHECK-NEXT: br i1 [[TMP6]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]]
119+
; CHECK: [[PRED_STORE_IF]]:
120+
; CHECK-NEXT: [[TMP7:%.*]] = add i16 [[OFFSET_IDX]], 0
121+
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP7]]
122+
; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 0
123+
; CHECK-NEXT: store i64 [[TMP9]], ptr [[TMP8]], align 1
124+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]]
125+
; CHECK: [[PRED_STORE_CONTINUE]]:
126+
; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP2]], i32 1
127+
; CHECK-NEXT: br i1 [[TMP10]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]]
128+
; CHECK: [[PRED_STORE_IF1]]:
129+
; CHECK-NEXT: [[TMP11:%.*]] = add i16 [[OFFSET_IDX]], 1
130+
; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP11]]
131+
; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 1
132+
; CHECK-NEXT: store i64 [[TMP13]], ptr [[TMP12]], align 1
133+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]]
134+
; CHECK: [[PRED_STORE_CONTINUE2]]:
135+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2)
136+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
137+
; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
138+
; CHECK: [[MIDDLE_BLOCK]]:
139+
; CHECK-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]]
140+
; CHECK: [[SCALAR_PH]]:
141+
;
142+
entry:
143+
br label %loop.header
144+
145+
loop.header:
146+
%iv = phi i16 [ 9, %entry ], [ %iv.next, %loop.latch ]
147+
%cmp1 = icmp eq i16 %iv, 10
148+
br i1 %cmp1, label %if.then, label %loop.latch
149+
150+
if.then:
151+
%sub = sub i16 1, %off
152+
%add = add i16 %sub, %off
153+
%add.iv = add i16 %iv, %add
154+
%gep.src = getelementptr inbounds i64, ptr @src, i16 %add.iv
155+
%l = load i64, ptr %gep.src, align 1
156+
%gep.dst = getelementptr inbounds i64, ptr %dst, i16 %iv
157+
store i64 %l, ptr %gep.dst, align 1
158+
br label %loop.latch
159+
160+
loop.latch:
161+
%iv.next = add i16 %iv, 1
162+
%ec = icmp eq i16 %iv.next, 11
163+
br i1 %ec, label %exit, label %loop.header
164+
165+
exit:
166+
ret void
167+
}
168+
169+
define void @ptr_doesnt_depend_on_poison_or_ub(ptr noalias %dst, i16 noundef %off) {
170+
; CHECK-LABEL: define void @ptr_doesnt_depend_on_poison_or_ub(
171+
; CHECK-SAME: ptr noalias [[DST:%.*]], i16 noundef [[OFF:%.*]]) {
172+
; CHECK-NEXT: [[ENTRY:.*:]]
173+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
174+
; CHECK: [[VECTOR_PH]]:
175+
; CHECK-NEXT: [[TMP0:%.*]] = sub i16 1, [[OFF]]
176+
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], [[OFF]]
177+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
178+
; CHECK: [[VECTOR_BODY]]:
179+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ]
180+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ <i16 9, i16 10>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ]
181+
; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16
182+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]]
183+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10)
184+
; CHECK-NEXT: [[TMP3:%.*]] = add i16 [[OFFSET_IDX]], [[TMP1]]
185+
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i64, ptr @src, i16 [[TMP3]]
186+
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, ptr [[TMP4]], i32 0
187+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP5]], align 1
188+
; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP2]], i32 0
189+
; CHECK-NEXT: br i1 [[TMP6]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]]
190+
; CHECK: [[PRED_STORE_IF]]:
191+
; CHECK-NEXT: [[TMP7:%.*]] = add i16 [[OFFSET_IDX]], 0
192+
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP7]]
193+
; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 0
194+
; CHECK-NEXT: store i64 [[TMP9]], ptr [[TMP8]], align 1
195+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]]
196+
; CHECK: [[PRED_STORE_CONTINUE]]:
197+
; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP2]], i32 1
198+
; CHECK-NEXT: br i1 [[TMP10]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]]
199+
; CHECK: [[PRED_STORE_IF1]]:
200+
; CHECK-NEXT: [[TMP11:%.*]] = add i16 [[OFFSET_IDX]], 1
201+
; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP11]]
202+
; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 1
203+
; CHECK-NEXT: store i64 [[TMP13]], ptr [[TMP12]], align 1
204+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]]
205+
; CHECK: [[PRED_STORE_CONTINUE2]]:
206+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2)
207+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
208+
; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
209+
; CHECK: [[MIDDLE_BLOCK]]:
210+
; CHECK-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]]
211+
; CHECK: [[SCALAR_PH]]:
212+
;
213+
entry:
214+
br label %loop.header
215+
216+
loop.header:
217+
%iv = phi i16 [ 9, %entry ], [ %iv.next, %loop.latch ]
218+
%cmp1 = icmp eq i16 %iv, 10
219+
br i1 %cmp1, label %if.then, label %loop.latch
220+
221+
if.then:
222+
%sub = sub i16 1, %off
223+
%add = add i16 %sub, %off
224+
%add.iv = add i16 %iv, %add
225+
%gep.src = getelementptr inbounds i64, ptr @src, i16 %add.iv
226+
%l = load i64, ptr %gep.src, align 1
227+
%gep.dst = getelementptr inbounds i64, ptr %dst, i16 %iv
228+
store i64 %l, ptr %gep.dst, align 1
229+
br label %loop.latch
230+
231+
loop.latch:
232+
%iv.next = add i16 %iv, 1
233+
%ec = icmp eq i16 %iv.next, 11
234+
br i1 %ec, label %exit, label %loop.header
235+
236+
exit:
237+
ret void
238+
}
239+
240+
; FIXME: Cannot speculatively execute %l, because %off may be poison.
241+
define void @ptr_depends_on_possibly_poison_value_from_load(ptr noalias %dst) {
242+
; CHECK-LABEL: define void @ptr_depends_on_possibly_poison_value_from_load(
243+
; CHECK-SAME: ptr noalias [[DST:%.*]]) {
244+
; CHECK-NEXT: [[ENTRY:.*:]]
245+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
246+
; CHECK: [[VECTOR_PH]]:
247+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
248+
; CHECK: [[VECTOR_BODY]]:
249+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ]
250+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ <i16 9, i16 10>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ]
251+
; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16
252+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]]
253+
; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @src, align 1
254+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10)
255+
; CHECK-NEXT: [[TMP2:%.*]] = sub i16 1, [[TMP0]]
256+
; CHECK-NEXT: [[TMP3:%.*]] = add i16 [[TMP2]], [[TMP0]]
257+
; CHECK-NEXT: [[TMP4:%.*]] = add i16 [[OFFSET_IDX]], [[TMP3]]
258+
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, ptr @src, i16 [[TMP4]]
259+
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, ptr [[TMP5]], i32 0
260+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP6]], align 1
261+
; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i1> [[TMP1]], i32 0
262+
; CHECK-NEXT: br i1 [[TMP7]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]]
263+
; CHECK: [[PRED_STORE_IF]]:
264+
; CHECK-NEXT: [[TMP8:%.*]] = add i16 [[OFFSET_IDX]], 0
265+
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP8]]
266+
; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 0
267+
; CHECK-NEXT: store i64 [[TMP10]], ptr [[TMP9]], align 1
268+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]]
269+
; CHECK: [[PRED_STORE_CONTINUE]]:
270+
; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP1]], i32 1
271+
; CHECK-NEXT: br i1 [[TMP11]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]]
272+
; CHECK: [[PRED_STORE_IF1]]:
273+
; CHECK-NEXT: [[TMP12:%.*]] = add i16 [[OFFSET_IDX]], 1
274+
; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP12]]
275+
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 1
276+
; CHECK-NEXT: store i64 [[TMP14]], ptr [[TMP13]], align 1
277+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]]
278+
; CHECK: [[PRED_STORE_CONTINUE2]]:
279+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2)
280+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
281+
; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]
282+
; CHECK: [[MIDDLE_BLOCK]]:
283+
; CHECK-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]]
284+
; CHECK: [[SCALAR_PH]]:
285+
;
286+
entry:
287+
br label %loop.header
288+
289+
loop.header:
290+
%iv = phi i16 [ 9, %entry ], [ %iv.next, %loop.latch ]
291+
%off = load i16, ptr @src, align 1
292+
%cmp1 = icmp eq i16 %iv, 10
293+
br i1 %cmp1, label %if.then, label %loop.latch
294+
295+
if.then:
296+
%sub = sub i16 1, %off
297+
%add = add i16 %sub, %off
298+
%add.iv = add i16 %iv, %add
299+
%gep.src = getelementptr inbounds i64, ptr @src, i16 %add.iv
300+
%l = load i64, ptr %gep.src, align 1
301+
%gep.dst = getelementptr inbounds i64, ptr %dst, i16 %iv
302+
store i64 %l, ptr %gep.dst, align 1
303+
br label %loop.latch
304+
305+
loop.latch:
306+
%iv.next = add i16 %iv, 1
307+
%ec = icmp eq i16 %iv.next, 11
308+
br i1 %ec, label %exit, label %loop.header
309+
310+
exit:
311+
ret void
312+
}
313+
314+
; Can speculatively execute %l, because %off cannot be poison due to !noundef.
315+
define void @ptr_depends_on_noundef_load(ptr noalias %dst) {
316+
; CHECK-LABEL: define void @ptr_depends_on_noundef_load(
317+
; CHECK-SAME: ptr noalias [[DST:%.*]]) {
318+
; CHECK-NEXT: [[ENTRY:.*:]]
319+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
320+
; CHECK: [[VECTOR_PH]]:
321+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
322+
; CHECK: [[VECTOR_BODY]]:
323+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ]
324+
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ <i16 9, i16 10>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ]
325+
; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16
326+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]]
327+
; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @src, align 1, !noundef [[META10:![0-9]+]]
328+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10)
329+
; CHECK-NEXT: [[TMP2:%.*]] = sub i16 1, [[TMP0]]
330+
; CHECK-NEXT: [[TMP3:%.*]] = add i16 [[TMP2]], [[TMP0]]
331+
; CHECK-NEXT: [[TMP4:%.*]] = add i16 [[OFFSET_IDX]], [[TMP3]]
332+
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, ptr @src, i16 [[TMP4]]
333+
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, ptr [[TMP5]], i32 0
334+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP6]], align 1
335+
; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i1> [[TMP1]], i32 0
336+
; CHECK-NEXT: br i1 [[TMP7]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]]
337+
; CHECK: [[PRED_STORE_IF]]:
338+
; CHECK-NEXT: [[TMP8:%.*]] = add i16 [[OFFSET_IDX]], 0
339+
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP8]]
340+
; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 0
341+
; CHECK-NEXT: store i64 [[TMP10]], ptr [[TMP9]], align 1
342+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]]
343+
; CHECK: [[PRED_STORE_CONTINUE]]:
344+
; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP1]], i32 1
345+
; CHECK-NEXT: br i1 [[TMP11]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]]
346+
; CHECK: [[PRED_STORE_IF1]]:
347+
; CHECK-NEXT: [[TMP12:%.*]] = add i16 [[OFFSET_IDX]], 1
348+
; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP12]]
349+
; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 1
350+
; CHECK-NEXT: store i64 [[TMP14]], ptr [[TMP13]], align 1
351+
; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]]
352+
; CHECK: [[PRED_STORE_CONTINUE2]]:
353+
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2)
354+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
355+
; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP11:![0-9]+]]
356+
; CHECK: [[MIDDLE_BLOCK]]:
357+
; CHECK-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]]
358+
; CHECK: [[SCALAR_PH]]:
359+
;
360+
entry:
361+
br label %loop.header
362+
363+
loop.header:
364+
%iv = phi i16 [ 9, %entry ], [ %iv.next, %loop.latch ]
365+
%off = load i16, ptr @src, align 1, !noundef !{}
366+
%cmp1 = icmp eq i16 %iv, 10
367+
br i1 %cmp1, label %if.then, label %loop.latch
368+
369+
if.then:
370+
%sub = sub i16 1, %off
371+
%add = add i16 %sub, %off
372+
%add.iv = add i16 %iv, %add
373+
%gep.src = getelementptr inbounds i64, ptr @src, i16 %add.iv
374+
%l = load i64, ptr %gep.src, align 1
375+
%gep.dst = getelementptr inbounds i64, ptr %dst, i16 %iv
376+
store i64 %l, ptr %gep.dst, align 1
377+
br label %loop.latch
378+
379+
loop.latch:
380+
%iv.next = add i16 %iv, 1
381+
%ec = icmp eq i16 %iv.next, 11
382+
br i1 %ec, label %exit, label %loop.header
383+
384+
exit:
385+
ret void
386+
}

0 commit comments

Comments
 (0)