1 ; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s
3 declare i32 @__CxxFrameHandler3(...)
10 define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
13 to label %invoke.cont unwind label %left
16 to label %exit unwind label %right
22 to label %right.catch unwind label %right.end
26 catchendpad unwind to caller
30 to label %shared.cont unwind label %inner
36 cleanupret %i unwind label %right.end
40 ; %inner is a cleanup which appears both as a child of
41 ; %left and as a child of %right. Since statically we
42 ; need each funclet to have a single parent, we need to
43 ; clone the entire %inner funclet so we can have one
44 ; copy under each parent. The cleanupret in %inner
45 ; unwinds to the catchendpad for %right, so the copy
46 ; of %inner under %right should include it; the copy
47 ; of %inner under %left should instead have an
48 ; `unreachable` inserted there, but the copy under
49 ; %left still needs to be created because it's possible
50 ; the dynamic path enters %left, then enters %inner,
51 ; then calls @h, and that the call to @h doesn't return.
52 ; CHECK-LABEL: define void @test1(
54 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
56 ; CHECK: to label %right.catch unwind label %right.end
58 ; CHECK: %x = call i32 @g()
59 ; CHECK: store i32 %x, i32* %x.wineh.spillslot
60 ; CHECK: to label %shared.cont unwind label %[[INNER_RIGHT:.+]]
62 ; CHECK: catchendpad unwind to caller
65 ; CHECK: [[SHARED_CONT_LEFT]]:
67 ; CHECK: [[INNER_RIGHT]]:
68 ; CHECK: [[I_R:\%.+]] = cleanuppad []
69 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
70 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
71 ; CHECK: cleanupret [[I_R]] unwind label %right.end
72 ; CHECK: [[INNER_LEFT]]:
73 ; CHECK: [[I_L:\%.+]] = cleanuppad []
74 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
75 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
79 define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
82 to label %invoke.cont unwind label %left
85 to label %exit unwind label %right
91 to label %right.catch unwind label %right.end
95 catchendpad unwind to caller
99 to label %shared.cont unwind label %inner
104 to label %inner.catch unwind label %inner.end
109 catchendpad unwind label %right.end
113 ; In this case left and right are both parents of inner. This differs from
114 ; @test1 in that inner is a catchpad rather than a cleanuppad, which makes
115 ; inner.end a block that gets cloned so that left and right each contain a
116 ; copy (catchendpad blocks are considered to be part of the parent funclet
117 ; of the associated catchpad). The catchendpad in %inner.end unwinds to
118 ; %right.end (which belongs to the entry funclet).
119 ; CHECK-LABEL: define void @test2(
121 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
123 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
124 ; CHECK: right.catch:
125 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
126 ; CHECK: [[RIGHT_END]]:
127 ; CHECK: catchendpad unwind to caller
128 ; CHECK: [[SHARED_CONT_RIGHT]]:
130 ; CHECK: [[SHARED_CONT_LEFT]]:
132 ; CHECK: [[INNER_RIGHT]]:
134 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
135 ; CHECK: [[INNER_LEFT]]:
137 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
138 ; CHECK: [[INNER_CATCH_RIGHT]]:
139 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
140 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
142 ; CHECK: [[INNER_CATCH_LEFT]]:
143 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
144 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
146 ; CHECK: [[INNER_END_LEFT]]:
147 ; CHECK: catchendpad unwind to caller
148 ; CHECK: [[INNER_END_RIGHT]]:
149 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
151 define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
154 to label %exit unwind label %left
159 cleanupendpad %l unwind label %right
162 to label %right.catch unwind label %right.end
166 catchendpad unwind to caller
170 to label %shared.cont unwind label %inner
175 to label %inner.catch unwind label %inner.end
180 catchendpad unwind label %left.end
184 ; In this case, %left and %right are siblings with %entry as the parent of both,
185 ; while %left and %right are both parents of %inner. The catchendpad in
186 ; %inner.end unwinds to %left.end. When %inner is cloned a copy of %inner.end
187 ; will be made for both %left and %right, but because %left.end is a cleanup pad
188 ; and %right is a catch pad the unwind edge from the copy of %inner.end for
189 ; %right must be removed.
190 ; CHECK-LABEL: define void @test3(
192 ; CHECK: %l = cleanuppad []
193 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
194 ; CHECK: [[LEFT_END:left.end.*]]:
195 ; CHECK: cleanupendpad %l unwind label %right
197 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
198 ; CHECK: right.catch:
199 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
200 ; CHECK: [[RIGHT_END]]:
201 ; CHECK: catchendpad unwind to caller
202 ; CHECK: [[SHARED_CONT_RIGHT]]:
204 ; CHECK: [[SHARED_CONT_LEFT]]:
206 ; CHECK: [[INNER_RIGHT]]:
208 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
209 ; CHECK: [[INNER_LEFT]]:
211 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
212 ; CHECK: [[INNER_CATCH_RIGHT]]:
213 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
214 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
216 ; CHECK: [[INNER_CATCH_LEFT]]:
217 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
218 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
220 ; CHECK: [[INNER_END_LEFT]]:
221 ; CHECK: catchendpad unwind label %[[LEFT_END]]
222 ; CHECK: [[INNER_END_RIGHT]]:
223 ; CHECK: catchendpad unwind to caller
226 define void @test4() personality i32 (...)* @__CxxFrameHandler3 {
229 to label %exit unwind label %left
232 to label %left.catch unwind label %left.end
236 catchendpad unwind label %right
239 to label %right.catch unwind label %right.end
243 catchendpad unwind to caller
247 to label %shared.cont unwind label %inner
252 to label %inner.catch unwind label %inner.end
257 catchendpad unwind label %left.end
261 ; This is a variation of @test3 in which both %left and %right are catch pads.
262 ; In this case, %left and %right are siblings with %entry as the parent of both,
263 ; while %left and %right are both parents of %inner. The catchendpad in
264 ; %inner.end unwinds to %left.end. When %inner is cloned a copy of %inner.end
265 ; will be made for both %left and %right, but because the catchpad in %right
266 ; does not unwind to %left.end the unwind edge from the copy of %inner.end for
267 ; %right must be removed.
268 ; CHECK-LABEL: define void @test4(
271 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
273 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
274 ; CHECK: [[LEFT_END]]:
275 ; CHECK: catchendpad unwind label %right
277 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
278 ; CHECK: right.catch:
279 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
280 ; CHECK: [[RIGHT_END]]:
281 ; CHECK: catchendpad unwind to caller
282 ; CHECK: [[SHARED_CONT_RIGHT]]:
284 ; CHECK: [[SHARED_CONT_LEFT]]:
286 ; CHECK: [[INNER_RIGHT]]:
288 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
289 ; CHECK: [[INNER_LEFT]]:
291 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
292 ; CHECK: [[INNER_CATCH_RIGHT]]:
293 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
294 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
296 ; CHECK: [[INNER_CATCH_LEFT]]:
297 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
298 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
300 ; CHECK: [[INNER_END_LEFT]]:
301 ; CHECK: catchendpad unwind label %[[LEFT_END]]
302 ; CHECK: [[INNER_END_RIGHT]]:
303 ; CHECK: catchendpad unwind to caller
306 define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
309 to label %exit unwind label %left
312 to label %left.catch unwind label %left.end
316 catchendpad unwind label %right
323 to label %shared.cont unwind label %inner
328 to label %inner.catch unwind label %inner.end
333 catchendpad unwind label %left.end
337 ; Like @test3, %left and %right are siblings with %entry as the parent of both,
338 ; while %left and %right are both parents of %inner. This case makes %left a
339 ; catch and %right a cleanup so that %inner unwinds to %left.end, which is a
340 ; block in %entry. The %inner funclet is cloned for %left and %right, but the
341 ; copy of %inner.end for %right must have its unwind edge removed because the
342 ; catchendpad at %left.end is not compatible with %right.
343 ; CHECK-LABEL: define void @test5(
346 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
348 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
349 ; CHECK: [[LEFT_END]]:
350 ; CHECK: catchendpad unwind label %right
352 ; CHECK: %r = cleanuppad []
353 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
354 ; CHECK: [[SHARED_CONT_RIGHT]]:
356 ; CHECK: [[SHARED_CONT_LEFT]]:
358 ; CHECK: [[INNER_RIGHT]]:
360 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
361 ; CHECK: [[INNER_LEFT]]:
363 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
364 ; CHECK: [[INNER_CATCH_RIGHT]]:
365 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
366 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
368 ; CHECK: [[INNER_CATCH_LEFT]]:
369 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
370 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
372 ; CHECK: [[INNER_END_LEFT]]:
373 ; CHECK: catchendpad unwind label %[[LEFT_END]]
374 ; CHECK: [[INNER_END_RIGHT]]:
375 ; CHECK: catchendpad unwind to caller
377 define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
380 to label %exit unwind label %left
383 to label %left.catch unwind label %left.end
387 catchendpad unwind label %middle
390 to label %middle.catch unwind label %middle.end
392 catchret %m to label %exit
394 catchendpad unwind label %right
401 to label %shared.cont unwind label %inner
406 to label %inner.catch unwind label %inner.end
411 catchendpad unwind label %left.end
415 ; This is like @test5 but it inserts another sibling between %left and %right.
416 ; In this case %left, %middle and %right are all siblings, while %left and
417 ; %right are both parents of %inner. This checks the proper handling of the
418 ; catchendpad in %inner.end (which will be cloned so that %left and %right both
419 ; have copies) unwinding to a catchendpad that unwinds to a sibling.
420 ; CHECK-LABEL: define void @test6(
423 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
425 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
426 ; CHECK: [[LEFT_END]]:
427 ; CHECK: catchendpad unwind label %middle
430 ; CHECK: to label %middle.catch unwind label %middle.end
431 ; CHECK: middle.catch:
432 ; CHECK: catchret %m to label %exit
434 ; CHECK: catchendpad unwind label %right
436 ; CHECK: %r = cleanuppad []
437 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
438 ; CHECK: [[SHARED_CONT_RIGHT]]:
440 ; CHECK: [[SHARED_CONT_LEFT]]:
442 ; CHECK: [[INNER_RIGHT]]:
444 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
445 ; CHECK: [[INNER_LEFT]]:
447 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
448 ; CHECK: [[INNER_CATCH_RIGHT]]:
449 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
450 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
452 ; CHECK: [[INNER_CATCH_LEFT]]:
453 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
454 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
456 ; CHECK: [[INNER_END_LEFT]]:
457 ; CHECK: catchendpad unwind label %[[LEFT_END]]
458 ; CHECK: [[INNER_END_RIGHT]]:
459 ; CHECK: catchendpad unwind to caller
462 define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
465 to label %exit unwind label %left
468 to label %left.catch unwind label %left.end
472 catchendpad unwind label %right
479 to label %shared.cont unwind label %inner
484 to label %inner.catch unwind label %inner.end
489 catchendpad unwind label %inner.sibling
493 cleanupret %is unwind label %left.end
497 ; This is like @test5 but instead of unwinding to %left.end, the catchendpad
498 ; in %inner.end unwinds to a sibling cleanup pad. Both %inner (along with its
499 ; associated blocks) and %inner.sibling must be cloned for %left and %right.
500 ; The clones of %inner will be identical, but the copy of %inner.sibling for
501 ; %right must end with an unreachable instruction, because it cannot unwind to
503 ; CHECK-LABEL: define void @test7(
506 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
508 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
509 ; CHECK: [[LEFT_END]]:
510 ; CHECK: catchendpad unwind label %[[RIGHT:.+]]
512 ; CHECK: [[R:\%.+]] = cleanuppad []
513 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
514 ; CHECK: [[SHARED_CONT_RIGHT]]:
516 ; CHECK: [[SHARED_CONT_LEFT]]:
518 ; CHECK: [[INNER_RIGHT]]:
520 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
521 ; CHECK: [[INNER_LEFT]]:
523 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
524 ; CHECK: [[INNER_CATCH_RIGHT]]:
525 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
526 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
528 ; CHECK: [[INNER_CATCH_LEFT]]:
529 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
530 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
532 ; CHECK: [[INNER_END_LEFT]]:
533 ; CHECK: catchendpad unwind label %[[INNER_SIBLING_LEFT:.+]]
534 ; CHECK: [[INNER_END_RIGHT]]:
535 ; CHECK: catchendpad unwind label %[[INNER_SIBLING_RIGHT:.+]]
536 ; CHECK: [[INNER_SIBLING_RIGHT]]
537 ; CHECK: [[IS_R:\%.+]] = cleanuppad []
538 ; CHECK: call void @h(i32 0)
540 ; CHECK: [[INNER_SIBLING_LEFT]]
541 ; CHECK: [[IS_L:\%.+]] = cleanuppad []
542 ; CHECK: call void @h(i32 0)
543 ; CHECK: cleanupret [[IS_L]] unwind label %[[LEFT_END]]
546 define void @test8() personality i32 (...)* @__CxxFrameHandler3 {
549 to label %invoke.cont unwind label %left
552 to label %unreachable unwind label %right
555 invoke void @f() to label %unreachable unwind label %inner
558 to label %right.catch unwind label %right.end
560 invoke void @f() to label %unreachable unwind label %inner
562 catchendpad unwind to caller
567 cleanupret %i unwind label %right.end
571 ; Another case of a two-parent child (like @test1), this time
572 ; with the join at the entry itself instead of following a
574 ; CHECK-LABEL: define void @test8(
575 ; CHECK: invoke.cont:
576 ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
578 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
580 ; CHECK: to label %right.catch unwind label %right.end
581 ; CHECK: right.catch:
582 ; CHECK: to label %unreachable unwind label %[[INNER_RIGHT:.+]]
584 ; CHECK: catchendpad unwind to caller
585 ; CHECK: [[INNER_RIGHT]]:
586 ; CHECK: [[I_R:\%.+]] = cleanuppad []
587 ; CHECK: [[X_R:\%.+]] = call i32 @g()
588 ; CHECK: call void @h(i32 [[X_R]])
589 ; CHECK: cleanupret [[I_R]] unwind label %right.end
590 ; CHECK: [[INNER_LEFT]]:
591 ; CHECK: [[I_L:\%.+]] = cleanuppad []
592 ; CHECK: [[X_L:\%.+]] = call i32 @g()
593 ; CHECK: call void @h(i32 [[X_L]])
595 ; CHECK: unreachable:
597 ; CHECK: [[UNREACHABLE_LEFT]]:
599 ; CHECK: [[UNREACHABLE_ENTRY]]:
603 define void @test9() personality i32 (...)* @__CxxFrameHandler3 {
606 to label %invoke.cont unwind label %left
609 to label %unreachable unwind label %right
615 to label %right.catch unwind label %right.end
619 catchendpad unwind to caller
622 to label %unreachable unwind label %inner
626 to label %unreachable unwind label %inner.child
635 ; %inner is a two-parent child which itself has a child; need
636 ; to make two copies of both the %inner and %inner.child.
637 ; CHECK-LABEL: define void @test9(
638 ; CHECK: invoke.cont:
639 ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
641 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
643 ; CHECK: to label %right.catch unwind label %right.end
644 ; CHECK: right.catch:
645 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
647 ; CHECK: catchendpad unwind to caller
648 ; CHECK: [[INNER_RIGHT]]:
649 ; CHECK: to label %[[UNREACHABLE_INNER_RIGHT:.+]] unwind label %[[INNER_CHILD_RIGHT:.+]]
650 ; CHECK: [[INNER_LEFT]]:
651 ; CHECK: to label %[[UNREACHABLE_INNER_LEFT:.+]] unwind label %[[INNER_CHILD_LEFT:.+]]
652 ; CHECK: [[INNER_CHILD_RIGHT]]:
653 ; CHECK: [[TMP:\%.+]] = cleanuppad []
654 ; CHECK: [[X:\%.+]] = call i32 @g()
655 ; CHECK: call void @h(i32 [[X]])
657 ; CHECK: [[INNER_CHILD_LEFT]]:
658 ; CHECK: [[TMP:\%.+]] = cleanuppad []
659 ; CHECK: [[X:\%.+]] = call i32 @g()
660 ; CHECK: call void @h(i32 [[X]])
662 ; CHECK: [[UNREACHABLE_INNER_RIGHT]]:
664 ; CHECK: [[UNREACHABLE_INNER_LEFT]]:
666 ; CHECK: [[UNREACHABLE_RIGHT]]:
668 ; CHECK: [[UNREACHABLE_LEFT]]:
670 ; CHECK: [[UNREACHABLE_ENTRY]]:
674 define void @test10() personality i32 (...)* @__CxxFrameHandler3 {
677 to label %invoke.cont unwind label %left
680 to label %unreachable unwind label %right
685 to label %unreachable unwind label %right
690 to label %unreachable unwind label %left
694 ; This is an irreducible loop with two funclets that enter each other;
695 ; need to make two copies of each funclet (one a child of root, the
696 ; other a child of the opposite funclet), but also make sure not to
697 ; clone self-descendants (if we tried to do that we'd need to make an
698 ; infinite number of them). Presumably if optimizations ever generated
699 ; such a thing it would mean that one of the two cleanups was originally
700 ; the parent of the other, but that we'd somehow lost track in the CFG
701 ; of which was which along the way; generating each possibility lets
702 ; whichever case was correct execute correctly.
703 ; CHECK-LABEL: define void @test10(
705 ; CHECK: to label %invoke.cont unwind label %[[LEFT:.+]]
706 ; CHECK: invoke.cont:
707 ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
708 ; CHECK: [[LEFT_FROM_RIGHT:.+]]:
709 ; CHECK: call void @h(i32 1)
710 ; CHECK: call void @f()
713 ; CHECK: call void @h(i32 1)
714 ; CHECK: invoke void @f()
715 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT_FROM_LEFT:.+]]
717 ; CHECK: call void @h(i32 2)
718 ; CHECK: invoke void @f()
719 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT_FROM_RIGHT]]
720 ; CHECK: [[RIGHT_FROM_LEFT]]:
721 ; CHECK: call void @h(i32 2)
722 ; CHECK: call void @f()
724 ; CHECK: [[UNREACHABLE_RIGHT]]:
726 ; CHECK: [[UNREACHABLE_LEFT]]:
728 ; CHECK: [[UNREACHABLE_ENTRY]]:
732 define void @test11() personality i32 (...)* @__CxxFrameHandler3 {
735 to label %exit unwind label %left
738 to label %left.catch unwind label %left.sibling
743 to label %left.sibling.catch unwind label %left.end
745 catchret %ls to label %exit
747 catchendpad unwind label %right
750 to label %right.catch unwind label %right.end
754 catchendpad unwind to caller
758 to label %shared.cont unwind label %inner
763 to label %inner.catch unwind label %inner.end
768 catchendpad unwind label %left.end
772 ; This is a variation of @test4 in which the shared child funclet unwinds to a
773 ; catchend pad that is the unwind destination of %left.sibling rather than %left
774 ; but is still a valid destination for %inner as reach from %left.
775 ; When %inner is cloned a copy of %inner.end will be made for both %left and
776 ; %right, but because the catchpad in %right does not unwind to %left.end the
777 ; unwind edge from the copy of %inner.end for %right must be removed.
778 ; CHECK-LABEL: define void @test11(
781 ; CHECK: to label %left.catch unwind label %left.sibling
783 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
784 ; CHECK: left.sibling:
786 ; CHECK: to label %left.sibling.catch unwind label %[[LEFT_END:.+]]
787 ; CHECK: [[LEFT_END]]:
788 ; CHECK: catchendpad unwind label %right
790 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
791 ; CHECK: right.catch:
792 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
793 ; CHECK: [[RIGHT_END]]:
794 ; CHECK: catchendpad unwind to caller
795 ; CHECK: [[SHARED_CONT_RIGHT]]:
797 ; CHECK: [[SHARED_CONT_LEFT]]:
799 ; CHECK: [[INNER_RIGHT]]:
801 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
802 ; CHECK: [[INNER_LEFT]]:
804 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
805 ; CHECK: [[INNER_CATCH_RIGHT]]:
806 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
807 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
809 ; CHECK: [[INNER_CATCH_LEFT]]:
810 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
811 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
813 ; CHECK: [[INNER_END_LEFT]]:
814 ; CHECK: catchendpad unwind label %[[LEFT_END]]
815 ; CHECK: [[INNER_END_RIGHT]]:
816 ; CHECK: catchendpad unwind to caller
819 define void @test12() personality i32 (...)* @__CxxFrameHandler3 {
822 to label %exit unwind label %left
825 to label %left.catch unwind label %right
830 to label %right.catch unwind label %right.end
834 catchendpad unwind to caller
838 to label %shared.cont unwind label %inner
843 to label %inner.catch unwind label %inner.end
848 catchendpad unwind label %right.end
852 ; In this case %left and %right are both parents of %inner, so %inner must be
853 ; cloned but the catchendpad unwind target in %inner.end is valid for both
854 ; parents, so the unwind edge should not be removed in either case.
855 ; CHECK-LABEL: define void @test12(
858 ; CHECK: to label %left.catch unwind label %right
860 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
862 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
863 ; CHECK: right.catch:
864 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
865 ; CHECK: [[RIGHT_END]]:
866 ; CHECK: catchendpad unwind to caller
867 ; CHECK: [[SHARED_CONT_RIGHT]]:
869 ; CHECK: [[SHARED_CONT_LEFT]]:
871 ; CHECK: [[INNER_RIGHT]]:
873 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
874 ; CHECK: [[INNER_LEFT]]:
876 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
877 ; CHECK: [[INNER_CATCH_RIGHT]]:
878 ; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
879 ; CHECK: call void @h(i32 [[X_RELOAD_R]])
881 ; CHECK: [[INNER_CATCH_LEFT]]:
882 ; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
883 ; CHECK: call void @h(i32 [[X_RELOAD_L]])
885 ; CHECK: [[INNER_END_LEFT]]:
886 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
887 ; CHECK: [[INNER_END_RIGHT]]:
888 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
890 define void @test13() personality i32 (...)* @__CxxFrameHandler3 {
893 to label %invoke.cont unwind label %left
896 to label %exit unwind label %right
899 to label %left.cont unwind label %left.end
902 to label %left.ret unwind label %inner
904 catchret %l to label %invoke.cont
906 catchendpad unwind to caller
909 to label %right.catch unwind label %right.end
912 to label %right.ret unwind label %inner
914 catchret %r to label %exit
916 catchendpad unwind to caller
922 to label %inner.catch unwind label %inner.end
925 catchret %i to label %shared
927 catchendpad unwind label %left.end
931 ; This case tests the scenario where a funclet with multiple parents uses a
932 ; catchret to return to a block that may exist in either parent funclets.
933 ; Both %left and %right are parents of %inner. During common block cloning
934 ; a clone of %shared will be made so that both %left and %right have a copy,
935 ; but the copy of %shared for one of the parent funclets will be unreachable
936 ; until the %inner funclet is cloned. When the %inner.catch block is cloned
937 ; during the %inner funclet cloning, the catchret instruction should be updated
938 ; so that the catchret in the copy %inner.catch for %left returns to the copy of
939 ; %shared in %left and the catchret in the copy of %inner.catch for %right
940 ; returns to the copy of %shared for %right.
941 ; CHECK-LABEL: define void @test13(
943 ; CHECK: %l = catchpad []
944 ; CHECK: to label %left.cont unwind label %left.end
946 ; CHECK: invoke void @f()
947 ; CHECK: to label %left.ret unwind label %[[INNER_LEFT:.+]]
949 ; CHECK: catchret %l to label %invoke.cont
951 ; CHECK: catchendpad unwind to caller
953 ; CHECK: %r = catchpad []
954 ; CHECK: to label %right.catch unwind label %right.end
955 ; CHECK: right.catch:
956 ; CHECK: invoke void @f()
957 ; CHECK: to label %right.ret unwind label %[[INNER_RIGHT:.+]]
959 ; CHECK: catchret %r to label %exit
961 ; CHECK: catchendpad unwind to caller
962 ; CHECK: [[SHARED_RIGHT:.+]]:
963 ; CHECK: call void @h(i32 0)
965 ; CHECK: [[SHARED_LEFT:.+]]:
966 ; CHECK: call void @h(i32 0)
968 ; CHECK: [[INNER_RIGHT]]:
969 ; CHECK: %[[I_RIGHT:.+]] = catchpad []
970 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
971 ; CHECK: [[INNER_LEFT]]:
972 ; CHECK: %[[I_LEFT:.+]] = catchpad []
973 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
974 ; CHECK: [[INNER_CATCH_RIGHT]]:
975 ; CHECK: call void @h(i32 1)
976 ; CHECK: catchret %[[I_RIGHT]] to label %[[SHARED_RIGHT]]
977 ; CHECK: [[INNER_CATCH_LEFT]]:
978 ; CHECK: call void @h(i32 1)
979 ; CHECK: catchret %[[I_LEFT]] to label %[[SHARED_LEFT]]
980 ; CHECK: [[INNER_END_LEFT]]:
981 ; CHECK: catchendpad unwind label %[[LEFT_END]]
982 ; CHECK: [[INNER_END_RIGHT]]:
983 ; CHECK: catchendpad unwind to caller
986 define void @test14() personality i32 (...)* @__CxxFrameHandler3 {
989 to label %exit unwind label %left
992 to label %shared unwind label %left.end
995 to label %left.ret unwind label %right
997 catchret %l to label %exit
999 catchendpad unwind to caller
1002 to label %right.catch unwind label %right.end
1006 catchendpad unwind label %left.end
1009 to label %shared.cont unwind label %inner
1014 to label %inner.catch unwind label %inner.end
1017 catchret %i to label %left.cont
1019 catchendpad unwind label %left.end
1023 ; This case tests another scenario where a funclet with multiple parents uses a
1024 ; catchret to return to a block in one of the parent funclets. Here %right and
1025 ; %left are both parents of %inner and %left is a parent of %right. The
1026 ; catchret in %inner.catch will cause %left.cont and %left.ret to be cloned for
1027 ; both %left and %right, but the catchret in %left.ret is invalid for %right
1028 ; but the catchret instruction in the copy of %left.ret for %right will be
1029 ; removed as an implausible terminator.
1030 ; CHECK-LABEL: define void @test14(
1032 ; CHECK: %l = catchpad []
1033 ; CHECK: to label %[[SHARED_LEFT:.+]] unwind label %[[LEFT_END:.+]]
1034 ; CHECK: [[LEFT_CONT:left.cont.*]]:
1035 ; CHECK: invoke void @f()
1036 ; CHECK: to label %[[LEFT_RET:.+]] unwind label %[[RIGHT:.+]]
1037 ; CHECK: [[LEFT_RET]]:
1038 ; CHECK: catchret %l to label %exit
1039 ; CHECK: [[LEFT_END]]:
1040 ; CHECK: catchendpad unwind to caller
1042 ; CHECK: catchpad []
1043 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1044 ; CHECK: [[RIGHT_CATCH]]:
1045 ; CHECK: invoke void @f()
1046 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1047 ; CHECK: [[RIGHT_END]]:
1048 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1049 ; CHECK: [[SHARED_LEFT]]:
1050 ; CHECK: invoke void @f()
1051 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1052 ; CHECK: [[SHARED_CONT_RIGHT]]:
1053 ; CHECK: unreachable
1054 ; CHECK: [[SHARED_CONT_LEFT]]:
1055 ; CHECK: unreachable
1056 ; CHECK: [[INNER_LEFT]]:
1057 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1058 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1059 ; CHECK: [[INNER_RIGHT]]:
1060 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1061 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1062 ; CHECK: [[INNER_CATCH_LEFT]]:
1063 ; CHECK: call void @h(i32 0)
1064 ; CHECK: catchret [[I_LEFT]] to label %[[LEFT_CONT]]
1065 ; CHECK: [[INNER_CATCH_RIGHT]]:
1066 ; CHECK: call void @h(i32 0)
1067 ; CHECK: unreachable
1068 ; CHECK: [[INNER_END_LEFT]]:
1069 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1070 ; CHECK: [[INNER_END_RIGHT]]:
1071 ; CHECK: catchendpad unwind to caller
1073 define void @test15() personality i32 (...)* @__CxxFrameHandler3 {
1076 to label %exit unwind label %left
1079 to label %left.catch unwind label %left.end
1082 to label %shared unwind label %right
1084 catchret %l to label %exit
1086 catchendpad unwind to caller
1089 to label %right.catch unwind label %right.end
1093 catchendpad unwind label %left.end
1096 to label %shared.cont unwind label %inner
1101 to label %inner.catch unwind label %inner.end
1104 catchret %i to label %left.ret
1106 catchendpad unwind label %left.end
1110 ; This case is a variation of test14 but instead of returning to an invoke the
1111 ; catchret in %inner.catch returns to a catchret instruction.
1112 ; CHECK-LABEL: define void @test15(
1114 ; CHECK: %l = catchpad []
1115 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
1116 ; CHECK: left.catch:
1117 ; CHECK: invoke void @f()
1118 ; CHECK: to label %[[SHARED_LEFT:.+]] unwind label %[[RIGHT:.+]]
1119 ; CHECK: [[LEFT_RET_RIGHT:.+]]:
1120 ; CHECK: unreachable
1121 ; CHECK: [[LEFT_RET_LEFT:.+]]:
1122 ; CHECK: catchret %l to label %exit
1123 ; CHECK: [[LEFT_END]]:
1124 ; CHECK: catchendpad unwind to caller
1126 ; CHECK: catchpad []
1127 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1128 ; CHECK: [[RIGHT_CATCH]]:
1129 ; CHECK: invoke void @f()
1130 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1131 ; CHECK: [[RIGHT_END]]:
1132 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1133 ; CHECK: [[SHARED_LEFT]]:
1134 ; CHECK: invoke void @f()
1135 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1136 ; CHECK: [[SHARED_CONT_RIGHT]]:
1137 ; CHECK: unreachable
1138 ; CHECK: [[SHARED_CONT_LEFT]]:
1139 ; CHECK: unreachable
1140 ; CHECK: [[INNER_LEFT]]:
1141 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1142 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1143 ; CHECK: [[INNER_RIGHT]]:
1144 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1145 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1146 ; CHECK: [[INNER_CATCH_LEFT]]:
1147 ; CHECK: call void @h(i32 0)
1148 ; CHECK: catchret [[I_LEFT]] to label %[[LEFT_RET_LEFT]]
1149 ; CHECK: [[INNER_CATCH_RIGHT]]:
1150 ; CHECK: call void @h(i32 0)
1151 ; CHECK: catchret [[I_RIGHT]] to label %[[LEFT_RET_RIGHT]]
1152 ; CHECK: [[INNER_END_LEFT]]:
1153 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1154 ; CHECK: [[INNER_END_RIGHT]]:
1155 ; CHECK: catchendpad unwind to caller
1158 define void @test16() personality i32 (...)* @__CxxFrameHandler3 {
1161 to label %exit unwind label %left
1166 cleanupret %l unwind label %right
1168 cleanupendpad %l unwind label %right
1171 to label %right.catch unwind label %right.end
1175 catchendpad unwind to caller
1178 to label %shared.cont unwind label %inner
1183 to label %inner.catch unwind label %inner.end
1186 catchret %i to label %left.cont
1188 catchendpad unwind label %left.end
1192 ; This case is another variation of test14 but here the catchret in %inner.catch
1193 ; returns to a cleanupret instruction.
1194 ; CHECK-LABEL: define void @test16(
1196 ; CHECK: %l = cleanuppad []
1197 ; CHECK: invoke void @f()
1198 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1199 ; CHECK: [[LEFT_CONT_RIGHT:.+]]:
1200 ; CHECK: unreachable
1201 ; CHECK: [[LEFT_CONT_LEFT:.+]]:
1202 ; CHECK: cleanupret %l unwind label %[[RIGHT:.+]]
1203 ; CHECK: [[LEFT_END_LEFT:.+]]:
1204 ; CHECK: cleanupendpad %l unwind label %[[RIGHT]]
1206 ; CHECK: catchpad []
1207 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1208 ; CHECK: [[RIGHT_CATCH]]:
1209 ; CHECK: invoke void @f()
1210 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1211 ; CHECK: [[RIGHT_END]]:
1212 ; CHECK: catchendpad unwind to caller
1213 ; CHECK: [[SHARED_CONT_RIGHT]]:
1214 ; CHECK: unreachable
1215 ; CHECK: [[SHARED_CONT_LEFT]]:
1216 ; CHECK: unreachable
1217 ; CHECK: [[INNER_RIGHT]]:
1218 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1219 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1220 ; CHECK: [[INNER_LEFT]]:
1221 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1222 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1223 ; CHECK: [[INNER_CATCH_RIGHT]]:
1224 ; CHECK: call void @h(i32 0)
1225 ; CHECK: catchret [[I_RIGHT]] to label %[[LEFT_CONT_RIGHT]]
1226 ; CHECK: [[INNER_CATCH_LEFT]]:
1227 ; CHECK: call void @h(i32 0)
1228 ; CHECK: catchret [[I_LEFT]] to label %[[LEFT_CONT_LEFT]]
1229 ; CHECK: [[INNER_END_LEFT]]:
1230 ; CHECK: catchendpad unwind label %[[LEFT_END_LEFT]]
1231 ; CHECK: [[INNER_END_RIGHT]]:
1232 ; CHECK: catchendpad unwind to caller
1235 define void @test17() personality i32 (...)* @__CxxFrameHandler3 {
1238 to label %invoke.cont unwind label %left
1241 to label %exit unwind label %right
1247 to label %right.catch unwind label %right.end
1251 catchendpad unwind to caller
1254 to label %unreachable unwind label %inner
1259 to label %inner.catch unwind label %inner.sibling
1265 to label %inner.sibling.catch unwind label %inner.end
1266 inner.sibling.catch:
1268 to label %unreachable unwind label %inner.end
1270 catchendpad unwind label %right.end
1274 ; This case tests the scenario where two catchpads with the same catchendpad
1275 ; have multiple parents. Both %left and %right are parents of %inner and
1276 ; %inner.sibling so both of the inner funclets must be cloned. Because
1277 ; the catchendpad in %inner.end unwinds to the catchendpad for %right, the
1278 ; unwind edge should be removed for the copy of %inner.end that is reached
1279 ; from %left. In addition, the %inner.siblin.catch block contains an invoke
1280 ; that unwinds to the shared inner catchendpad. The unwind destination for
1281 ; this invoke should be updated to unwind to the correct cloned %inner.end
1282 ; for each path to the funclet.
1283 ; CHECK-LABEL: define void @test17(
1285 ; CHECK: %l = cleanuppad []
1286 ; CHECK: invoke void @f()
1287 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1289 ; CHECK: catchpad []
1290 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1291 ; CHECK: [[RIGHT_CATCH]]:
1292 ; CHECK: invoke void @f()
1293 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1294 ; CHECK: [[RIGHT_END]]:
1295 ; CHECK: catchendpad unwind to caller
1296 ; CHECK: [[SHARED_CONT_RIGHT]]:
1297 ; CHECK: unreachable
1298 ; CHECK: [[SHARED_CONT_LEFT]]:
1299 ; CHECK: unreachable
1300 ; CHECK: [[INNER_RIGHT]]:
1301 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1302 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]]
1303 ; CHECK: [[INNER_LEFT]]:
1304 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1305 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]]
1306 ; CHECK: [[INNER_CATCH_RIGHT]]:
1307 ; CHECK: call void @h(i32 0)
1308 ; CHECK: unreachable
1309 ; CHECK: [[INNER_CATCH_LEFT]]:
1310 ; CHECK: call void @h(i32 0)
1311 ; CHECK: unreachable
1312 ; CHECK: [[INNER_SIBLING_RIGHT]]:
1313 ; CHECK: [[IS_RIGHT:\%.+]] = catchpad []
1314 ; CHECK: to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1315 ; CHECK: [[INNER_SIBLING_LEFT]]:
1316 ; CHECK: [[IS_LEFT:\%.+]] = catchpad []
1317 ; CHECK: to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1318 ; CHECK: [[INNER_SIBLING_CATCH_RIGHT]]:
1319 ; CHECK: invoke void @f()
1320 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
1321 ; CHECK: [[INNER_SIBLING_CATCH_LEFT]]:
1322 ; CHECK: invoke void @f()
1323 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT]]
1324 ; CHECK: [[INNER_END_LEFT]]:
1325 ; CHECK: catchendpad unwind to caller
1326 ; CHECK: [[INNER_END_RIGHT]]:
1327 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
1330 define void @test18() personality i32 (...)* @__CxxFrameHandler3 {
1333 to label %invoke.cont unwind label %left
1336 to label %exit unwind label %right
1342 to label %right.catch unwind label %right.end
1346 catchendpad unwind to caller
1349 to label %unreachable unwind label %inner
1354 to label %inner.catch unwind label %inner.sibling
1357 to label %unreachable unwind label %inner.end
1360 to label %inner.sibling.catch unwind label %inner.end
1361 inner.sibling.catch:
1365 catchendpad unwind label %right.end
1369 ; This is like test17 except that the inner invoke is moved from the
1370 ; %inner.sibling funclet to %inner so that it is unwinding to a
1371 ; catchendpad block that has not yet been cloned. The unwind destination
1372 ; of the invoke should still be updated to reach the correct copy of
1373 ; %inner.end for the path by which it is reached.
1374 ; CHECK-LABEL: define void @test18(
1376 ; CHECK: %l = cleanuppad []
1377 ; CHECK: invoke void @f()
1378 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1380 ; CHECK: catchpad []
1381 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1382 ; CHECK: [[RIGHT_CATCH]]:
1383 ; CHECK: invoke void @f()
1384 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1385 ; CHECK: [[RIGHT_END]]:
1386 ; CHECK: catchendpad unwind to caller
1387 ; CHECK: [[SHARED_CONT_RIGHT]]:
1388 ; CHECK: unreachable
1389 ; CHECK: [[SHARED_CONT_LEFT]]:
1390 ; CHECK: unreachable
1391 ; CHECK: [[INNER_RIGHT]]:
1392 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1393 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]]
1394 ; CHECK: [[INNER_LEFT]]:
1395 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1396 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]]
1397 ; CHECK: [[INNER_CATCH_RIGHT]]:
1398 ; CHECK: invoke void @f()
1399 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1400 ; CHECK: [[INNER_CATCH_LEFT]]:
1401 ; CHECK: invoke void @f()
1402 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1403 ; CHECK: [[INNER_SIBLING_RIGHT]]:
1404 ; CHECK: [[IS_RIGHT:\%.+]] = catchpad []
1405 ; CHECK: to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
1406 ; CHECK: [[INNER_SIBLING_LEFT]]:
1407 ; CHECK: [[IS_LEFT:\%.+]] = catchpad []
1408 ; CHECK: to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT]]
1409 ; CHECK: [[INNER_SIBLING_CATCH_RIGHT]]:
1410 ; CHECK: call void @h(i32 0)
1411 ; CHECK: unreachable
1412 ; CHECK: [[INNER_SIBLING_CATCH_LEFT]]:
1413 ; CHECK: call void @h(i32 0)
1414 ; CHECK: unreachable
1415 ; CHECK: [[INNER_END_LEFT]]:
1416 ; CHECK: catchendpad unwind to caller
1417 ; CHECK: [[INNER_END_RIGHT]]:
1418 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
1421 define void @test19() personality i32 (...)* @__CxxFrameHandler3 {
1424 to label %invoke.cont unwind label %left
1427 to label %exit unwind label %right
1433 to label %right.catch unwind label %right.end
1437 catchendpad unwind to caller
1440 to label %unreachable unwind label %inner
1446 to label %unreachable unwind label %inner.end
1448 cleanupendpad %i unwind label %right.end
1452 ; This case tests the scenario where an invoke in a funclet with multiple
1453 ; parents unwinds to a cleanup end pad for the funclet. The unwind destination
1454 ; for the invoke should map to the correct copy of the cleanup end pad block.
1455 ; CHECK-LABEL: define void @test19(
1457 ; CHECK: %l = cleanuppad []
1458 ; CHECK: invoke void @f()
1459 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1461 ; CHECK: catchpad []
1462 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1463 ; CHECK: [[RIGHT_CATCH]]:
1464 ; CHECK: invoke void @f()
1465 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1466 ; CHECK: [[RIGHT_END]]:
1467 ; CHECK: catchendpad unwind to caller
1468 ; CHECK: [[SHARED_CONT_RIGHT]]:
1469 ; CHECK: unreachable
1470 ; CHECK: [[SHARED_CONT_LEFT]]:
1471 ; CHECK: unreachable
1472 ; CHECK: [[INNER_RIGHT]]:
1473 ; CHECK: [[I_RIGHT:\%.+]] = cleanuppad []
1474 ; CHECK: invoke void @f()
1475 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1476 ; CHECK: [[INNER_LEFT]]:
1477 ; CHECK: [[I_LEFT:\%.+]] = cleanuppad []
1478 ; CHECK: invoke void @f()
1479 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1480 ; CHECK: [[INNER_END_RIGHT]]:
1481 ; CHECK: cleanupendpad [[I_RIGHT]] unwind label %[[RIGHT_END]]
1482 ; CHECK: [[INNER_END_LEFT]]:
1483 ; CHECK: cleanupendpad [[I_LEFT]] unwind to caller
1485 define void @test20() personality i32 (...)* @__CxxFrameHandler3 {
1488 to label %invoke.cont unwind label %left
1491 to label %exit unwind label %right
1497 to label %right.catch unwind label %right.end
1501 catchendpad unwind to caller
1504 to label %unreachable unwind label %inner
1510 to label %unreachable unwind label %inner.cleanup
1518 ; This tests the case where a funclet with multiple parents contains an invoke
1519 ; instruction that unwinds to a child funclet. Here %left and %right are both
1520 ; parents of %inner. Initially %inner is the only parent of %inner.cleanup but
1521 ; after %inner is cloned, %inner.cleanup has multiple parents and so it must
1523 ; CHECK-LABEL: define void @test20(
1525 ; CHECK: %l = cleanuppad []
1526 ; CHECK: invoke void @f()
1527 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1529 ; CHECK: catchpad []
1530 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1531 ; CHECK: [[RIGHT_CATCH]]:
1532 ; CHECK: invoke void @f()
1533 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1534 ; CHECK: [[RIGHT_END]]:
1535 ; CHECK: catchendpad unwind to caller
1536 ; CHECK: [[SHARED_CONT_RIGHT]]:
1537 ; CHECK: unreachable
1538 ; CHECK: [[SHARED_CONT_LEFT]]:
1539 ; CHECK: unreachable
1540 ; CHECK: [[INNER_RIGHT]]:
1541 ; CHECK: [[I_RIGHT:\%.+]] = cleanuppad []
1542 ; CHECK: invoke void @f()
1543 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_CLEANUP_RIGHT:.+]]
1544 ; CHECK: [[INNER_LEFT]]:
1545 ; CHECK: [[I_LEFT:\%.+]] = cleanuppad []
1546 ; CHECK: invoke void @f()
1547 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_CLEANUP_LEFT:.+]]
1548 ; CHECK: [[INNER_CLEANUP_RIGHT]]:
1549 ; CHECK: cleanuppad []
1550 ; CHECK: call void @f()
1551 ; CHECK: unreachable
1552 ; CHECK: [[INNER_CLEANUP_LEFT]]:
1553 ; CHECK: cleanuppad []
1554 ; CHECK: call void @f()
1555 ; CHECK: unreachable