[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / multiblock-multipath.ll
blobab7a056f7018d4cd99a948e5edafa28022ed9dd5
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -basic-aa -dse -S | FileCheck %s
4 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
6 declare void @use(i32 *)
8 ; Tests where the pointer/object is accessible after the function returns.
10 define void @accessible_after_return_1(i32* noalias %P, i1 %c1) {
11 ; CHECK-LABEL: @accessible_after_return_1(
12 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
13 ; CHECK:       bb1:
14 ; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
15 ; CHECK-NEXT:    br label [[BB5:%.*]]
16 ; CHECK:       bb2:
17 ; CHECK-NEXT:    store i32 3, i32* [[P]], align 4
18 ; CHECK-NEXT:    br label [[BB5]]
19 ; CHECK:       bb5:
20 ; CHECK-NEXT:    call void @use(i32* [[P]])
21 ; CHECK-NEXT:    ret void
23   store i32 1, i32* %P
24   br i1 %c1, label %bb1, label %bb2
26 bb1:
27   store i32 0, i32* %P
28   br label %bb5
29 bb2:
30   store i32 3, i32* %P
31   br label %bb5
33 bb5:
34   call void @use(i32* %P)
35   ret void
38 define void @accessible_after_return_2(i32* noalias %P, i1 %c.1, i1 %c.2) {
39 ; CHECK-LABEL: @accessible_after_return_2(
40 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
41 ; CHECK:       bb1:
42 ; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
43 ; CHECK-NEXT:    br label [[BB5:%.*]]
44 ; CHECK:       bb2:
45 ; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
46 ; CHECK:       bb3:
47 ; CHECK-NEXT:    store i32 3, i32* [[P]], align 4
48 ; CHECK-NEXT:    br label [[BB5]]
49 ; CHECK:       bb4:
50 ; CHECK-NEXT:    store i32 5, i32* [[P]], align 4
51 ; CHECK-NEXT:    br label [[BB5]]
52 ; CHECK:       bb5:
53 ; CHECK-NEXT:    call void @use(i32* [[P]])
54 ; CHECK-NEXT:    ret void
56   store i32 1, i32* %P
57   br i1 %c.1, label %bb1, label %bb2
58 bb1:
59   store i32 0, i32* %P
60   br label %bb5
62 bb2:
63   br i1 %c.2, label %bb3, label %bb4
65 bb3:
66   store i32 3, i32* %P
67   br label %bb5
69 bb4:
70   store i32 5, i32* %P
71   br label %bb5
73 bb5:
74   call void @use(i32* %P)
75   ret void
78 ; Cannot remove store in entry block because it is not overwritten on path
79 ; entry->bb2->bb5.
80 define void @accessible_after_return_3(i32* noalias %P, i1 %c1) {
81 ; CHECK-LABEL: @accessible_after_return_3(
82 ; CHECK-NEXT:    store i32 1, i32* [[P:%.*]], align 4
83 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
84 ; CHECK:       bb1:
85 ; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
86 ; CHECK-NEXT:    br label [[BB5:%.*]]
87 ; CHECK:       bb2:
88 ; CHECK-NEXT:    br label [[BB5]]
89 ; CHECK:       bb5:
90 ; CHECK-NEXT:    call void @use(i32* [[P]])
91 ; CHECK-NEXT:    ret void
93   store i32 1, i32* %P
94   br i1 %c1, label %bb1, label %bb2
96 bb1:
97   store i32 0, i32* %P
98   br label %bb5
100 bb2:
101   br label %bb5
103 bb5:
104   call void @use(i32* %P)
105   ret void
108 ; Cannot remove store in entry block because it is not overwritten on path
109 ; entry->bb2->bb5.
110 define void @accessible_after_return_4(i32* noalias %P, i1 %c1) {
111 ; CHECK-LABEL: @accessible_after_return_4(
112 ; CHECK-NEXT:    store i32 1, i32* [[P:%.*]], align 4
113 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
114 ; CHECK:       bb1:
115 ; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
116 ; CHECK-NEXT:    call void @use(i32* [[P]])
117 ; CHECK-NEXT:    br label [[BB5:%.*]]
118 ; CHECK:       bb2:
119 ; CHECK-NEXT:    br label [[BB5]]
120 ; CHECK:       bb5:
121 ; CHECK-NEXT:    ret void
123   store i32 1, i32* %P
124   br i1 %c1, label %bb1, label %bb2
126 bb1:
127   store i32 0, i32* %P
128   call void @use(i32* %P)
129   br label %bb5
131 bb2:
132   br label %bb5
134 bb5:
135   ret void
138 ; Cannot remove the store in entry, as it is not overwritten on all paths to an
139 ; exit (patch including bb4).
140 define void @accessible_after_return5(i32* %P, i1 %c.1, i1 %c.2) {
141 ; CHECK-LABEL: @accessible_after_return5(
142 ; CHECK-NEXT:  entry:
143 ; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
144 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
145 ; CHECK:       bb1:
146 ; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
147 ; CHECK:       bb2:
148 ; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
149 ; CHECK-NEXT:    br label [[BB5:%.*]]
150 ; CHECK:       bb3:
151 ; CHECK-NEXT:    store i32 2, i32* [[P]], align 4
152 ; CHECK-NEXT:    br label [[BB5]]
153 ; CHECK:       bb4:
154 ; CHECK-NEXT:    br label [[BB5]]
155 ; CHECK:       bb5:
156 ; CHECK-NEXT:    ret void
158 entry:
159   store i32 0, i32* %P
160   br i1 %c.1, label %bb1, label %bb2
162 bb1:
163   br i1 %c.2, label %bb3, label %bb4
165 bb2:
166   store i32 1, i32* %P
167   br label %bb5
169 bb3:
170   store i32 2, i32* %P
171   br label %bb5
173 bb4:
174   br label %bb5
176 bb5:
177   ret void
180 ; Can remove store in entry block, because it is overwritten before each return.
181 define void @accessible_after_return6(i32* %P, i1 %c.1, i1 %c.2) {
182 ; CHECK-LABEL: @accessible_after_return6(
183 ; CHECK-NEXT:  entry:
184 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
185 ; CHECK:       bb1:
186 ; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
187 ; CHECK:       bb2:
188 ; CHECK-NEXT:    store i32 1, i32* [[P:%.*]], align 4
189 ; CHECK-NEXT:    ret void
190 ; CHECK:       bb3:
191 ; CHECK-NEXT:    store i32 2, i32* [[P]], align 4
192 ; CHECK-NEXT:    ret void
193 ; CHECK:       bb4:
194 ; CHECK-NEXT:    store i32 3, i32* [[P]], align 4
195 ; CHECK-NEXT:    ret void
197 entry:
198   store i32 0, i32* %P
199   br i1 %c.1, label %bb1, label %bb2
201 bb1:
202   br i1 %c.2, label %bb3, label %bb4
204 bb2:
205   store i32 1, i32* %P
206   ret void
208 bb3:
209   store i32 2, i32* %P
210   ret void
212 bb4:
213   store i32 3, i32* %P
214   ret void
217 ; Can remove store in bb1, because it is overwritten along each path
218 ; from bb1 to the exit.
219 define void @accessible_after_return7(i32* %P, i1 %c.1, i1 %c.2) {
220 ; CHECK-LABEL: @accessible_after_return7(
221 ; CHECK-NEXT:  entry:
222 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
223 ; CHECK:       bb1:
224 ; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
225 ; CHECK:       bb3:
226 ; CHECK-NEXT:    store i32 2, i32* [[P:%.*]], align 4
227 ; CHECK-NEXT:    br label [[BB5:%.*]]
228 ; CHECK:       bb4:
229 ; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
230 ; CHECK-NEXT:    br label [[BB5]]
231 ; CHECK:       bb2:
232 ; CHECK-NEXT:    br label [[BB5]]
233 ; CHECK:       bb5:
234 ; CHECK-NEXT:    ret void
236 entry:
237   br i1 %c.1, label %bb1, label %bb2
239 bb1:
240   store i32 0, i32* %P
241   br i1 %c.2, label %bb3, label %bb4
243 bb3:
244   store i32 2, i32* %P
245   br label %bb5
247 bb4:
248   store i32 1, i32* %P
249   br label %bb5
251 bb2:
252   br label %bb5
254 bb5:
255   ret void
259 ; Cannot remove store in entry block, because it is overwritten along each path to
260 ; the exit (entry->bb1->bb4->bb5).
261 define void @accessible_after_return8(i32* %P, i1 %c.1, i1 %c.2) {
262 ; CHECK-LABEL: @accessible_after_return8(
263 ; CHECK-NEXT:  entry:
264 ; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
265 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
266 ; CHECK:       bb1:
267 ; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
268 ; CHECK:       bb2:
269 ; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
270 ; CHECK-NEXT:    br label [[BB5:%.*]]
271 ; CHECK:       bb3:
272 ; CHECK-NEXT:    store i32 2, i32* [[P]], align 4
273 ; CHECK-NEXT:    br label [[BB5]]
274 ; CHECK:       bb4:
275 ; CHECK-NEXT:    br label [[BB5]]
276 ; CHECK:       bb5:
277 ; CHECK-NEXT:    ret void
279 entry:
280   store i32 0, i32* %P
281   br i1 %c.1, label %bb1, label %bb2
283 bb1:
284   br i1 %c.2, label %bb3, label %bb4
286 bb2:
287   store i32 1, i32* %P
288   br label %bb5
290 bb3:
291   store i32 2, i32* %P
292   br label %bb5
294 bb4:
295   br label %bb5
297 bb5:
298   ret void
301 ; Make sure no stores are removed here. In particular, the store in if.then
302 ; should not be removed.
303 define void @accessible_after_return9(i8* noalias %ptr) {
304 ; CHECK-LABEL: @accessible_after_return9(
305 ; CHECK-NEXT:  entry:
306 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
307 ; CHECK-NEXT:    br i1 [[C_0]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
308 ; CHECK:       for.body:
309 ; CHECK-NEXT:    store i8 99, i8* [[PTR:%.*]], align 8
310 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
311 ; CHECK-NEXT:    br i1 [[C_1]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
312 ; CHECK:       if.then:
313 ; CHECK-NEXT:    store i8 20, i8* [[PTR]], align 8
314 ; CHECK-NEXT:    br label [[IF_END]]
315 ; CHECK:       if.end:
316 ; CHECK-NEXT:    [[C_2:%.*]] = call i1 @cond()
317 ; CHECK-NEXT:    br i1 [[C_2]], label [[IF_THEN10:%.*]], label [[FOR_INC:%.*]]
318 ; CHECK:       if.then10:
319 ; CHECK-NEXT:    store i8 0, i8* [[PTR]], align 8
320 ; CHECK-NEXT:    br label [[FOR_INC]]
321 ; CHECK:       for.inc:
322 ; CHECK-NEXT:    [[C_3:%.*]] = call i1 @cond()
323 ; CHECK-NEXT:    br i1 [[C_3]], label [[FOR_BODY]], label [[FOR_END]]
324 ; CHECK:       for.end:
325 ; CHECK-NEXT:    ret void
327 entry:
328   %c.0 = call i1 @cond()
329   br i1 %c.0, label %for.body, label %for.end
331 for.body:
332   store i8 99, i8* %ptr, align 8
333   %c.1 = call i1 @cond()
334   br i1 %c.1, label %if.end, label %if.then
336 if.then:
337   store i8 20, i8* %ptr, align 8
338   br label %if.end
340 if.end:
341   %c.2 = call i1 @cond()
342   br i1 %c.2, label %if.then10, label %for.inc
344 if.then10:
345   store i8 0, i8* %ptr, align 8
346   br label %for.inc
348 for.inc:
349   %c.3 = call i1 @cond()
350   br i1 %c.3, label %for.body, label %for.end
352 for.end:
353   ret void
356 ; Cannot remove store in entry block because it is not overwritten on path
357 ; entry->bb2->bb4. Also make sure we deal with dead exit blocks without
358 ; crashing.
359 define void @accessible_after_return10_dead_block(i32* %P, i1 %c.1, i1 %c.2) {
360 ; CHECK-LABEL: @accessible_after_return10_dead_block(
361 ; CHECK-NEXT:  entry:
362 ; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
363 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
364 ; CHECK:       bb1:
365 ; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
366 ; CHECK:       bb2:
367 ; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
368 ; CHECK-NEXT:    ret void
369 ; CHECK:       bb3:
370 ; CHECK-NEXT:    store i32 2, i32* [[P]], align 4
371 ; CHECK-NEXT:    ret void
372 ; CHECK:       bb4:
373 ; CHECK-NEXT:    ret void
374 ; CHECK:       bb5:
375 ; CHECK-NEXT:    ret void
377 entry:
378   store i32 0, i32* %P
379   br i1 %c.1, label %bb1, label %bb2
381 bb1:
382   br i1 %c.2, label %bb3, label %bb4
384 bb2:
385   store i32 1, i32* %P
386   ret void
388 bb3:
389   store i32 2, i32* %P
390   ret void
392 bb4:
393   ret void
395 bb5:
396   ret void
399 @linenum = external local_unnamed_addr global i32, align 4
401 define void @accessible_after_return11_loop() {
402 ; CHECK-LABEL: @accessible_after_return11_loop(
403 ; CHECK-NEXT:  entry:
404 ; CHECK-NEXT:    br label [[FOR_BODY_I:%.*]]
405 ; CHECK:       for.body.i:
406 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
407 ; CHECK-NEXT:    br i1 [[C_1]], label [[FOR_BODY_I]], label [[INIT_PARSE_EXIT:%.*]]
408 ; CHECK:       init_parse.exit:
409 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull undef)
410 ; CHECK-NEXT:    store i32 0, i32* @linenum, align 4
411 ; CHECK-NEXT:    br label [[FOR_BODY_I20:%.*]]
412 ; CHECK:       for.body.i20:
413 ; CHECK-NEXT:    [[C_2:%.*]] = call i1 @cond()
414 ; CHECK-NEXT:    br i1 [[C_2]], label [[FOR_BODY_I20]], label [[EXIT:%.*]]
415 ; CHECK:       exit:
416 ; CHECK-NEXT:    ret void
418 entry:
419   br label %for.body.i
421 for.body.i:                                       ; preds = %for.body.i, %entry
422   %c.1 = call i1 @cond()
423   br i1 %c.1, label %for.body.i, label %init_parse.exit
425 init_parse.exit:                                  ; preds = %for.body.i
426   store i32 0, i32* @linenum, align 4
427   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull undef) #2
428   store i32 0, i32* @linenum, align 4
429   br label %for.body.i20
431 for.body.i20:                                     ; preds = %for.body.i20, %init_parse.exit
432   %c.2 = call i1 @cond()
433   br i1 %c.2, label %for.body.i20, label %exit
435 exit:
436   ret void
438 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
439 declare i1 @cond() readnone nounwind
441 ; Tests where the pointer/object is *NOT* accessible after the function returns.
443 ; The store in the entry block can be eliminated, because it is overwritten
444 ; on all paths to the exit.
445 define void @alloca_1(i1 %c1) {
446 ; CHECK-LABEL: @alloca_1(
447 ; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
448 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
449 ; CHECK:       bb1:
450 ; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
451 ; CHECK-NEXT:    br label [[BB5:%.*]]
452 ; CHECK:       bb2:
453 ; CHECK-NEXT:    store i32 3, i32* [[P]], align 4
454 ; CHECK-NEXT:    br label [[BB5]]
455 ; CHECK:       bb5:
456 ; CHECK-NEXT:    call void @use(i32* [[P]])
457 ; CHECK-NEXT:    ret void
459   %P = alloca i32
460   store i32 1, i32* %P
461   br i1 %c1, label %bb1, label %bb2
463 bb1:
464   store i32 0, i32* %P
465   br label %bb5
466 bb2:
467   store i32 3, i32* %P
468   br label %bb5
470 bb5:
471   call void @use(i32* %P)
472   ret void
475 ; The store in the entry block can be eliminated, because it is overwritten
476 ; on all paths to the exit.
477 define void @alloca_2(i1 %c.1, i1 %c.2) {
478 ; CHECK-LABEL: @alloca_2(
479 ; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
480 ; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
481 ; CHECK:       bb1:
482 ; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
483 ; CHECK-NEXT:    br label [[BB5:%.*]]
484 ; CHECK:       bb2:
485 ; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
486 ; CHECK:       bb3:
487 ; CHECK-NEXT:    store i32 3, i32* [[P]], align 4
488 ; CHECK-NEXT:    br label [[BB5]]
489 ; CHECK:       bb4:
490 ; CHECK-NEXT:    store i32 5, i32* [[P]], align 4
491 ; CHECK-NEXT:    br label [[BB5]]
492 ; CHECK:       bb5:
493 ; CHECK-NEXT:    call void @use(i32* [[P]])
494 ; CHECK-NEXT:    ret void
496   %P = alloca i32
497   store i32 1, i32* %P
498   br i1 %c.1, label %bb1, label %bb2
500 bb1:
501   store i32 0, i32* %P
502   br label %bb5
504 bb2:
505   br i1 %c.2, label %bb3, label %bb4
507 bb3:
508   store i32 3, i32* %P
509   br label %bb5
511 bb4:
512   store i32 5, i32* %P
513   br label %bb5
515 bb5:
516   call void @use(i32* %P)
517   ret void
520 ; The store in the entry block cannot be eliminated. There's a path from the
521 ; first store to the read in bb5, where the location is not overwritten.
522 define void @alloca_3(i1 %c1) {
523 ; CHECK-LABEL: @alloca_3(
524 ; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
525 ; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
526 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
527 ; CHECK:       bb1:
528 ; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
529 ; CHECK-NEXT:    br label [[BB5:%.*]]
530 ; CHECK:       bb2:
531 ; CHECK-NEXT:    br label [[BB5]]
532 ; CHECK:       bb5:
533 ; CHECK-NEXT:    call void @use(i32* [[P]])
534 ; CHECK-NEXT:    ret void
536   %P = alloca i32
537   store i32 1, i32* %P
538   br i1 %c1, label %bb1, label %bb2
540 bb1:
541   store i32 0, i32* %P
542   br label %bb5
543 bb2:
544   br label %bb5
546 bb5:
547   call void @use(i32* %P)
548   ret void
551 ; The store in the entry block can be eliminated, because it is overwritten
552 ; before the use in bb1 and not read on other paths to the function exit. The
553 ; object cannot be accessed by the caller.
554 define void @alloca_4(i1 %c1) {
555 ; CHECK-LABEL: @alloca_4(
556 ; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
557 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
558 ; CHECK:       bb1:
559 ; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
560 ; CHECK-NEXT:    call void @use(i32* [[P]])
561 ; CHECK-NEXT:    br label [[BB5:%.*]]
562 ; CHECK:       bb2:
563 ; CHECK-NEXT:    br label [[BB5]]
564 ; CHECK:       bb5:
565 ; CHECK-NEXT:    ret void
567   %P = alloca i32
568   store i32 1, i32* %P
569   br i1 %c1, label %bb1, label %bb2
571 bb1:
572   store i32 0, i32* %P
573   call void @use(i32* %P)
574   br label %bb5
576 bb2:
577   br label %bb5
579 bb5:
580   ret void
583 %struct.blam.4 = type { %struct.bar.5, [4 x i8] }
584 %struct.bar.5 = type <{ i64, i64*, i32, i64 }>
586 ; Make sure we do not eliminate the store in %bb.
587 define void @alloca_5(i1 %c) {
588 ; CHECK-LABEL: @alloca_5(
589 ; CHECK-NEXT:  bb:
590 ; CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_BLAM_4:%.*]], align 8
591 ; CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds [[STRUCT_BLAM_4]], %struct.blam.4* [[TMP]], i64 0, i32 0, i32 3
592 ; CHECK-NEXT:    [[TMP39:%.*]] = bitcast i64* [[TMP38]] to i64*
593 ; CHECK-NEXT:    store i64 0, i64* [[TMP39]], align 4
594 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB46:%.*]], label [[BB47:%.*]]
595 ; CHECK:       bb46:
596 ; CHECK-NEXT:    ret void
597 ; CHECK:       bb47:
598 ; CHECK-NEXT:    [[TMP48:%.*]] = getelementptr inbounds [[STRUCT_BLAM_4]], %struct.blam.4* [[TMP]], i64 0, i32 0, i32 2
599 ; CHECK-NEXT:    store i32 20, i32* [[TMP48]], align 8
600 ; CHECK-NEXT:    br label [[BB52:%.*]]
601 ; CHECK:       bb52:
602 ; CHECK-NEXT:    br i1 [[C]], label [[BB68:%.*]], label [[BB59:%.*]]
603 ; CHECK:       bb59:
604 ; CHECK-NEXT:    call void @use.2(%struct.blam.4* [[TMP]])
605 ; CHECK-NEXT:    ret void
606 ; CHECK:       bb68:
607 ; CHECK-NEXT:    ret void
610   %tmp = alloca %struct.blam.4, align 8
611   %tmp36 = getelementptr inbounds %struct.blam.4, %struct.blam.4* %tmp, i64 0, i32 0, i32 1
612   %tmp37 = bitcast i64** %tmp36 to i8*
613   %tmp38 = getelementptr inbounds %struct.blam.4, %struct.blam.4* %tmp, i64 0, i32 0, i32 3
614   %tmp39 = bitcast i64* %tmp38 to i64*
615   store i64 0, i64* %tmp39, align 4
616   br i1 %c, label %bb46, label %bb47
618 bb46:                                             ; preds = %bb12
619   call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(20) %tmp37, i8 0, i64 26, i1 false)
620   ret void
622 bb47:                                             ; preds = %bb12
623   %tmp48 = getelementptr inbounds %struct.blam.4, %struct.blam.4* %tmp, i64 0, i32 0, i32 2
624   store i32 20, i32* %tmp48, align 8
625   br label %bb52
627 bb52:                                             ; preds = %bb47
628   br i1 %c, label %bb68, label %bb59
630 bb59:                                             ; preds = %bb52
631   call void @use.2(%struct.blam.4* %tmp)
632   ret void
634 bb68:                                             ; preds = %bb52
635   ret void
638 declare void @use.2(%struct.blam.4*)
640 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg)