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(
55 ; CHECK: %x.for.left = call i32 @g()
56 ; CHECK: invoke void @f()
57 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
59 ; CHECK: to label %right.catch unwind label %right.end
61 ; CHECK: %x = call i32 @g()
62 ; CHECK: to label %shared.cont unwind label %[[INNER_RIGHT:.+]]
64 ; CHECK: catchendpad unwind to caller
67 ; CHECK: [[SHARED_CONT_LEFT]]:
69 ; CHECK: [[INNER_RIGHT]]:
70 ; CHECK: [[I_R:\%.+]] = cleanuppad []
71 ; CHECK: call void @h(i32 %x)
72 ; CHECK: cleanupret [[I_R]] unwind label %right.end
73 ; CHECK: [[INNER_LEFT]]:
74 ; CHECK: [[I_L:\%.+]] = cleanuppad []
75 ; CHECK: call void @h(i32 %x.for.left)
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(
122 ; CHECK: %x.for.left = call i32 @g()
123 ; CHECK: invoke void @f()
124 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
126 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
127 ; CHECK: right.catch:
128 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
129 ; CHECK: [[RIGHT_END]]:
130 ; CHECK: catchendpad unwind to caller
131 ; CHECK: [[SHARED_CONT_RIGHT]]:
133 ; CHECK: [[SHARED_CONT_LEFT]]:
135 ; CHECK: [[INNER_RIGHT]]:
137 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
138 ; CHECK: [[INNER_LEFT]]:
140 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
141 ; CHECK: [[INNER_CATCH_RIGHT]]:
142 ; CHECK: call void @h(i32 %x)
144 ; CHECK: [[INNER_CATCH_LEFT]]:
145 ; CHECK: call void @h(i32 %x.for.left)
147 ; CHECK: [[INNER_END_LEFT]]:
148 ; CHECK: catchendpad unwind to caller
149 ; CHECK: [[INNER_END_RIGHT]]:
150 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
152 define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
155 to label %exit unwind label %left
160 cleanupendpad %l unwind label %right
163 to label %right.catch unwind label %right.end
167 catchendpad unwind to caller
171 to label %shared.cont unwind label %inner
176 to label %inner.catch unwind label %inner.end
181 catchendpad unwind label %left.end
185 ; In this case, %left and %right are siblings with %entry as the parent of both,
186 ; while %left and %right are both parents of %inner. The catchendpad in
187 ; %inner.end unwinds to %left.end. When %inner is cloned a copy of %inner.end
188 ; will be made for both %left and %right, but because %left.end is a cleanup pad
189 ; and %right is a catch pad the unwind edge from the copy of %inner.end for
190 ; %right must be removed.
191 ; CHECK-LABEL: define void @test3(
193 ; CHECK: %l = cleanuppad []
194 ; CHECK: %x.for.left = call i32 @g()
195 ; CHECK: invoke void @f()
196 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
197 ; CHECK: [[LEFT_END:left.end.*]]:
198 ; CHECK: cleanupendpad %l unwind label %right
200 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
201 ; CHECK: right.catch:
202 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
203 ; CHECK: [[RIGHT_END]]:
204 ; CHECK: catchendpad unwind to caller
205 ; CHECK: [[SHARED_CONT_RIGHT]]:
207 ; CHECK: [[SHARED_CONT_LEFT]]:
209 ; CHECK: [[INNER_RIGHT]]:
211 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
212 ; CHECK: [[INNER_LEFT]]:
214 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
215 ; CHECK: [[INNER_CATCH_RIGHT]]:
216 ; CHECK: call void @h(i32 %x)
218 ; CHECK: [[INNER_CATCH_LEFT]]:
219 ; CHECK: call void @h(i32 %x.for.left)
221 ; CHECK: [[INNER_END_LEFT]]:
222 ; CHECK: catchendpad unwind label %[[LEFT_END]]
223 ; CHECK: [[INNER_END_RIGHT]]:
224 ; CHECK: catchendpad unwind to caller
227 define void @test4() personality i32 (...)* @__CxxFrameHandler3 {
230 to label %exit unwind label %left
233 to label %left.catch unwind label %left.end
237 catchendpad unwind label %right
240 to label %right.catch unwind label %right.end
244 catchendpad unwind to caller
248 to label %shared.cont unwind label %inner
253 to label %inner.catch unwind label %inner.end
258 catchendpad unwind label %left.end
262 ; This is a variation of @test3 in which both %left and %right are catch pads.
263 ; In this case, %left and %right are siblings with %entry as the parent of both,
264 ; while %left and %right are both parents of %inner. The catchendpad in
265 ; %inner.end unwinds to %left.end. When %inner is cloned a copy of %inner.end
266 ; will be made for both %left and %right, but because the catchpad in %right
267 ; does not unwind to %left.end the unwind edge from the copy of %inner.end for
268 ; %right must be removed.
269 ; CHECK-LABEL: define void @test4(
272 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
274 ; CHECK: %x.for.left = call i32 @g()
275 ; CHECK: invoke void @f()
276 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
277 ; CHECK: [[LEFT_END]]:
278 ; CHECK: catchendpad unwind label %right
280 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
281 ; CHECK: right.catch:
282 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
283 ; CHECK: [[RIGHT_END]]:
284 ; CHECK: catchendpad unwind to caller
285 ; CHECK: [[SHARED_CONT_RIGHT]]:
287 ; CHECK: [[SHARED_CONT_LEFT]]:
289 ; CHECK: [[INNER_RIGHT]]:
291 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
292 ; CHECK: [[INNER_LEFT]]:
294 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
295 ; CHECK: [[INNER_CATCH_RIGHT]]:
296 ; CHECK: call void @h(i32 %x)
298 ; CHECK: [[INNER_CATCH_LEFT]]:
299 ; CHECK: call void @h(i32 %x.for.left)
301 ; CHECK: [[INNER_END_RIGHT]]:
302 ; CHECK: catchendpad unwind to caller
303 ; CHECK: [[INNER_END_LEFT]]:
304 ; CHECK: catchendpad unwind label %[[LEFT_END]]
307 define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
310 to label %exit unwind label %left
313 to label %left.catch unwind label %left.end
317 catchendpad unwind label %right
324 to label %shared.cont unwind label %inner
329 to label %inner.catch unwind label %inner.end
334 catchendpad unwind label %left.end
338 ; Like @test3, %left and %right are siblings with %entry as the parent of both,
339 ; while %left and %right are both parents of %inner. This case makes %left a
340 ; catch and %right a cleanup so that %inner unwinds to %left.end, which is a
341 ; block in %entry. The %inner funclet is cloned for %left and %right, but the
342 ; copy of %inner.end for %right must have its unwind edge removed because the
343 ; catchendpad at %left.end is not compatible with %right.
344 ; CHECK-LABEL: define void @test5(
347 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
349 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
350 ; CHECK: [[LEFT_END]]:
351 ; CHECK: catchendpad unwind label %right
353 ; CHECK: %r = cleanuppad []
354 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
355 ; CHECK: [[SHARED_CONT_RIGHT]]:
357 ; CHECK: [[SHARED_CONT_LEFT]]:
359 ; CHECK: [[INNER_RIGHT]]:
361 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
362 ; CHECK: [[INNER_LEFT]]:
364 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
365 ; CHECK: [[INNER_CATCH_RIGHT]]:
366 ; CHECK: call void @h(i32 %x)
368 ; CHECK: [[INNER_CATCH_LEFT]]:
369 ; CHECK: call void @h(i32 %x.for.left)
371 ; CHECK: [[INNER_END_RIGHT]]:
372 ; CHECK: catchendpad unwind to caller
373 ; CHECK: [[INNER_END_LEFT]]:
374 ; CHECK: catchendpad unwind label %[[LEFT_END]]
376 define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
379 to label %exit unwind label %left
382 to label %left.catch unwind label %left.end
386 catchendpad unwind label %middle
389 to label %middle.catch unwind label %middle.end
391 catchret %m to label %exit
393 catchendpad unwind label %right
400 to label %shared.cont unwind label %inner
405 to label %inner.catch unwind label %inner.end
410 catchendpad unwind label %left.end
414 ; This is like @test5 but it inserts another sibling between %left and %right.
415 ; In this case %left, %middle and %right are all siblings, while %left and
416 ; %right are both parents of %inner. This checks the proper handling of the
417 ; catchendpad in %inner.end (which will be cloned so that %left and %right both
418 ; have copies) unwinding to a catchendpad that unwinds to a sibling.
419 ; CHECK-LABEL: define void @test6(
422 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
424 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
425 ; CHECK: [[LEFT_END]]:
426 ; CHECK: catchendpad unwind label %middle
429 ; CHECK: to label %middle.catch unwind label %middle.end
430 ; CHECK: middle.catch:
431 ; CHECK: catchret %m to label %exit
433 ; CHECK: catchendpad unwind label %right
435 ; CHECK: %r = cleanuppad []
436 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
437 ; CHECK: [[SHARED_CONT_RIGHT]]:
439 ; CHECK: [[SHARED_CONT_LEFT]]:
441 ; CHECK: [[INNER_RIGHT]]:
443 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
444 ; CHECK: [[INNER_LEFT]]:
446 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
447 ; CHECK: [[INNER_CATCH_RIGHT]]:
448 ; CHECK: call void @h(i32 %x)
450 ; CHECK: [[INNER_CATCH_LEFT]]:
451 ; CHECK: call void @h(i32 %x.for.left)
453 ; CHECK: [[INNER_END_RIGHT]]:
454 ; CHECK: catchendpad unwind to caller
455 ; CHECK: [[INNER_END_LEFT]]:
456 ; CHECK: catchendpad unwind label %[[LEFT_END]]
459 define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
462 to label %exit unwind label %left
465 to label %left.catch unwind label %left.end
469 catchendpad unwind label %right
476 to label %shared.cont unwind label %inner
481 to label %inner.catch unwind label %inner.end
486 catchendpad unwind label %inner.sibling
490 cleanupret %is unwind label %left.end
494 ; This is like @test5 but instead of unwinding to %left.end, the catchendpad
495 ; in %inner.end unwinds to a sibling cleanup pad. Both %inner (along with its
496 ; associated blocks) and %inner.sibling must be cloned for %left and %right.
497 ; The clones of %inner will be identical, but the copy of %inner.sibling for
498 ; %right must end with an unreachable instruction, because it cannot unwind to
500 ; CHECK-LABEL: define void @test7(
503 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
505 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
506 ; CHECK: [[LEFT_END]]:
507 ; CHECK: catchendpad unwind label %[[RIGHT:.+]]
509 ; CHECK: [[R:\%.+]] = cleanuppad []
510 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
511 ; CHECK: [[SHARED_CONT_RIGHT]]:
513 ; CHECK: [[SHARED_CONT_LEFT]]:
515 ; CHECK: [[INNER_RIGHT]]:
517 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
518 ; CHECK: [[INNER_LEFT]]:
520 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
521 ; CHECK: [[INNER_CATCH_RIGHT]]:
522 ; CHECK: call void @h(i32 %x)
524 ; CHECK: [[INNER_CATCH_LEFT]]:
525 ; CHECK: call void @h(i32 %x.for.left)
527 ; CHECK: [[INNER_END_RIGHT]]:
528 ; CHECK: catchendpad unwind label %[[INNER_SIBLING_RIGHT:.+]]
529 ; CHECK: [[INNER_END_LEFT]]:
530 ; CHECK: catchendpad unwind label %[[INNER_SIBLING_LEFT:.+]]
531 ; CHECK: [[INNER_SIBLING_RIGHT]]
532 ; CHECK: [[IS_R:\%.+]] = cleanuppad []
533 ; CHECK: call void @h(i32 0)
535 ; CHECK: [[INNER_SIBLING_LEFT]]
536 ; CHECK: [[IS_L:\%.+]] = cleanuppad []
537 ; CHECK: call void @h(i32 0)
538 ; CHECK: cleanupret [[IS_L]] unwind label %[[LEFT_END]]
541 define void @test8() personality i32 (...)* @__CxxFrameHandler3 {
544 to label %invoke.cont unwind label %left
547 to label %unreachable unwind label %right
550 invoke void @f() to label %unreachable unwind label %inner
553 to label %right.catch unwind label %right.end
555 invoke void @f() to label %unreachable unwind label %inner
557 catchendpad unwind to caller
562 cleanupret %i unwind label %right.end
566 ; Another case of a two-parent child (like @test1), this time
567 ; with the join at the entry itself instead of following a
569 ; CHECK-LABEL: define void @test8(
570 ; CHECK: invoke.cont:
571 ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
573 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
575 ; CHECK: to label %right.catch unwind label %right.end
576 ; CHECK: right.catch:
577 ; CHECK: to label %unreachable unwind label %[[INNER_RIGHT:.+]]
579 ; CHECK: catchendpad unwind to caller
580 ; CHECK: [[INNER_RIGHT]]:
581 ; CHECK: [[I_R:\%.+]] = cleanuppad []
582 ; CHECK: [[X_R:\%.+]] = call i32 @g()
583 ; CHECK: call void @h(i32 [[X_R]])
584 ; CHECK: cleanupret [[I_R]] unwind label %right.end
585 ; CHECK: [[INNER_LEFT]]:
586 ; CHECK: [[I_L:\%.+]] = cleanuppad []
587 ; CHECK: [[X_L:\%.+]] = call i32 @g()
588 ; CHECK: call void @h(i32 [[X_L]])
590 ; CHECK: unreachable:
592 ; CHECK: [[UNREACHABLE_LEFT]]:
594 ; CHECK: [[UNREACHABLE_ENTRY]]:
598 define void @test9() personality i32 (...)* @__CxxFrameHandler3 {
601 to label %invoke.cont unwind label %left
604 to label %unreachable unwind label %right
610 to label %right.catch unwind label %right.end
614 catchendpad unwind to caller
617 to label %unreachable unwind label %inner
621 to label %unreachable unwind label %inner.child
630 ; %inner is a two-parent child which itself has a child; need
631 ; to make two copies of both the %inner and %inner.child.
632 ; CHECK-LABEL: define void @test9(
633 ; CHECK: invoke.cont:
634 ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
636 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
638 ; CHECK: to label %right.catch unwind label %right.end
639 ; CHECK: right.catch:
640 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
642 ; CHECK: catchendpad unwind to caller
643 ; CHECK: [[INNER_RIGHT]]:
644 ; CHECK: to label %[[UNREACHABLE_INNER_RIGHT:.+]] unwind label %[[INNER_CHILD_RIGHT:.+]]
645 ; CHECK: [[INNER_LEFT]]:
646 ; CHECK: to label %[[UNREACHABLE_INNER_LEFT:.+]] unwind label %[[INNER_CHILD_LEFT:.+]]
647 ; CHECK: [[INNER_CHILD_RIGHT]]:
648 ; CHECK: [[TMP:\%.+]] = cleanuppad []
649 ; CHECK: [[X:\%.+]] = call i32 @g()
650 ; CHECK: call void @h(i32 [[X]])
652 ; CHECK: [[INNER_CHILD_LEFT]]:
653 ; CHECK: [[TMP:\%.+]] = cleanuppad []
654 ; CHECK: [[X:\%.+]] = call i32 @g()
655 ; CHECK: call void @h(i32 [[X]])
657 ; CHECK: [[UNREACHABLE_INNER_RIGHT]]:
659 ; CHECK: [[UNREACHABLE_INNER_LEFT]]:
661 ; CHECK: [[UNREACHABLE_RIGHT]]:
663 ; CHECK: [[UNREACHABLE_LEFT]]:
665 ; CHECK: [[UNREACHABLE_ENTRY]]:
669 define void @test10() personality i32 (...)* @__CxxFrameHandler3 {
672 to label %invoke.cont unwind label %left
675 to label %unreachable unwind label %right
680 to label %unreachable unwind label %right
685 to label %unreachable unwind label %left
689 ; This is an irreducible loop with two funclets that enter each other;
690 ; need to make two copies of each funclet (one a child of root, the
691 ; other a child of the opposite funclet), but also make sure not to
692 ; clone self-descendants (if we tried to do that we'd need to make an
693 ; infinite number of them). Presumably if optimizations ever generated
694 ; such a thing it would mean that one of the two cleanups was originally
695 ; the parent of the other, but that we'd somehow lost track in the CFG
696 ; of which was which along the way; generating each possibility lets
697 ; whichever case was correct execute correctly.
698 ; CHECK-LABEL: define void @test10(
700 ; CHECK: to label %invoke.cont unwind label %[[LEFT:.+]]
701 ; CHECK: invoke.cont:
702 ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
703 ; CHECK: [[LEFT_FROM_RIGHT:.+]]:
704 ; CHECK: call void @h(i32 1)
705 ; CHECK: call void @f()
708 ; CHECK: call void @h(i32 1)
709 ; CHECK: invoke void @f()
710 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT_FROM_LEFT:.+]]
712 ; CHECK: call void @h(i32 2)
713 ; CHECK: invoke void @f()
714 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT_FROM_RIGHT]]
715 ; CHECK: [[RIGHT_FROM_LEFT]]:
716 ; CHECK: call void @h(i32 2)
717 ; CHECK: call void @f()
719 ; CHECK: [[UNREACHABLE_RIGHT]]:
721 ; CHECK: [[UNREACHABLE_LEFT]]:
723 ; CHECK: [[UNREACHABLE_ENTRY]]:
727 define void @test11() personality i32 (...)* @__CxxFrameHandler3 {
730 to label %exit unwind label %left
733 to label %left.catch unwind label %left.sibling
738 to label %left.sibling.catch unwind label %left.end
740 catchret %ls to label %exit
742 catchendpad unwind label %right
745 to label %right.catch unwind label %right.end
749 catchendpad unwind to caller
753 to label %shared.cont unwind label %inner
758 to label %inner.catch unwind label %inner.end
763 catchendpad unwind label %left.end
767 ; This is a variation of @test4 in which the shared child funclet unwinds to a
768 ; catchend pad that is the unwind destination of %left.sibling rather than %left
769 ; but is still a valid destination for %inner as reach from %left.
770 ; When %inner is cloned a copy of %inner.end will be made for both %left and
771 ; %right, but because the catchpad in %right does not unwind to %left.end the
772 ; unwind edge from the copy of %inner.end for %right must be removed.
773 ; CHECK-LABEL: define void @test11(
776 ; CHECK: to label %left.catch unwind label %left.sibling
778 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
779 ; CHECK: left.sibling:
781 ; CHECK: to label %left.sibling.catch unwind label %[[LEFT_END:.+]]
782 ; CHECK: [[LEFT_END]]:
783 ; CHECK: catchendpad unwind label %right
785 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
786 ; CHECK: right.catch:
787 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
788 ; CHECK: [[RIGHT_END]]:
789 ; CHECK: catchendpad unwind to caller
790 ; CHECK: [[SHARED_CONT_RIGHT]]:
792 ; CHECK: [[SHARED_CONT_LEFT]]:
794 ; CHECK: [[INNER_RIGHT]]:
796 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
797 ; CHECK: [[INNER_LEFT]]:
799 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
800 ; CHECK: [[INNER_CATCH_RIGHT]]:
801 ; CHECK: call void @h(i32 %x)
803 ; CHECK: [[INNER_CATCH_LEFT]]:
804 ; CHECK: call void @h(i32 %x.for.left)
806 ; CHECK: [[INNER_END_RIGHT]]:
807 ; CHECK: catchendpad unwind to caller
808 ; CHECK: [[INNER_END_LEFT]]:
809 ; CHECK: catchendpad unwind label %[[LEFT_END]]
812 define void @test12() personality i32 (...)* @__CxxFrameHandler3 {
815 to label %exit unwind label %left
818 to label %left.catch unwind label %right
823 to label %right.catch unwind label %right.end
827 catchendpad unwind to caller
831 to label %shared.cont unwind label %inner
836 to label %inner.catch unwind label %inner.end
841 catchendpad unwind label %right.end
845 ; In this case %left and %right are both parents of %inner, so %inner must be
846 ; cloned but the catchendpad unwind target in %inner.end is valid for both
847 ; parents, so the unwind edge should not be removed in either case.
848 ; CHECK-LABEL: define void @test12(
851 ; CHECK: to label %left.catch unwind label %right
853 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
855 ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]]
856 ; CHECK: right.catch:
857 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
858 ; CHECK: [[RIGHT_END]]:
859 ; CHECK: catchendpad unwind to caller
860 ; CHECK: [[SHARED_CONT_RIGHT]]:
862 ; CHECK: [[SHARED_CONT_LEFT]]:
864 ; CHECK: [[INNER_RIGHT]]:
866 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
867 ; CHECK: [[INNER_LEFT]]:
869 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
870 ; CHECK: [[INNER_CATCH_RIGHT]]:
871 ; CHECK: call void @h(i32 %x)
873 ; CHECK: [[INNER_CATCH_LEFT]]:
874 ; CHECK: call void @h(i32 %x.for.left)
876 ; CHECK: [[INNER_END_RIGHT]]:
877 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
878 ; CHECK: [[INNER_END_LEFT]]:
879 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
881 define void @test13() personality i32 (...)* @__CxxFrameHandler3 {
884 to label %invoke.cont unwind label %left
887 to label %exit unwind label %right
890 to label %left.cont unwind label %left.end
893 to label %left.ret unwind label %inner
895 catchret %l to label %invoke.cont
897 catchendpad unwind to caller
900 to label %right.catch unwind label %right.end
903 to label %right.ret unwind label %inner
905 catchret %r to label %exit
907 catchendpad unwind to caller
913 to label %inner.catch unwind label %inner.end
916 catchret %i to label %shared
918 catchendpad unwind label %left.end
922 ; This case tests the scenario where a funclet with multiple parents uses a
923 ; catchret to return to a block that may exist in either parent funclets.
924 ; Both %left and %right are parents of %inner. During common block cloning
925 ; a clone of %shared will be made so that both %left and %right have a copy,
926 ; but the copy of %shared for one of the parent funclets will be unreachable
927 ; until the %inner funclet is cloned. When the %inner.catch block is cloned
928 ; during the %inner funclet cloning, the catchret instruction should be updated
929 ; so that the catchret in the copy %inner.catch for %left returns to the copy of
930 ; %shared in %left and the catchret in the copy of %inner.catch for %right
931 ; returns to the copy of %shared for %right.
932 ; CHECK-LABEL: define void @test13(
934 ; CHECK: %l = catchpad []
935 ; CHECK: to label %left.cont unwind label %left.end
937 ; CHECK: invoke void @f()
938 ; CHECK: to label %left.ret unwind label %[[INNER_LEFT:.+]]
940 ; CHECK: catchret %l to label %invoke.cont
942 ; CHECK: catchendpad unwind to caller
944 ; CHECK: %r = catchpad []
945 ; CHECK: to label %right.catch unwind label %right.end
946 ; CHECK: right.catch:
947 ; CHECK: invoke void @f()
948 ; CHECK: to label %right.ret unwind label %[[INNER_RIGHT:.+]]
950 ; CHECK: catchret %r to label %exit
952 ; CHECK: catchendpad unwind to caller
953 ; CHECK: [[SHARED_RIGHT:.+]]:
954 ; CHECK: call void @h(i32 0)
956 ; CHECK: [[SHARED_LEFT:.+]]:
957 ; CHECK: call void @h(i32 0)
959 ; CHECK: [[INNER_RIGHT]]:
960 ; CHECK: %[[I_RIGHT:.+]] = catchpad []
961 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
962 ; CHECK: [[INNER_LEFT]]:
963 ; CHECK: %[[I_LEFT:.+]] = catchpad []
964 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
965 ; CHECK: [[INNER_CATCH_RIGHT]]:
966 ; CHECK: call void @h(i32 1)
967 ; CHECK: catchret %[[I_RIGHT]] to label %[[SHARED_RIGHT]]
968 ; CHECK: [[INNER_CATCH_LEFT]]:
969 ; CHECK: call void @h(i32 1)
970 ; CHECK: catchret %[[I_LEFT]] to label %[[SHARED_LEFT]]
971 ; CHECK: [[INNER_END_LEFT]]:
972 ; CHECK: catchendpad unwind label %[[LEFT_END]]
973 ; CHECK: [[INNER_END_RIGHT]]:
974 ; CHECK: catchendpad unwind to caller
977 define void @test14() personality i32 (...)* @__CxxFrameHandler3 {
980 to label %exit unwind label %left
983 to label %shared unwind label %left.end
986 to label %left.ret unwind label %right
988 catchret %l to label %exit
990 catchendpad unwind to caller
993 to label %right.catch unwind label %right.end
997 catchendpad unwind label %left.end
1000 to label %shared.cont unwind label %inner
1005 to label %inner.catch unwind label %inner.end
1008 catchret %i to label %left.cont
1010 catchendpad unwind label %left.end
1014 ; This case tests another scenario where a funclet with multiple parents uses a
1015 ; catchret to return to a block in one of the parent funclets. Here %right and
1016 ; %left are both parents of %inner and %left is a parent of %right. The
1017 ; catchret in %inner.catch will cause %left.cont and %left.ret to be cloned for
1018 ; both %left and %right, but the catchret in %left.ret is invalid for %right
1019 ; but the catchret instruction in the copy of %left.ret for %right will be
1020 ; removed as an implausible terminator.
1021 ; CHECK-LABEL: define void @test14(
1023 ; CHECK: %l = catchpad []
1024 ; CHECK: to label %[[SHARED_LEFT:.+]] unwind label %[[LEFT_END:.+]]
1025 ; CHECK: [[LEFT_CONT:left.cont.*]]:
1026 ; CHECK: invoke void @f()
1027 ; CHECK: to label %[[LEFT_RET:.+]] unwind label %[[RIGHT:.+]]
1028 ; CHECK: [[LEFT_RET]]:
1029 ; CHECK: catchret %l to label %exit
1030 ; CHECK: [[LEFT_END]]:
1031 ; CHECK: catchendpad unwind to caller
1033 ; CHECK: catchpad []
1034 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1035 ; CHECK: [[RIGHT_CATCH]]:
1036 ; CHECK: invoke void @f()
1037 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1038 ; CHECK: [[RIGHT_END]]:
1039 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1040 ; CHECK: [[SHARED_LEFT]]:
1041 ; CHECK: invoke void @f()
1042 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1043 ; CHECK: [[SHARED_CONT_RIGHT]]:
1044 ; CHECK: unreachable
1045 ; CHECK: [[SHARED_CONT_LEFT]]:
1046 ; CHECK: unreachable
1047 ; CHECK: [[INNER_LEFT]]:
1048 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1049 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1050 ; CHECK: [[INNER_RIGHT]]:
1051 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1052 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1053 ; CHECK: [[INNER_CATCH_LEFT]]:
1054 ; CHECK: call void @h(i32 0)
1055 ; CHECK: catchret [[I_LEFT]] to label %[[LEFT_CONT]]
1056 ; CHECK: [[INNER_CATCH_RIGHT]]:
1057 ; CHECK: call void @h(i32 0)
1058 ; CHECK: unreachable
1059 ; CHECK: [[INNER_END_LEFT]]:
1060 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1061 ; CHECK: [[INNER_END_RIGHT]]:
1062 ; CHECK: catchendpad unwind to caller
1064 define void @test15() personality i32 (...)* @__CxxFrameHandler3 {
1067 to label %exit unwind label %left
1070 to label %left.catch unwind label %left.end
1073 to label %shared unwind label %right
1075 catchret %l to label %exit
1077 catchendpad unwind to caller
1080 to label %right.catch unwind label %right.end
1084 catchendpad unwind label %left.end
1087 to label %shared.cont unwind label %inner
1092 to label %inner.catch unwind label %inner.end
1095 catchret %i to label %left.ret
1097 catchendpad unwind label %left.end
1101 ; This case is a variation of test14 but instead of returning to an invoke the
1102 ; catchret in %inner.catch returns to a catchret instruction.
1103 ; CHECK-LABEL: define void @test15(
1105 ; CHECK: %l = catchpad []
1106 ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]]
1107 ; CHECK: left.catch:
1108 ; CHECK: invoke void @f()
1109 ; CHECK: to label %[[SHARED_LEFT:.+]] unwind label %[[RIGHT:.+]]
1110 ; CHECK: [[LEFT_RET_RIGHT:.+]]:
1111 ; CHECK: unreachable
1112 ; CHECK: [[LEFT_RET_LEFT:.+]]:
1113 ; CHECK: catchret %l to label %exit
1114 ; CHECK: [[LEFT_END]]:
1115 ; CHECK: catchendpad unwind to caller
1117 ; CHECK: catchpad []
1118 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1119 ; CHECK: [[RIGHT_CATCH]]:
1120 ; CHECK: invoke void @f()
1121 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1122 ; CHECK: [[RIGHT_END]]:
1123 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1124 ; CHECK: [[SHARED_LEFT]]:
1125 ; CHECK: invoke void @f()
1126 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1127 ; CHECK: [[SHARED_CONT_RIGHT]]:
1128 ; CHECK: unreachable
1129 ; CHECK: [[SHARED_CONT_LEFT]]:
1130 ; CHECK: unreachable
1131 ; CHECK: [[INNER_LEFT]]:
1132 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1133 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1134 ; CHECK: [[INNER_RIGHT]]:
1135 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1136 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1137 ; CHECK: [[INNER_CATCH_LEFT]]:
1138 ; CHECK: call void @h(i32 0)
1139 ; CHECK: catchret [[I_LEFT]] to label %[[LEFT_RET_LEFT]]
1140 ; CHECK: [[INNER_CATCH_RIGHT]]:
1141 ; CHECK: call void @h(i32 0)
1142 ; CHECK: catchret [[I_RIGHT]] to label %[[LEFT_RET_RIGHT]]
1143 ; CHECK: [[INNER_END_RIGHT]]:
1144 ; CHECK: catchendpad unwind to caller
1145 ; CHECK: [[INNER_END_LEFT]]:
1146 ; CHECK: catchendpad unwind label %[[LEFT_END]]
1149 define void @test16() personality i32 (...)* @__CxxFrameHandler3 {
1152 to label %exit unwind label %left
1157 cleanupret %l unwind label %right
1159 cleanupendpad %l unwind label %right
1162 to label %right.catch unwind label %right.end
1166 catchendpad unwind to caller
1169 to label %shared.cont unwind label %inner
1174 to label %inner.catch unwind label %inner.end
1177 catchret %i to label %left.cont
1179 catchendpad unwind label %left.end
1183 ; This case is another variation of test14 but here the catchret in %inner.catch
1184 ; returns to a cleanupret instruction.
1185 ; CHECK-LABEL: define void @test16(
1187 ; CHECK: %l = cleanuppad []
1188 ; CHECK: invoke void @f()
1189 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1190 ; CHECK: [[LEFT_CONT_RIGHT:.+]]:
1191 ; CHECK: unreachable
1192 ; CHECK: [[LEFT_CONT_LEFT:.+]]:
1193 ; CHECK: cleanupret %l unwind label %[[RIGHT:.+]]
1194 ; CHECK: [[LEFT_END_LEFT:.+]]:
1195 ; CHECK: cleanupendpad %l unwind label %[[RIGHT]]
1197 ; CHECK: catchpad []
1198 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1199 ; CHECK: [[RIGHT_CATCH]]:
1200 ; CHECK: invoke void @f()
1201 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1202 ; CHECK: [[RIGHT_END]]:
1203 ; CHECK: catchendpad unwind to caller
1204 ; CHECK: [[SHARED_CONT_RIGHT]]:
1205 ; CHECK: unreachable
1206 ; CHECK: [[SHARED_CONT_LEFT]]:
1207 ; CHECK: unreachable
1208 ; CHECK: [[INNER_RIGHT]]:
1209 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1210 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1211 ; CHECK: [[INNER_LEFT]]:
1212 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1213 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1214 ; CHECK: [[INNER_CATCH_RIGHT]]:
1215 ; CHECK: call void @h(i32 0)
1216 ; CHECK: catchret [[I_RIGHT]] to label %[[LEFT_CONT_RIGHT]]
1217 ; CHECK: [[INNER_CATCH_LEFT]]:
1218 ; CHECK: call void @h(i32 0)
1219 ; CHECK: catchret [[I_LEFT]] to label %[[LEFT_CONT_LEFT]]
1220 ; CHECK: [[INNER_END_LEFT]]:
1221 ; CHECK: catchendpad unwind label %[[LEFT_END_LEFT]]
1222 ; CHECK: [[INNER_END_RIGHT]]:
1223 ; CHECK: catchendpad unwind to caller
1226 define void @test17() personality i32 (...)* @__CxxFrameHandler3 {
1229 to label %invoke.cont unwind label %left
1232 to label %exit unwind label %right
1238 to label %right.catch unwind label %right.end
1242 catchendpad unwind to caller
1245 to label %unreachable unwind label %inner
1250 to label %inner.catch unwind label %inner.sibling
1256 to label %inner.sibling.catch unwind label %inner.end
1257 inner.sibling.catch:
1259 to label %unreachable unwind label %inner.end
1261 catchendpad unwind label %right.end
1265 ; This case tests the scenario where two catchpads with the same catchendpad
1266 ; have multiple parents. Both %left and %right are parents of %inner and
1267 ; %inner.sibling so both of the inner funclets must be cloned. Because
1268 ; the catchendpad in %inner.end unwinds to the catchendpad for %right, the
1269 ; unwind edge should be removed for the copy of %inner.end that is reached
1270 ; from %left. In addition, the %inner.siblin.catch block contains an invoke
1271 ; that unwinds to the shared inner catchendpad. The unwind destination for
1272 ; this invoke should be updated to unwind to the correct cloned %inner.end
1273 ; for each path to the funclet.
1274 ; CHECK-LABEL: define void @test17(
1276 ; CHECK: %l = cleanuppad []
1277 ; CHECK: invoke void @f()
1278 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1280 ; CHECK: catchpad []
1281 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1282 ; CHECK: [[RIGHT_CATCH]]:
1283 ; CHECK: invoke void @f()
1284 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1285 ; CHECK: [[RIGHT_END]]:
1286 ; CHECK: catchendpad unwind to caller
1287 ; CHECK: [[SHARED_CONT_RIGHT]]:
1288 ; CHECK: unreachable
1289 ; CHECK: [[SHARED_CONT_LEFT]]:
1290 ; CHECK: unreachable
1291 ; CHECK: [[INNER_RIGHT]]:
1292 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1293 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]]
1294 ; CHECK: [[INNER_LEFT]]:
1295 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1296 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]]
1297 ; CHECK: [[INNER_CATCH_RIGHT]]:
1298 ; CHECK: call void @h(i32 0)
1299 ; CHECK: unreachable
1300 ; CHECK: [[INNER_CATCH_LEFT]]:
1301 ; CHECK: call void @h(i32 0)
1302 ; CHECK: unreachable
1303 ; CHECK: [[INNER_SIBLING_RIGHT]]:
1304 ; CHECK: [[IS_RIGHT:\%.+]] = catchpad []
1305 ; CHECK: to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1306 ; CHECK: [[INNER_SIBLING_LEFT]]:
1307 ; CHECK: [[IS_LEFT:\%.+]] = catchpad []
1308 ; CHECK: to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1309 ; CHECK: [[INNER_SIBLING_CATCH_RIGHT]]:
1310 ; CHECK: invoke void @f()
1311 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
1312 ; CHECK: [[INNER_SIBLING_CATCH_LEFT]]:
1313 ; CHECK: invoke void @f()
1314 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT]]
1315 ; CHECK: [[INNER_END_LEFT]]:
1316 ; CHECK: catchendpad unwind to caller
1317 ; CHECK: [[INNER_END_RIGHT]]:
1318 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
1321 define void @test18() personality i32 (...)* @__CxxFrameHandler3 {
1324 to label %invoke.cont unwind label %left
1327 to label %exit unwind label %right
1333 to label %right.catch unwind label %right.end
1337 catchendpad unwind to caller
1340 to label %unreachable unwind label %inner
1345 to label %inner.catch unwind label %inner.sibling
1348 to label %unreachable unwind label %inner.end
1351 to label %inner.sibling.catch unwind label %inner.end
1352 inner.sibling.catch:
1356 catchendpad unwind label %right.end
1360 ; This is like test17 except that the inner invoke is moved from the
1361 ; %inner.sibling funclet to %inner so that it is unwinding to a
1362 ; catchendpad block that has not yet been cloned. The unwind destination
1363 ; of the invoke should still be updated to reach the correct copy of
1364 ; %inner.end for the path by which it is reached.
1365 ; CHECK-LABEL: define void @test18(
1367 ; CHECK: %l = cleanuppad []
1368 ; CHECK: invoke void @f()
1369 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1371 ; CHECK: catchpad []
1372 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1373 ; CHECK: [[RIGHT_CATCH]]:
1374 ; CHECK: invoke void @f()
1375 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1376 ; CHECK: [[RIGHT_END]]:
1377 ; CHECK: catchendpad unwind to caller
1378 ; CHECK: [[SHARED_CONT_RIGHT]]:
1379 ; CHECK: unreachable
1380 ; CHECK: [[SHARED_CONT_LEFT]]:
1381 ; CHECK: unreachable
1382 ; CHECK: [[INNER_RIGHT]]:
1383 ; CHECK: [[I_RIGHT:\%.+]] = catchpad []
1384 ; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]]
1385 ; CHECK: [[INNER_LEFT]]:
1386 ; CHECK: [[I_LEFT:\%.+]] = catchpad []
1387 ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]]
1388 ; CHECK: [[INNER_CATCH_RIGHT]]:
1389 ; CHECK: invoke void @f()
1390 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1391 ; CHECK: [[INNER_CATCH_LEFT]]:
1392 ; CHECK: invoke void @f()
1393 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1394 ; CHECK: [[INNER_SIBLING_RIGHT]]:
1395 ; CHECK: [[IS_RIGHT:\%.+]] = catchpad []
1396 ; CHECK: to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
1397 ; CHECK: [[INNER_SIBLING_LEFT]]:
1398 ; CHECK: [[IS_LEFT:\%.+]] = catchpad []
1399 ; CHECK: to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT]]
1400 ; CHECK: [[INNER_SIBLING_CATCH_RIGHT]]:
1401 ; CHECK: call void @h(i32 0)
1402 ; CHECK: unreachable
1403 ; CHECK: [[INNER_SIBLING_CATCH_LEFT]]:
1404 ; CHECK: call void @h(i32 0)
1405 ; CHECK: unreachable
1406 ; CHECK: [[INNER_END_LEFT]]:
1407 ; CHECK: catchendpad unwind to caller
1408 ; CHECK: [[INNER_END_RIGHT]]:
1409 ; CHECK: catchendpad unwind label %[[RIGHT_END]]
1412 define void @test19() personality i32 (...)* @__CxxFrameHandler3 {
1415 to label %invoke.cont unwind label %left
1418 to label %exit unwind label %right
1424 to label %right.catch unwind label %right.end
1428 catchendpad unwind to caller
1431 to label %unreachable unwind label %inner
1437 to label %unreachable unwind label %inner.end
1439 cleanupendpad %i unwind label %right.end
1443 ; This case tests the scenario where an invoke in a funclet with multiple
1444 ; parents unwinds to a cleanup end pad for the funclet. The unwind destination
1445 ; for the invoke should map to the correct copy of the cleanup end pad block.
1446 ; CHECK-LABEL: define void @test19(
1448 ; CHECK: %l = cleanuppad []
1449 ; CHECK: invoke void @f()
1450 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1452 ; CHECK: catchpad []
1453 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1454 ; CHECK: [[RIGHT_CATCH]]:
1455 ; CHECK: invoke void @f()
1456 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1457 ; CHECK: [[RIGHT_END]]:
1458 ; CHECK: catchendpad unwind to caller
1459 ; CHECK: [[SHARED_CONT_RIGHT]]:
1460 ; CHECK: unreachable
1461 ; CHECK: [[SHARED_CONT_LEFT]]:
1462 ; CHECK: unreachable
1463 ; CHECK: [[INNER_RIGHT]]:
1464 ; CHECK: [[I_RIGHT:\%.+]] = cleanuppad []
1465 ; CHECK: invoke void @f()
1466 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
1467 ; CHECK: [[INNER_LEFT]]:
1468 ; CHECK: [[I_LEFT:\%.+]] = cleanuppad []
1469 ; CHECK: invoke void @f()
1470 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
1471 ; CHECK: [[INNER_END_RIGHT]]:
1472 ; CHECK: cleanupendpad [[I_RIGHT]] unwind label %[[RIGHT_END]]
1473 ; CHECK: [[INNER_END_LEFT]]:
1474 ; CHECK: cleanupendpad [[I_LEFT]] unwind to caller
1476 define void @test20() personality i32 (...)* @__CxxFrameHandler3 {
1479 to label %invoke.cont unwind label %left
1482 to label %exit unwind label %right
1488 to label %right.catch unwind label %right.end
1492 catchendpad unwind to caller
1495 to label %unreachable unwind label %inner
1501 to label %unreachable unwind label %inner.cleanup
1509 ; This tests the case where a funclet with multiple parents contains an invoke
1510 ; instruction that unwinds to a child funclet. Here %left and %right are both
1511 ; parents of %inner. Initially %inner is the only parent of %inner.cleanup but
1512 ; after %inner is cloned, %inner.cleanup has multiple parents and so it must
1514 ; CHECK-LABEL: define void @test20(
1516 ; CHECK: %l = cleanuppad []
1517 ; CHECK: invoke void @f()
1518 ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
1520 ; CHECK: catchpad []
1521 ; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
1522 ; CHECK: [[RIGHT_CATCH]]:
1523 ; CHECK: invoke void @f()
1524 ; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
1525 ; CHECK: [[RIGHT_END]]:
1526 ; CHECK: catchendpad unwind to caller
1527 ; CHECK: [[SHARED_CONT_RIGHT]]:
1528 ; CHECK: unreachable
1529 ; CHECK: [[SHARED_CONT_LEFT]]:
1530 ; CHECK: unreachable
1531 ; CHECK: [[INNER_RIGHT]]:
1532 ; CHECK: [[I_RIGHT:\%.+]] = cleanuppad []
1533 ; CHECK: invoke void @f()
1534 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_CLEANUP_RIGHT:.+]]
1535 ; CHECK: [[INNER_LEFT]]:
1536 ; CHECK: [[I_LEFT:\%.+]] = cleanuppad []
1537 ; CHECK: invoke void @f()
1538 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_CLEANUP_LEFT:.+]]
1539 ; CHECK: [[INNER_CLEANUP_RIGHT]]:
1540 ; CHECK: cleanuppad []
1541 ; CHECK: call void @f()
1542 ; CHECK: unreachable
1543 ; CHECK: [[INNER_CLEANUP_LEFT]]:
1544 ; CHECK: cleanuppad []
1545 ; CHECK: call void @f()
1546 ; CHECK: unreachable