[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / EarlyCSE / invariant.start.ll
bloba0e267d85569c49c5eece5a2b023e6e1c35de777
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2 ; RUN: opt < %s -S -early-cse -earlycse-debug-hash | FileCheck %s --check-prefixes=CHECK,NO_ASSUME
3 ; RUN: opt < %s -S -early-cse --enable-knowledge-retention | FileCheck %s --check-prefixes=CHECK,USE_ASSUME
4 ; RUN: opt < %s -S -passes=early-cse | FileCheck %s --check-prefixes=CHECK,NO_ASSUME
6 declare {}* @llvm.invariant.start.p0i8(i64, i8* nocapture) nounwind readonly
7 declare void @llvm.invariant.end.p0i8({}*, i64, i8* nocapture) nounwind
9 ; Check that we do load-load forwarding over invariant.start, since it does not
10 ; clobber memory
11 define i8 @test_bypass1(i8 *%P) {
12 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass1
13 ; NO_ASSUME-SAME: (i8* [[P:%.*]])
14 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i8, i8* [[P]], align 1
15 ; NO_ASSUME-NEXT:    [[I:%.*]] = call {}* @llvm.invariant.start.p0i8(i64 1, i8* [[P]])
16 ; NO_ASSUME-NEXT:    ret i8 0
18 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass1
19 ; USE_ASSUME-SAME: (i8* [[P:%.*]])
20 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i8, i8* [[P]], align 1
21 ; USE_ASSUME-NEXT:    [[I:%.*]] = call {}* @llvm.invariant.start.p0i8(i64 1, i8* [[P]])
22 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i8* [[P]], i64 1), "nonnull"(i8* [[P]]) ]
23 ; USE_ASSUME-NEXT:    ret i8 0
26   %V1 = load i8, i8* %P
27   %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
28   %V2 = load i8, i8* %P
29   %Diff = sub i8 %V1, %V2
30   ret i8 %Diff
34 ; Trivial Store->load forwarding over invariant.start
35 define i8 @test_bypass2(i8 *%P) {
36 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass2
37 ; NO_ASSUME-SAME: (i8* [[P:%.*]])
38 ; NO_ASSUME-NEXT:    store i8 42, i8* [[P]], align 1
39 ; NO_ASSUME-NEXT:    [[I:%.*]] = call {}* @llvm.invariant.start.p0i8(i64 1, i8* [[P]])
40 ; NO_ASSUME-NEXT:    ret i8 42
42 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass2
43 ; USE_ASSUME-SAME: (i8* [[P:%.*]])
44 ; USE_ASSUME-NEXT:    store i8 42, i8* [[P]], align 1
45 ; USE_ASSUME-NEXT:    [[I:%.*]] = call {}* @llvm.invariant.start.p0i8(i64 1, i8* [[P]])
46 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i8* [[P]], i64 1), "nonnull"(i8* [[P]]) ]
47 ; USE_ASSUME-NEXT:    ret i8 42
50   store i8 42, i8* %P
51   %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
52   %V1 = load i8, i8* %P
53   ret i8 %V1
56 ; We can DSE over invariant.start calls, since the first store to
57 ; %P is valid, and the second store is actually unreachable based on semantics
58 ; of invariant.start.
59 define void @test_bypass3(i8* %P) {
60 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_bypass3
61 ; NO_ASSUME-SAME: (i8* [[P:%.*]])
62 ; NO_ASSUME-NEXT:    [[I:%.*]] = call {}* @llvm.invariant.start.p0i8(i64 1, i8* [[P]])
63 ; NO_ASSUME-NEXT:    store i8 60, i8* [[P]], align 1
64 ; NO_ASSUME-NEXT:    ret void
66 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_bypass3
67 ; USE_ASSUME-SAME: (i8* [[P:%.*]])
68 ; USE_ASSUME-NEXT:    [[I:%.*]] = call {}* @llvm.invariant.start.p0i8(i64 1, i8* [[P]])
69 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i8* [[P]], i64 1), "nonnull"(i8* [[P]]) ]
70 ; USE_ASSUME-NEXT:    store i8 60, i8* [[P]], align 1
71 ; USE_ASSUME-NEXT:    ret void
74   store i8 50, i8* %P
75   %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
76   store i8 60, i8* %P
77   ret void
81 ; FIXME: Now the first store can actually be eliminated, since there is no read within
82 ; the invariant region, between start and end.
83 define void @test_bypass4(i8* %P) {
84 ; CHECK-LABEL: define {{[^@]+}}@test_bypass4
85 ; CHECK-SAME: (i8* [[P:%.*]])
86 ; CHECK-NEXT:    store i8 50, i8* [[P]], align 1
87 ; CHECK-NEXT:    [[I:%.*]] = call {}* @llvm.invariant.start.p0i8(i64 1, i8* [[P]])
88 ; CHECK-NEXT:    call void @llvm.invariant.end.p0i8({}* [[I]], i64 1, i8* [[P]])
89 ; CHECK-NEXT:    store i8 60, i8* [[P]], align 1
90 ; CHECK-NEXT:    ret void
94   store i8 50, i8* %P
95   %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
96   call void @llvm.invariant.end.p0i8({}* %i, i64 1, i8* %P)
97   store i8 60, i8* %P
98   ret void
102 declare void @clobber()
103 declare {}* @llvm.invariant.start.p0i32(i64 %size, i32* nocapture %ptr)
104 declare void @llvm.invariant.end.p0i32({}*, i64, i32* nocapture) nounwind
106 define i32 @test_before_load(i32* %p) {
107 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_before_load
108 ; NO_ASSUME-SAME: (i32* [[P:%.*]])
109 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
110 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
111 ; NO_ASSUME-NEXT:    call void @clobber()
112 ; NO_ASSUME-NEXT:    ret i32 0
114 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_before_load
115 ; USE_ASSUME-SAME: (i32* [[P:%.*]])
116 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
117 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
118 ; USE_ASSUME-NEXT:    call void @clobber()
119 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
120 ; USE_ASSUME-NEXT:    ret i32 0
122   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
123   %v1 = load i32, i32* %p
124   call void @clobber()
125   %v2 = load i32, i32* %p
126   %sub = sub i32 %v1, %v2
127   ret i32 %sub
130 define i32 @test_before_clobber(i32* %p) {
131 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_before_clobber
132 ; NO_ASSUME-SAME: (i32* [[P:%.*]])
133 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
134 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
135 ; NO_ASSUME-NEXT:    call void @clobber()
136 ; NO_ASSUME-NEXT:    ret i32 0
138 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_before_clobber
139 ; USE_ASSUME-SAME: (i32* [[P:%.*]])
140 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
141 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
142 ; USE_ASSUME-NEXT:    call void @clobber()
143 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
144 ; USE_ASSUME-NEXT:    ret i32 0
146   %v1 = load i32, i32* %p
147   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
148   call void @clobber()
149   %v2 = load i32, i32* %p
150   %sub = sub i32 %v1, %v2
151   ret i32 %sub
154 define i32 @test_duplicate_scope(i32* %p) {
155 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_duplicate_scope
156 ; NO_ASSUME-SAME: (i32* [[P:%.*]])
157 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
158 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
159 ; NO_ASSUME-NEXT:    call void @clobber()
160 ; NO_ASSUME-NEXT:    [[TMP2:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
161 ; NO_ASSUME-NEXT:    ret i32 0
163 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_duplicate_scope
164 ; USE_ASSUME-SAME: (i32* [[P:%.*]])
165 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
166 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
167 ; USE_ASSUME-NEXT:    call void @clobber()
168 ; USE_ASSUME-NEXT:    [[TMP2:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
169 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
170 ; USE_ASSUME-NEXT:    ret i32 0
172   %v1 = load i32, i32* %p
173   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
174   call void @clobber()
175   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
176   %v2 = load i32, i32* %p
177   %sub = sub i32 %v1, %v2
178   ret i32 %sub
181 define i32 @test_unanalzyable_load(i32* %p) {
182 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_unanalzyable_load
183 ; NO_ASSUME-SAME: (i32* [[P:%.*]])
184 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
185 ; NO_ASSUME-NEXT:    call void @clobber()
186 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
187 ; NO_ASSUME-NEXT:    call void @clobber()
188 ; NO_ASSUME-NEXT:    ret i32 0
190 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_unanalzyable_load
191 ; USE_ASSUME-SAME: (i32* [[P:%.*]])
192 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
193 ; USE_ASSUME-NEXT:    call void @clobber()
194 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
195 ; USE_ASSUME-NEXT:    call void @clobber()
196 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
197 ; USE_ASSUME-NEXT:    ret i32 0
199   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
200   call void @clobber()
201   %v1 = load i32, i32* %p
202   call void @clobber()
203   %v2 = load i32, i32* %p
204   %sub = sub i32 %v1, %v2
205   ret i32 %sub
208 define i32 @test_negative_after_clobber(i32* %p) {
209 ; CHECK-LABEL: define {{[^@]+}}@test_negative_after_clobber
210 ; CHECK-SAME: (i32* [[P:%.*]])
211 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
212 ; CHECK-NEXT:    call void @clobber()
213 ; CHECK-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
214 ; CHECK-NEXT:    [[V2:%.*]] = load i32, i32* [[P]], align 4
215 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
216 ; CHECK-NEXT:    ret i32 [[SUB]]
218   %v1 = load i32, i32* %p
219   call void @clobber()
220   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
221   %v2 = load i32, i32* %p
222   %sub = sub i32 %v1, %v2
223   ret i32 %sub
226 define i32 @test_merge(i32* %p, i1 %cnd) {
227 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_merge
228 ; NO_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
229 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
230 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
231 ; NO_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]
232 ; NO_ASSUME:       taken:
233 ; NO_ASSUME-NEXT:    call void @clobber()
234 ; NO_ASSUME-NEXT:    br label [[MERGE]]
235 ; NO_ASSUME:       merge:
236 ; NO_ASSUME-NEXT:    ret i32 0
238 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_merge
239 ; USE_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
240 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
241 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
242 ; USE_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]
243 ; USE_ASSUME:       taken:
244 ; USE_ASSUME-NEXT:    call void @clobber()
245 ; USE_ASSUME-NEXT:    br label [[MERGE]]
246 ; USE_ASSUME:       merge:
247 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
248 ; USE_ASSUME-NEXT:    ret i32 0
250   %v1 = load i32, i32* %p
251   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
252   br i1 %cnd, label %merge, label %taken
254 taken:
255   call void @clobber()
256   br label %merge
257 merge:
258   %v2 = load i32, i32* %p
259   %sub = sub i32 %v1, %v2
260   ret i32 %sub
263 define i32 @test_negative_after_mergeclobber(i32* %p, i1 %cnd) {
264 ; CHECK-LABEL: define {{[^@]+}}@test_negative_after_mergeclobber
265 ; CHECK-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
266 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
267 ; CHECK-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]
268 ; CHECK:       taken:
269 ; CHECK-NEXT:    call void @clobber()
270 ; CHECK-NEXT:    br label [[MERGE]]
271 ; CHECK:       merge:
272 ; CHECK-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
273 ; CHECK-NEXT:    [[V2:%.*]] = load i32, i32* [[P]], align 4
274 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
275 ; CHECK-NEXT:    ret i32 [[SUB]]
277   %v1 = load i32, i32* %p
278   br i1 %cnd, label %merge, label %taken
280 taken:
281   call void @clobber()
282   br label %merge
283 merge:
284   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
285   %v2 = load i32, i32* %p
286   %sub = sub i32 %v1, %v2
287   ret i32 %sub
290 ; In theory, this version could work, but earlycse is incapable of
291 ; merging facts along distinct paths.
292 define i32 @test_false_negative_merge(i32* %p, i1 %cnd) {
293 ; CHECK-LABEL: define {{[^@]+}}@test_false_negative_merge
294 ; CHECK-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
295 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
296 ; CHECK-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]
297 ; CHECK:       taken:
298 ; CHECK-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
299 ; CHECK-NEXT:    call void @clobber()
300 ; CHECK-NEXT:    br label [[MERGE]]
301 ; CHECK:       merge:
302 ; CHECK-NEXT:    [[V2:%.*]] = load i32, i32* [[P]], align 4
303 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
304 ; CHECK-NEXT:    ret i32 [[SUB]]
306   %v1 = load i32, i32* %p
307   br i1 %cnd, label %merge, label %taken
309 taken:
310   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
311   call void @clobber()
312   br label %merge
313 merge:
314   %v2 = load i32, i32* %p
315   %sub = sub i32 %v1, %v2
316   ret i32 %sub
319 define i32 @test_merge_unanalyzable_load(i32* %p, i1 %cnd) {
320 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_merge_unanalyzable_load
321 ; NO_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
322 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
323 ; NO_ASSUME-NEXT:    call void @clobber()
324 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
325 ; NO_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]
326 ; NO_ASSUME:       taken:
327 ; NO_ASSUME-NEXT:    call void @clobber()
328 ; NO_ASSUME-NEXT:    br label [[MERGE]]
329 ; NO_ASSUME:       merge:
330 ; NO_ASSUME-NEXT:    ret i32 0
332 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_merge_unanalyzable_load
333 ; USE_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
334 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
335 ; USE_ASSUME-NEXT:    call void @clobber()
336 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
337 ; USE_ASSUME-NEXT:    br i1 [[CND]], label [[MERGE:%.*]], label [[TAKEN:%.*]]
338 ; USE_ASSUME:       taken:
339 ; USE_ASSUME-NEXT:    call void @clobber()
340 ; USE_ASSUME-NEXT:    br label [[MERGE]]
341 ; USE_ASSUME:       merge:
342 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
343 ; USE_ASSUME-NEXT:    ret i32 0
345   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
346   call void @clobber()
347   %v1 = load i32, i32* %p
348   br i1 %cnd, label %merge, label %taken
350 taken:
351   call void @clobber()
352   br label %merge
353 merge:
354   %v2 = load i32, i32* %p
355   %sub = sub i32 %v1, %v2
356   ret i32 %sub
359 define void @test_dse_before_load(i32* %p, i1 %cnd) {
360 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_dse_before_load
361 ; NO_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
362 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
363 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
364 ; NO_ASSUME-NEXT:    call void @clobber()
365 ; NO_ASSUME-NEXT:    ret void
367 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_dse_before_load
368 ; USE_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
369 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
370 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
371 ; USE_ASSUME-NEXT:    call void @clobber()
372 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
373 ; USE_ASSUME-NEXT:    ret void
375   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
376   %v1 = load i32, i32* %p
377   call void @clobber()
378   store i32 %v1, i32* %p
379   ret void
382 define void @test_dse_after_load(i32* %p, i1 %cnd) {
383 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_dse_after_load
384 ; NO_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
385 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
386 ; NO_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
387 ; NO_ASSUME-NEXT:    call void @clobber()
388 ; NO_ASSUME-NEXT:    ret void
390 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_dse_after_load
391 ; USE_ASSUME-SAME: (i32* [[P:%.*]], i1 [[CND:%.*]])
392 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
393 ; USE_ASSUME-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
394 ; USE_ASSUME-NEXT:    call void @clobber()
395 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
396 ; USE_ASSUME-NEXT:    ret void
398   %v1 = load i32, i32* %p
399   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
400   call void @clobber()
401   store i32 %v1, i32* %p
402   ret void
406 ; In this case, we have a false negative since MemoryLocation is implicitly
407 ; typed due to the user of a Value to represent the address.  Note that other
408 ; passes will canonicalize away the bitcasts in this example.
409 define i32 @test_false_negative_types(i32* %p) {
410 ; CHECK-LABEL: define {{[^@]+}}@test_false_negative_types
411 ; CHECK-SAME: (i32* [[P:%.*]])
412 ; CHECK-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
413 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
414 ; CHECK-NEXT:    call void @clobber()
415 ; CHECK-NEXT:    [[PF:%.*]] = bitcast i32* [[P]] to float*
416 ; CHECK-NEXT:    [[V2F:%.*]] = load float, float* [[PF]], align 4
417 ; CHECK-NEXT:    [[V2:%.*]] = bitcast float [[V2F]] to i32
418 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
419 ; CHECK-NEXT:    ret i32 [[SUB]]
421   call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
422   %v1 = load i32, i32* %p
423   call void @clobber()
424   %pf = bitcast i32* %p to float*
425   %v2f = load float, float* %pf
426   %v2 = bitcast float %v2f to i32
427   %sub = sub i32 %v1, %v2
428   ret i32 %sub
431 define i32 @test_negative_size1(i32* %p) {
432 ; CHECK-LABEL: define {{[^@]+}}@test_negative_size1
433 ; CHECK-SAME: (i32* [[P:%.*]])
434 ; CHECK-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 3, i32* [[P]])
435 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
436 ; CHECK-NEXT:    call void @clobber()
437 ; CHECK-NEXT:    [[V2:%.*]] = load i32, i32* [[P]], align 4
438 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
439 ; CHECK-NEXT:    ret i32 [[SUB]]
441   call {}* @llvm.invariant.start.p0i32(i64 3, i32* %p)
442   %v1 = load i32, i32* %p
443   call void @clobber()
444   %v2 = load i32, i32* %p
445   %sub = sub i32 %v1, %v2
446   ret i32 %sub
449 define i32 @test_negative_size2(i32* %p) {
450 ; CHECK-LABEL: define {{[^@]+}}@test_negative_size2
451 ; CHECK-SAME: (i32* [[P:%.*]])
452 ; CHECK-NEXT:    [[TMP1:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 0, i32* [[P]])
453 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
454 ; CHECK-NEXT:    call void @clobber()
455 ; CHECK-NEXT:    [[V2:%.*]] = load i32, i32* [[P]], align 4
456 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
457 ; CHECK-NEXT:    ret i32 [[SUB]]
459   call {}* @llvm.invariant.start.p0i32(i64 0, i32* %p)
460   %v1 = load i32, i32* %p
461   call void @clobber()
462   %v2 = load i32, i32* %p
463   %sub = sub i32 %v1, %v2
464   ret i32 %sub
467 define i32 @test_negative_scope(i32* %p) {
468 ; CHECK-LABEL: define {{[^@]+}}@test_negative_scope
469 ; CHECK-SAME: (i32* [[P:%.*]])
470 ; CHECK-NEXT:    [[SCOPE:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
471 ; CHECK-NEXT:    call void @llvm.invariant.end.p0i32({}* [[SCOPE]], i64 4, i32* [[P]])
472 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
473 ; CHECK-NEXT:    call void @clobber()
474 ; CHECK-NEXT:    [[V2:%.*]] = load i32, i32* [[P]], align 4
475 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
476 ; CHECK-NEXT:    ret i32 [[SUB]]
478   %scope = call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
479   call void @llvm.invariant.end.p0i32({}* %scope, i64 4, i32* %p)
480   %v1 = load i32, i32* %p
481   call void @clobber()
482   %v2 = load i32, i32* %p
483   %sub = sub i32 %v1, %v2
484   ret i32 %sub
487 define i32 @test_false_negative_scope(i32* %p) {
488 ; CHECK-LABEL: define {{[^@]+}}@test_false_negative_scope
489 ; CHECK-SAME: (i32* [[P:%.*]])
490 ; CHECK-NEXT:    [[SCOPE:%.*]] = call {}* @llvm.invariant.start.p0i32(i64 4, i32* [[P]])
491 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4
492 ; CHECK-NEXT:    call void @clobber()
493 ; CHECK-NEXT:    [[V2:%.*]] = load i32, i32* [[P]], align 4
494 ; CHECK-NEXT:    call void @llvm.invariant.end.p0i32({}* [[SCOPE]], i64 4, i32* [[P]])
495 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[V1]], [[V2]]
496 ; CHECK-NEXT:    ret i32 [[SUB]]
498   %scope = call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
499   %v1 = load i32, i32* %p
500   call void @clobber()
501   %v2 = load i32, i32* %p
502   call void @llvm.invariant.end.p0i32({}* %scope, i64 4, i32* %p)
503   %sub = sub i32 %v1, %v2
504   ret i32 %sub
507 ; Invariant load defact starts an invariant.start scope of the appropriate size
508 define i32 @test_invariant_load_scope(i32* %p) {
509 ; NO_ASSUME-LABEL: define {{[^@]+}}@test_invariant_load_scope
510 ; NO_ASSUME-SAME: (i32* [[P:%.*]])
511 ; NO_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4, !invariant.load !0
512 ; NO_ASSUME-NEXT:    call void @clobber()
513 ; NO_ASSUME-NEXT:    ret i32 0
515 ; USE_ASSUME-LABEL: define {{[^@]+}}@test_invariant_load_scope
516 ; USE_ASSUME-SAME: (i32* [[P:%.*]])
517 ; USE_ASSUME-NEXT:    [[V1:%.*]] = load i32, i32* [[P]], align 4, !invariant.load !0
518 ; USE_ASSUME-NEXT:    call void @clobber()
519 ; USE_ASSUME-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ]
520 ; USE_ASSUME-NEXT:    ret i32 0
522   %v1 = load i32, i32* %p, !invariant.load !{}
523   call void @clobber()
524   %v2 = load i32, i32* %p
525   %sub = sub i32 %v1, %v2
526   ret i32 %sub
529 ; USE_ASSUME: declare void @llvm.assume(i1 noundef)