1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 5
2 ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -sink-common-insts -S | FileCheck %s
3 ; RUN: opt < %s -passes='simplifycfg<sink-common-insts>' -S | FileCheck %s
5 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
6 target triple = "x86_64-unknown-linux-gnu"
8 ; Simple test, nothing interesting happens here.
9 define void @t0_noop() personality ptr @__gxx_personality_v0 {
10 ; CHECK-LABEL: define void @t0_noop() personality ptr @__gxx_personality_v0 {
11 ; CHECK-NEXT: [[ENTRY:.*:]]
12 ; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
13 ; CHECK-NEXT: br i1 [[C]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
15 ; CHECK-NEXT: invoke void @simple_throw()
16 ; CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
17 ; CHECK: [[INVOKE_CONT]]:
18 ; CHECK-NEXT: unreachable
20 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
22 ; CHECK-NEXT: call void @destructor()
23 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
25 ; CHECK-NEXT: call void @sideeffect()
26 ; CHECK-NEXT: ret void
30 br i1 %c, label %if.then, label %if.end
33 invoke void @simple_throw() to label %invoke.cont unwind label %lpad
39 %eh = landingpad { ptr, i32 } cleanup
40 call void @destructor()
41 resume { ptr, i32 } %eh
44 call void @sideeffect()
48 ; More interesting test, here we can merge the invokes.
49 define void @t1_mergeable_invoke() personality ptr @__gxx_personality_v0 {
50 ; CHECK-LABEL: define void @t1_mergeable_invoke() personality ptr @__gxx_personality_v0 {
51 ; CHECK-NEXT: [[ENTRY:.*:]]
52 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
53 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
55 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
57 ; CHECK-NEXT: call void @destructor()
58 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
60 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
61 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
62 ; CHECK: [[IF_THEN1_INVOKE]]:
63 ; CHECK-NEXT: invoke void @simple_throw()
64 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
65 ; CHECK: [[IF_THEN1_CONT]]:
66 ; CHECK-NEXT: unreachable
68 ; CHECK-NEXT: call void @sideeffect()
69 ; CHECK-NEXT: ret void
73 br i1 %c0, label %if.then0, label %if.else
76 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
82 %eh = landingpad { ptr, i32 } cleanup
83 call void @destructor()
84 resume { ptr, i32 } %eh
88 br i1 %c1, label %if.then1, label %if.end
91 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
97 call void @sideeffect()
101 ; normal block is shared, but it is unreachable, so we are fine.
102 define void @t2_shared_normal_dest() personality ptr @__gxx_personality_v0 {
103 ; CHECK-LABEL: define void @t2_shared_normal_dest() personality ptr @__gxx_personality_v0 {
104 ; CHECK-NEXT: [[ENTRY:.*:]]
105 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
106 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
107 ; CHECK: [[LPAD:.*]]:
108 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
109 ; CHECK-NEXT: cleanup
110 ; CHECK-NEXT: call void @destructor()
111 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
112 ; CHECK: [[IF_ELSE]]:
113 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
114 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
115 ; CHECK: [[IF_THEN1_INVOKE]]:
116 ; CHECK-NEXT: invoke void @simple_throw()
117 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
118 ; CHECK: [[IF_THEN1_CONT]]:
119 ; CHECK-NEXT: unreachable
121 ; CHECK-NEXT: call void @sideeffect()
122 ; CHECK-NEXT: ret void
125 %c0 = call i1 @cond()
126 br i1 %c0, label %if.then0, label %if.else
129 invoke void @simple_throw() to label %invoke.cont unwind label %lpad
135 %eh = landingpad { ptr, i32 } cleanup
136 call void @destructor()
137 resume { ptr, i32 } %eh
140 %c1 = call i1 @cond()
141 br i1 %c1, label %if.then1, label %if.end
144 invoke void @simple_throw() to label %invoke.cont unwind label %lpad
147 call void @sideeffect()
151 ; shared normal destination is not unreachable.
152 define void @t3_shared_identical_normal_dest() personality ptr @__gxx_personality_v0 {
153 ; CHECK-LABEL: define void @t3_shared_identical_normal_dest() personality ptr @__gxx_personality_v0 {
154 ; CHECK-NEXT: [[ENTRY:.*:]]
155 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
156 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
157 ; CHECK: [[INVOKE_CONT:.*]]:
158 ; CHECK-NEXT: call void @sideeffect()
159 ; CHECK-NEXT: unreachable
160 ; CHECK: [[LPAD:.*]]:
161 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
162 ; CHECK-NEXT: cleanup
163 ; CHECK-NEXT: call void @destructor()
164 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
165 ; CHECK: [[IF_ELSE]]:
166 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
167 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
168 ; CHECK: [[IF_THEN1_INVOKE]]:
169 ; CHECK-NEXT: invoke void @maybe_throw()
170 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
172 ; CHECK-NEXT: call void @sideeffect()
173 ; CHECK-NEXT: ret void
176 %c0 = call i1 @cond()
177 br i1 %c0, label %if.then0, label %if.else
180 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
183 call void @sideeffect()
187 %eh = landingpad { ptr, i32 } cleanup
188 call void @destructor()
189 resume { ptr, i32 } %eh
192 %c1 = call i1 @cond()
193 br i1 %c1, label %if.then1, label %if.end
196 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
199 call void @sideeffect()
203 ; normal destinations are not unreachable and not shared and can not be merged.
204 define void @t4_normal_dests() personality ptr @__gxx_personality_v0 {
205 ; CHECK-LABEL: define void @t4_normal_dests() personality ptr @__gxx_personality_v0 {
206 ; CHECK-NEXT: [[ENTRY:.*:]]
207 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
208 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
209 ; CHECK: [[IF_THEN0]]:
210 ; CHECK-NEXT: invoke void @maybe_throw()
211 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
212 ; CHECK: [[INVOKE_CONT0]]:
213 ; CHECK-NEXT: call void @sideeffect()
214 ; CHECK-NEXT: unreachable
216 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
217 ; CHECK-NEXT: cleanup
218 ; CHECK-NEXT: call void @destructor()
219 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
220 ; CHECK: [[IF_ELSE]]:
221 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
222 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
223 ; CHECK: [[IF_THEN1]]:
224 ; CHECK-NEXT: invoke void @maybe_throw()
225 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
226 ; CHECK: [[INVOKE_CONT2]]:
227 ; CHECK-NEXT: call void @another_sideeffect()
228 ; CHECK-NEXT: unreachable
230 ; CHECK-NEXT: call void @sideeffect()
231 ; CHECK-NEXT: ret void
234 %c0 = call i1 @cond()
235 br i1 %c0, label %if.then0, label %if.else
238 invoke void @maybe_throw() to label %invoke.cont0 unwind label %lpad
241 call void @sideeffect()
245 %eh = landingpad { ptr, i32 } cleanup
246 call void @destructor()
247 resume { ptr, i32 } %eh
250 %c1 = call i1 @cond()
251 br i1 %c1, label %if.then1, label %if.end
254 invoke void @maybe_throw() to label %invoke.cont2 unwind label %lpad
257 call void @another_sideeffect()
261 call void @sideeffect()
265 ; Invokes lead to different landing pads.
266 define void @t5_different_landingpads() personality ptr @__gxx_personality_v0 {
267 ; CHECK-LABEL: define void @t5_different_landingpads() personality ptr @__gxx_personality_v0 {
268 ; CHECK-NEXT: [[ENTRY:.*:]]
269 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
270 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
271 ; CHECK: [[IF_THEN0]]:
272 ; CHECK-NEXT: invoke void @simple_throw()
273 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD0:.*]]
274 ; CHECK: [[INVOKE_CONT0]]:
275 ; CHECK-NEXT: unreachable
276 ; CHECK: [[COMMON_RESUME:.*]]:
277 ; CHECK-NEXT: [[COMMON_RESUME_OP:%.*]] = phi { ptr, i32 } [ [[EH0:%.*]], %[[LPAD0]] ], [ [[EH1:%.*]], %[[LPAD1:.*]] ]
278 ; CHECK-NEXT: resume { ptr, i32 } [[COMMON_RESUME_OP]]
280 ; CHECK-NEXT: [[EH0]] = landingpad { ptr, i32 }
281 ; CHECK-NEXT: cleanup
282 ; CHECK-NEXT: call void @destructor()
283 ; CHECK-NEXT: br label %[[COMMON_RESUME]]
284 ; CHECK: [[IF_ELSE]]:
285 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
286 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
287 ; CHECK: [[IF_THEN1]]:
288 ; CHECK-NEXT: invoke void @simple_throw()
289 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD1]]
290 ; CHECK: [[INVOKE_CONT2]]:
291 ; CHECK-NEXT: unreachable
293 ; CHECK-NEXT: [[EH1]] = landingpad { ptr, i32 }
294 ; CHECK-NEXT: cleanup
295 ; CHECK-NEXT: call void @another_destructor()
296 ; CHECK-NEXT: br label %[[COMMON_RESUME]]
298 ; CHECK-NEXT: call void @sideeffect()
299 ; CHECK-NEXT: ret void
302 %c0 = call i1 @cond()
303 br i1 %c0, label %if.then0, label %if.else
306 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad0
312 %eh0 = landingpad { ptr, i32 } cleanup
313 call void @destructor()
314 resume { ptr, i32 } %eh0
317 %c1 = call i1 @cond()
318 br i1 %c1, label %if.then1, label %if.end
321 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad1
327 %eh1 = landingpad { ptr, i32 } cleanup
328 call void @another_destructor()
329 resume { ptr, i32 } %eh1
332 call void @sideeffect()
336 ; The invoked functions are different
337 define void @t6_different_invokes() personality ptr @__gxx_personality_v0 {
338 ; CHECK-LABEL: define void @t6_different_invokes() personality ptr @__gxx_personality_v0 {
339 ; CHECK-NEXT: [[ENTRY:.*:]]
340 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
341 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
342 ; CHECK: [[IF_THEN0]]:
343 ; CHECK-NEXT: invoke void @simple_throw()
344 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
345 ; CHECK: [[INVOKE_CONT0]]:
346 ; CHECK-NEXT: unreachable
348 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
349 ; CHECK-NEXT: cleanup
350 ; CHECK-NEXT: call void @destructor()
351 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
352 ; CHECK: [[IF_ELSE]]:
353 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
354 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
355 ; CHECK: [[IF_THEN1]]:
356 ; CHECK-NEXT: invoke void @another_simple_throw()
357 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
358 ; CHECK: [[INVOKE_CONT2]]:
359 ; CHECK-NEXT: unreachable
361 ; CHECK-NEXT: call void @sideeffect()
362 ; CHECK-NEXT: ret void
365 %c0 = call i1 @cond()
366 br i1 %c0, label %if.then0, label %if.else
369 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
375 %eh = landingpad { ptr, i32 } cleanup
376 call void @destructor()
377 resume { ptr, i32 } %eh
380 %c1 = call i1 @cond()
381 br i1 %c1, label %if.then1, label %if.end
384 invoke void @another_simple_throw() to label %invoke.cont2 unwind label %lpad
390 call void @sideeffect()
394 ; Merging of this invoke is disallowed
395 define void @t7_nomerge0() personality ptr @__gxx_personality_v0 {
396 ; CHECK-LABEL: define void @t7_nomerge0() personality ptr @__gxx_personality_v0 {
397 ; CHECK-NEXT: [[ENTRY:.*:]]
398 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
399 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
400 ; CHECK: [[IF_THEN0]]:
401 ; CHECK-NEXT: invoke void @simple_throw()
402 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
403 ; CHECK: [[INVOKE_CONT0]]:
404 ; CHECK-NEXT: unreachable
406 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
407 ; CHECK-NEXT: cleanup
408 ; CHECK-NEXT: call void @destructor()
409 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
410 ; CHECK: [[IF_ELSE]]:
411 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
412 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
413 ; CHECK: [[IF_THEN1]]:
414 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1:[0-9]+]]
415 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
416 ; CHECK: [[INVOKE_CONT2]]:
417 ; CHECK-NEXT: unreachable
419 ; CHECK-NEXT: call void @sideeffect()
420 ; CHECK-NEXT: ret void
423 %c0 = call i1 @cond()
424 br i1 %c0, label %if.then0, label %if.else
427 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
433 %eh = landingpad { ptr, i32 } cleanup
434 call void @destructor()
435 resume { ptr, i32 } %eh
438 %c1 = call i1 @cond()
439 br i1 %c1, label %if.then1, label %if.end
442 invoke void @simple_throw() nomerge to label %invoke.cont2 unwind label %lpad
448 call void @sideeffect()
451 define void @t8_nomerge1() personality ptr @__gxx_personality_v0 {
452 ; CHECK-LABEL: define void @t8_nomerge1() personality ptr @__gxx_personality_v0 {
453 ; CHECK-NEXT: [[ENTRY:.*:]]
454 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
455 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
456 ; CHECK: [[IF_THEN0]]:
457 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1]]
458 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
459 ; CHECK: [[INVOKE_CONT0]]:
460 ; CHECK-NEXT: unreachable
462 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
463 ; CHECK-NEXT: cleanup
464 ; CHECK-NEXT: call void @destructor()
465 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
466 ; CHECK: [[IF_ELSE]]:
467 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
468 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
469 ; CHECK: [[IF_THEN1]]:
470 ; CHECK-NEXT: invoke void @simple_throw()
471 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
472 ; CHECK: [[INVOKE_CONT2]]:
473 ; CHECK-NEXT: unreachable
475 ; CHECK-NEXT: call void @sideeffect()
476 ; CHECK-NEXT: ret void
479 %c0 = call i1 @cond()
480 br i1 %c0, label %if.then0, label %if.else
483 invoke void @simple_throw() nomerge to label %invoke.cont0 unwind label %lpad
489 %eh = landingpad { ptr, i32 } cleanup
490 call void @destructor()
491 resume { ptr, i32 } %eh
494 %c1 = call i1 @cond()
495 br i1 %c1, label %if.then1, label %if.end
498 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
504 call void @sideeffect()
507 define void @t9_nomerge2() personality ptr @__gxx_personality_v0 {
508 ; CHECK-LABEL: define void @t9_nomerge2() personality ptr @__gxx_personality_v0 {
509 ; CHECK-NEXT: [[ENTRY:.*:]]
510 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
511 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
512 ; CHECK: [[IF_THEN0]]:
513 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1]]
514 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
515 ; CHECK: [[INVOKE_CONT0]]:
516 ; CHECK-NEXT: unreachable
518 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
519 ; CHECK-NEXT: cleanup
520 ; CHECK-NEXT: call void @destructor()
521 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
522 ; CHECK: [[IF_ELSE]]:
523 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
524 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
525 ; CHECK: [[IF_THEN1]]:
526 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1]]
527 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
528 ; CHECK: [[INVOKE_CONT2]]:
529 ; CHECK-NEXT: unreachable
531 ; CHECK-NEXT: call void @sideeffect()
532 ; CHECK-NEXT: ret void
535 %c0 = call i1 @cond()
536 br i1 %c0, label %if.then0, label %if.else
539 invoke void @simple_throw() nomerge to label %invoke.cont0 unwind label %lpad
545 %eh = landingpad { ptr, i32 } cleanup
546 call void @destructor()
547 resume { ptr, i32 } %eh
550 %c1 = call i1 @cond()
551 br i1 %c1, label %if.then1, label %if.end
554 invoke void @simple_throw() nomerge to label %invoke.cont2 unwind label %lpad
560 call void @sideeffect()
564 ; Just don't deal with inlineasm.
565 define void @t10_inlineasm() personality ptr @__gxx_personality_v0 {
566 ; CHECK-LABEL: define void @t10_inlineasm() personality ptr @__gxx_personality_v0 {
567 ; CHECK-NEXT: [[ENTRY:.*:]]
568 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
569 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
570 ; CHECK: [[IF_THEN0]]:
571 ; CHECK-NEXT: invoke void asm sideeffect "something bad", ""()
572 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
573 ; CHECK: [[INVOKE_CONT0]]:
574 ; CHECK-NEXT: unreachable
576 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
577 ; CHECK-NEXT: cleanup
578 ; CHECK-NEXT: call void @destructor()
579 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
580 ; CHECK: [[IF_ELSE]]:
581 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
582 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
583 ; CHECK: [[IF_THEN1]]:
584 ; CHECK-NEXT: invoke void asm sideeffect "something bad", ""()
585 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
586 ; CHECK: [[INVOKE_CONT2]]:
587 ; CHECK-NEXT: unreachable
589 ; CHECK-NEXT: call void @sideeffect()
590 ; CHECK-NEXT: ret void
593 %c0 = call i1 @cond()
594 br i1 %c0, label %if.then0, label %if.else
597 invoke void asm sideeffect "something bad", ""() to label %invoke.cont0 unwind label %lpad
603 %eh = landingpad { ptr, i32 } cleanup
604 call void @destructor()
605 resume { ptr, i32 } %eh
608 %c1 = call i1 @cond()
609 br i1 %c1, label %if.then1, label %if.end
612 invoke void asm sideeffect "something bad", ""() to label %invoke.cont2 unwind label %lpad
618 call void @sideeffect()
622 ; landingpad has PHI nodes, and the incoming values are incompatible.
623 define void @t11_phi_in_landingpad_incompatible_incoming_values() personality ptr @__gxx_personality_v0 {
624 ; CHECK-LABEL: define void @t11_phi_in_landingpad_incompatible_incoming_values() personality ptr @__gxx_personality_v0 {
625 ; CHECK-NEXT: [[ENTRY:.*:]]
626 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
627 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
628 ; CHECK: [[IF_THEN0]]:
629 ; CHECK-NEXT: invoke void @simple_throw()
630 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
631 ; CHECK: [[INVOKE_CONT0]]:
632 ; CHECK-NEXT: unreachable
634 ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[IF_THEN0]] ], [ 1, %[[IF_THEN1:.*]] ]
635 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
636 ; CHECK-NEXT: cleanup
637 ; CHECK-NEXT: call void @consume(i32 [[PHI]])
638 ; CHECK-NEXT: call void @destructor()
639 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
640 ; CHECK: [[IF_ELSE]]:
641 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
642 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1]], label %[[IF_END:.*]]
643 ; CHECK: [[IF_THEN1]]:
644 ; CHECK-NEXT: invoke void @simple_throw()
645 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
646 ; CHECK: [[INVOKE_CONT2]]:
647 ; CHECK-NEXT: unreachable
649 ; CHECK-NEXT: call void @sideeffect()
650 ; CHECK-NEXT: ret void
653 %c0 = call i1 @cond()
654 br i1 %c0, label %if.then0, label %if.else
657 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
663 %phi = phi i32 [ 0, %if.then0 ], [ 1, %if.then1 ]
664 %eh = landingpad { ptr, i32 } cleanup
665 call void @consume(i32 %phi)
666 call void @destructor()
667 resume { ptr, i32 } %eh
670 %c1 = call i1 @cond()
671 br i1 %c1, label %if.then1, label %if.end
674 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
680 call void @sideeffect()
684 ; It is okay for the invoke to take arguments
685 define void @t12_arguments_are_fine() personality ptr @__gxx_personality_v0 {
686 ; CHECK-LABEL: define void @t12_arguments_are_fine() personality ptr @__gxx_personality_v0 {
687 ; CHECK-NEXT: [[ENTRY:.*:]]
688 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
689 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
690 ; CHECK: [[LPAD:.*]]:
691 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
692 ; CHECK-NEXT: cleanup
693 ; CHECK-NEXT: call void @destructor()
694 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
695 ; CHECK: [[IF_ELSE]]:
696 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
697 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
698 ; CHECK: [[IF_THEN1_INVOKE]]:
699 ; CHECK-NEXT: invoke void @simple_throw_taking_argument(i32 42)
700 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
701 ; CHECK: [[IF_THEN1_CONT]]:
702 ; CHECK-NEXT: unreachable
704 ; CHECK-NEXT: call void @sideeffect()
705 ; CHECK-NEXT: ret void
708 %c0 = call i1 @cond()
709 br i1 %c0, label %if.then0, label %if.else
712 invoke void @simple_throw_taking_argument(i32 42) to label %invoke.cont0 unwind label %lpad
718 %eh = landingpad { ptr, i32 } cleanup
719 call void @destructor()
720 resume { ptr, i32 } %eh
723 %c1 = call i1 @cond()
724 br i1 %c1, label %if.then1, label %if.end
727 invoke void @simple_throw_taking_argument(i32 42) to label %invoke.cont2 unwind label %lpad
733 call void @sideeffect()
737 ; It is okay for the invoke to take different arguments
738 define void @t13_different_arguments_are_fine() personality ptr @__gxx_personality_v0 {
739 ; CHECK-LABEL: define void @t13_different_arguments_are_fine() personality ptr @__gxx_personality_v0 {
740 ; CHECK-NEXT: [[ENTRY:.*]]:
741 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
742 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
743 ; CHECK: [[LPAD:.*]]:
744 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
745 ; CHECK-NEXT: cleanup
746 ; CHECK-NEXT: call void @destructor()
747 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
748 ; CHECK: [[IF_ELSE]]:
749 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
750 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
751 ; CHECK: [[IF_THEN1_INVOKE]]:
752 ; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, %[[IF_ELSE]] ], [ 0, %[[ENTRY]] ]
753 ; CHECK-NEXT: invoke void @simple_throw_taking_argument(i32 [[TMP0]])
754 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
755 ; CHECK: [[IF_THEN1_CONT]]:
756 ; CHECK-NEXT: unreachable
758 ; CHECK-NEXT: call void @sideeffect()
759 ; CHECK-NEXT: ret void
762 %c0 = call i1 @cond()
763 br i1 %c0, label %if.then0, label %if.else
766 invoke void @simple_throw_taking_argument(i32 0) to label %invoke.cont0 unwind label %lpad
772 %eh = landingpad { ptr, i32 } cleanup
773 call void @destructor()
774 resume { ptr, i32 } %eh
777 %c1 = call i1 @cond()
778 br i1 %c1, label %if.then1, label %if.end
781 invoke void @simple_throw_taking_argument(i32 42) to label %invoke.cont2 unwind label %lpad
787 call void @sideeffect()
791 ; There can be more than two invokes in a set
792 define void @t14_three_invokes() personality ptr @__gxx_personality_v0 {
793 ; CHECK-LABEL: define void @t14_three_invokes() personality ptr @__gxx_personality_v0 {
794 ; CHECK-NEXT: [[ENTRY:.*:]]
795 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
796 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN2_INVOKE:.*]], label %[[IF_ELSE0:.*]]
797 ; CHECK: [[LPAD:.*]]:
798 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
799 ; CHECK-NEXT: cleanup
800 ; CHECK-NEXT: call void @destructor()
801 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
802 ; CHECK: [[IF_ELSE0]]:
803 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
804 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN2_INVOKE]], label %[[IF_ELSE1:.*]]
805 ; CHECK: [[IF_ELSE1]]:
806 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
807 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN2_INVOKE]], label %[[IF_END:.*]]
808 ; CHECK: [[IF_THEN2_INVOKE]]:
809 ; CHECK-NEXT: invoke void @simple_throw()
810 ; CHECK-NEXT: to label %[[IF_THEN2_CONT:.*]] unwind label %[[LPAD]]
811 ; CHECK: [[IF_THEN2_CONT]]:
812 ; CHECK-NEXT: unreachable
814 ; CHECK-NEXT: call void @sideeffect()
815 ; CHECK-NEXT: ret void
818 %c0 = call i1 @cond()
819 br i1 %c0, label %if.then0, label %if.else0
822 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
828 %eh = landingpad { ptr, i32 } cleanup
829 call void @destructor()
830 resume { ptr, i32 } %eh
833 %c1 = call i1 @cond()
834 br i1 %c1, label %if.then1, label %if.else1
837 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
843 %c2 = call i1 @cond()
844 br i1 %c2, label %if.then2, label %if.end
847 invoke void @simple_throw() to label %invoke.cont3 unwind label %lpad
853 call void @sideeffect()
857 ; If not all invokes of landingpad are compatible then we still merge compatible ones.
858 define void @t15_three_invokes_only_two_compatible() personality ptr @__gxx_personality_v0 {
859 ; CHECK-LABEL: define void @t15_three_invokes_only_two_compatible() personality ptr @__gxx_personality_v0 {
860 ; CHECK-NEXT: [[ENTRY:.*:]]
861 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
862 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE0:.*]]
863 ; CHECK: [[LPAD:.*]]:
864 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
865 ; CHECK-NEXT: cleanup
866 ; CHECK-NEXT: call void @destructor()
867 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
868 ; CHECK: [[IF_ELSE0]]:
869 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
870 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_ELSE1:.*]]
871 ; CHECK: [[IF_THEN1_INVOKE]]:
872 ; CHECK-NEXT: invoke void @simple_throw()
873 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
874 ; CHECK: [[IF_THEN1_CONT]]:
875 ; CHECK-NEXT: unreachable
876 ; CHECK: [[IF_ELSE1]]:
877 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
878 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN2:.*]], label %[[IF_END:.*]]
879 ; CHECK: [[IF_THEN2]]:
880 ; CHECK-NEXT: invoke void @another_simple_throw()
881 ; CHECK-NEXT: to label %[[INVOKE_CONT3:.*]] unwind label %[[LPAD]]
882 ; CHECK: [[INVOKE_CONT3]]:
883 ; CHECK-NEXT: unreachable
885 ; CHECK-NEXT: call void @sideeffect()
886 ; CHECK-NEXT: ret void
889 %c0 = call i1 @cond()
890 br i1 %c0, label %if.then0, label %if.else0
893 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
899 %eh = landingpad { ptr, i32 } cleanup
900 call void @destructor()
901 resume { ptr, i32 } %eh
904 %c1 = call i1 @cond()
905 br i1 %c1, label %if.then1, label %if.else1
908 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
914 %c2 = call i1 @cond()
915 br i1 %c2, label %if.then2, label %if.end
918 invoke void @another_simple_throw() to label %invoke.cont3 unwind label %lpad
924 call void @sideeffect()
928 ; We succeed in merging invokes into two sets
929 define void @t16_four_invokes_forming_two_sets() personality ptr @__gxx_personality_v0 {
930 ; CHECK-LABEL: define void @t16_four_invokes_forming_two_sets() personality ptr @__gxx_personality_v0 {
931 ; CHECK-NEXT: [[ENTRY:.*:]]
932 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
933 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE0:.*]]
934 ; CHECK: [[LPAD:.*]]:
935 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
936 ; CHECK-NEXT: cleanup
937 ; CHECK-NEXT: call void @destructor()
938 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
939 ; CHECK: [[IF_ELSE0]]:
940 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
941 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_ELSE1:.*]]
942 ; CHECK: [[IF_THEN1_INVOKE]]:
943 ; CHECK-NEXT: invoke void @simple_throw()
944 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
945 ; CHECK: [[IF_THEN1_CONT]]:
946 ; CHECK-NEXT: unreachable
947 ; CHECK: [[IF_ELSE1]]:
948 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
949 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN3_INVOKE:.*]], label %[[IF_ELSE2:.*]]
950 ; CHECK: [[IF_ELSE2]]:
951 ; CHECK-NEXT: [[C3:%.*]] = call i1 @cond()
952 ; CHECK-NEXT: br i1 [[C3]], label %[[IF_THEN3_INVOKE]], label %[[IF_END:.*]]
953 ; CHECK: [[IF_THEN3_INVOKE]]:
954 ; CHECK-NEXT: invoke void @another_simple_throw()
955 ; CHECK-NEXT: to label %[[IF_THEN3_CONT:.*]] unwind label %[[LPAD]]
956 ; CHECK: [[IF_THEN3_CONT]]:
957 ; CHECK-NEXT: unreachable
959 ; CHECK-NEXT: call void @sideeffect()
960 ; CHECK-NEXT: ret void
963 %c0 = call i1 @cond()
964 br i1 %c0, label %if.then0, label %if.else0
967 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
973 %eh = landingpad { ptr, i32 } cleanup
974 call void @destructor()
975 resume { ptr, i32 } %eh
978 %c1 = call i1 @cond()
979 br i1 %c1, label %if.then1, label %if.else1
982 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
988 %c2 = call i1 @cond()
989 br i1 %c2, label %if.then2, label %if.else2
992 invoke void @another_simple_throw() to label %invoke.cont3 unwind label %lpad
998 %c3 = call i1 @cond()
999 br i1 %c3, label %if.then3, label %if.end
1002 invoke void @another_simple_throw() to label %invoke.cont4 unwind label %lpad
1008 call void @sideeffect()
1012 define void @t17_mismatched_attrs_okay_merge() personality ptr @__gxx_personality_v0 {
1013 ; CHECK-LABEL: define void @t17_mismatched_attrs_okay_merge() personality ptr @__gxx_personality_v0 {
1014 ; CHECK-NEXT: [[ENTRY:.*:]]
1015 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1016 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1017 ; CHECK: [[LPAD:.*]]:
1018 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1019 ; CHECK-NEXT: cleanup
1020 ; CHECK-NEXT: call void @destructor()
1021 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1022 ; CHECK: [[IF_ELSE]]:
1023 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1024 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1025 ; CHECK: [[IF_THEN1_INVOKE]]:
1026 ; CHECK-NEXT: invoke void @simple_throw()
1027 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1028 ; CHECK: [[IF_THEN1_CONT]]:
1029 ; CHECK-NEXT: unreachable
1030 ; CHECK: [[IF_END]]:
1031 ; CHECK-NEXT: call void @sideeffect()
1032 ; CHECK-NEXT: ret void
1035 %c0 = call i1 @cond()
1036 br i1 %c0, label %if.then0, label %if.else
1039 invoke void @simple_throw() readnone to label %invoke.cont0 unwind label %lpad
1045 %eh = landingpad { ptr, i32 } cleanup
1046 call void @destructor()
1047 resume { ptr, i32 } %eh
1050 %c1 = call i1 @cond()
1051 br i1 %c1, label %if.then1, label %if.end
1054 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
1060 call void @sideeffect()
1064 define void @t17_mismatched_attrs_okay_merge_intersect() personality ptr @__gxx_personality_v0 {
1065 ; CHECK-LABEL: define void @t17_mismatched_attrs_okay_merge_intersect() personality ptr @__gxx_personality_v0 {
1066 ; CHECK-NEXT: [[ENTRY:.*:]]
1067 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1068 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1069 ; CHECK: [[LPAD:.*]]:
1070 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1071 ; CHECK-NEXT: cleanup
1072 ; CHECK-NEXT: call void @destructor()
1073 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1074 ; CHECK: [[IF_ELSE]]:
1075 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1076 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1077 ; CHECK: [[IF_THEN1_INVOKE]]:
1078 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2:[0-9]+]]
1079 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1080 ; CHECK: [[IF_THEN1_CONT]]:
1081 ; CHECK-NEXT: unreachable
1082 ; CHECK: [[IF_END]]:
1083 ; CHECK-NEXT: call void @sideeffect()
1084 ; CHECK-NEXT: ret void
1087 %c0 = call i1 @cond()
1088 br i1 %c0, label %if.then0, label %if.else
1091 invoke void @simple_throw() readnone cold to label %invoke.cont0 unwind label %lpad
1097 %eh = landingpad { ptr, i32 } cleanup
1098 call void @destructor()
1099 resume { ptr, i32 } %eh
1102 %c1 = call i1 @cond()
1103 br i1 %c1, label %if.then1, label %if.end
1106 invoke void @simple_throw() readnone to label %invoke.cont2 unwind label %lpad
1112 call void @sideeffect()
1116 define void @t17_mismatched_attrs_okay_merge_intersect2() personality ptr @__gxx_personality_v0 {
1117 ; CHECK-LABEL: define void @t17_mismatched_attrs_okay_merge_intersect2() personality ptr @__gxx_personality_v0 {
1118 ; CHECK-NEXT: [[ENTRY:.*:]]
1119 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1120 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1121 ; CHECK: [[LPAD:.*]]:
1122 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1123 ; CHECK-NEXT: cleanup
1124 ; CHECK-NEXT: call void @destructor()
1125 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1126 ; CHECK: [[IF_ELSE]]:
1127 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1128 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1129 ; CHECK: [[IF_THEN1_INVOKE]]:
1130 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2]]
1131 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1132 ; CHECK: [[IF_THEN1_CONT]]:
1133 ; CHECK-NEXT: unreachable
1134 ; CHECK: [[IF_END]]:
1135 ; CHECK-NEXT: call void @sideeffect()
1136 ; CHECK-NEXT: ret void
1139 %c0 = call i1 @cond()
1140 br i1 %c0, label %if.then0, label %if.else
1143 invoke void @simple_throw() readnone to label %invoke.cont0 unwind label %lpad
1149 %eh = landingpad { ptr, i32 } cleanup
1150 call void @destructor()
1151 resume { ptr, i32 } %eh
1154 %c1 = call i1 @cond()
1155 br i1 %c1, label %if.then1, label %if.end
1158 invoke void @simple_throw() readnone cold to label %invoke.cont2 unwind label %lpad
1164 call void @sideeffect()
1169 define void @t17_mismatched_attrs_prevent_merge() personality ptr @__gxx_personality_v0 {
1170 ; CHECK-LABEL: define void @t17_mismatched_attrs_prevent_merge() personality ptr @__gxx_personality_v0 {
1171 ; CHECK-NEXT: [[ENTRY:.*:]]
1172 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1173 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
1174 ; CHECK: [[IF_THEN0]]:
1175 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR3:[0-9]+]]
1176 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
1177 ; CHECK: [[INVOKE_CONT0]]:
1178 ; CHECK-NEXT: unreachable
1180 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1181 ; CHECK-NEXT: cleanup
1182 ; CHECK-NEXT: call void @destructor()
1183 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1184 ; CHECK: [[IF_ELSE]]:
1185 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1186 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
1187 ; CHECK: [[IF_THEN1]]:
1188 ; CHECK-NEXT: invoke void @simple_throw()
1189 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
1190 ; CHECK: [[INVOKE_CONT2]]:
1191 ; CHECK-NEXT: unreachable
1192 ; CHECK: [[IF_END]]:
1193 ; CHECK-NEXT: call void @sideeffect()
1194 ; CHECK-NEXT: ret void
1197 %c0 = call i1 @cond()
1198 br i1 %c0, label %if.then0, label %if.else
1201 invoke void @simple_throw() strictfp to label %invoke.cont0 unwind label %lpad
1207 %eh = landingpad { ptr, i32 } cleanup
1208 call void @destructor()
1209 resume { ptr, i32 } %eh
1212 %c1 = call i1 @cond()
1213 br i1 %c1, label %if.then1, label %if.end
1216 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
1222 call void @sideeffect()
1227 ; Common attributes are preserved
1228 define void @t18_attributes_are_preserved() personality ptr @__gxx_personality_v0 {
1229 ; CHECK-LABEL: define void @t18_attributes_are_preserved() personality ptr @__gxx_personality_v0 {
1230 ; CHECK-NEXT: [[ENTRY:.*:]]
1231 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1232 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1233 ; CHECK: [[LPAD:.*]]:
1234 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1235 ; CHECK-NEXT: cleanup
1236 ; CHECK-NEXT: call void @destructor()
1237 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1238 ; CHECK: [[IF_ELSE]]:
1239 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1240 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1241 ; CHECK: [[IF_THEN1_INVOKE]]:
1242 ; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2]]
1243 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1244 ; CHECK: [[IF_THEN1_CONT]]:
1245 ; CHECK-NEXT: unreachable
1246 ; CHECK: [[IF_END]]:
1247 ; CHECK-NEXT: call void @sideeffect()
1248 ; CHECK-NEXT: ret void
1251 %c0 = call i1 @cond()
1252 br i1 %c0, label %if.then0, label %if.else
1255 invoke void @simple_throw() readnone to label %invoke.cont0 unwind label %lpad
1261 %eh = landingpad { ptr, i32 } cleanup
1262 call void @destructor()
1263 resume { ptr, i32 } %eh
1266 %c1 = call i1 @cond()
1267 br i1 %c1, label %if.then1, label %if.end
1270 invoke void @simple_throw() readnone to label %invoke.cont2 unwind label %lpad
1276 call void @sideeffect()
1280 ; Fully identical operand bundles are good.
1281 define void @t19_compatible_operand_bundle() personality ptr @__gxx_personality_v0 {
1282 ; CHECK-LABEL: define void @t19_compatible_operand_bundle() personality ptr @__gxx_personality_v0 {
1283 ; CHECK-NEXT: [[ENTRY:.*:]]
1284 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1285 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1286 ; CHECK: [[LPAD:.*]]:
1287 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1288 ; CHECK-NEXT: cleanup
1289 ; CHECK-NEXT: call void @destructor()
1290 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1291 ; CHECK: [[IF_ELSE]]:
1292 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1293 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1294 ; CHECK: [[IF_THEN1_INVOKE]]:
1295 ; CHECK-NEXT: invoke void @simple_throw() [ "abc"(i32 42) ]
1296 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1297 ; CHECK: [[IF_THEN1_CONT]]:
1298 ; CHECK-NEXT: unreachable
1299 ; CHECK: [[IF_END]]:
1300 ; CHECK-NEXT: call void @sideeffect()
1301 ; CHECK-NEXT: ret void
1304 %c0 = call i1 @cond()
1305 br i1 %c0, label %if.then0, label %if.else
1308 invoke void @simple_throw() [ "abc"(i32 42) ] to label %invoke.cont0 unwind label %lpad
1314 %eh = landingpad { ptr, i32 } cleanup
1315 call void @destructor()
1316 resume { ptr, i32 } %eh
1319 %c1 = call i1 @cond()
1320 br i1 %c1, label %if.then1, label %if.end
1323 invoke void @simple_throw() [ "abc"(i32 42) ] to label %invoke.cont2 unwind label %lpad
1329 call void @sideeffect()
1333 ; Operand bundles must be compatible, else we can't merge.
1334 define void @t20_incompatible_operand_bundle() personality ptr @__gxx_personality_v0 {
1335 ; CHECK-LABEL: define void @t20_incompatible_operand_bundle() personality ptr @__gxx_personality_v0 {
1336 ; CHECK-NEXT: [[ENTRY:.*:]]
1337 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1338 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
1339 ; CHECK: [[IF_THEN0]]:
1340 ; CHECK-NEXT: invoke void @simple_throw() [ "abc"(i32 42) ]
1341 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
1342 ; CHECK: [[INVOKE_CONT0]]:
1343 ; CHECK-NEXT: unreachable
1345 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1346 ; CHECK-NEXT: cleanup
1347 ; CHECK-NEXT: call void @destructor()
1348 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1349 ; CHECK: [[IF_ELSE]]:
1350 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1351 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
1352 ; CHECK: [[IF_THEN1]]:
1353 ; CHECK-NEXT: invoke void @simple_throw() [ "def"(i32 0) ]
1354 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
1355 ; CHECK: [[INVOKE_CONT2]]:
1356 ; CHECK-NEXT: unreachable
1357 ; CHECK: [[IF_END]]:
1358 ; CHECK-NEXT: call void @sideeffect()
1359 ; CHECK-NEXT: ret void
1362 %c0 = call i1 @cond()
1363 br i1 %c0, label %if.then0, label %if.else
1366 invoke void @simple_throw() [ "abc"(i32 42) ] to label %invoke.cont0 unwind label %lpad
1372 %eh = landingpad { ptr, i32 } cleanup
1373 call void @destructor()
1374 resume { ptr, i32 } %eh
1377 %c1 = call i1 @cond()
1378 br i1 %c1, label %if.then1, label %if.end
1381 invoke void @simple_throw() [ "def"(i32 0) ] to label %invoke.cont2 unwind label %lpad
1387 call void @sideeffect()
1391 ; We need to PHI together the arguments of the operand bundles.
1392 define void @t21_semicompatible_operand_bundle(i32 %a, i32 %b) personality ptr @__gxx_personality_v0 {
1393 ; CHECK-LABEL: define void @t21_semicompatible_operand_bundle(
1394 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) personality ptr @__gxx_personality_v0 {
1395 ; CHECK-NEXT: [[ENTRY:.*]]:
1396 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1397 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1398 ; CHECK: [[LPAD:.*]]:
1399 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1400 ; CHECK-NEXT: cleanup
1401 ; CHECK-NEXT: call void @destructor()
1402 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1403 ; CHECK: [[IF_ELSE]]:
1404 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1405 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1406 ; CHECK: [[IF_THEN1_INVOKE]]:
1407 ; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[B]], %[[IF_ELSE]] ], [ [[A]], %[[ENTRY]] ]
1408 ; CHECK-NEXT: invoke void @simple_throw() [ "abc"(i32 [[TMP0]]) ]
1409 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1410 ; CHECK: [[IF_THEN1_CONT]]:
1411 ; CHECK-NEXT: unreachable
1412 ; CHECK: [[IF_END]]:
1413 ; CHECK-NEXT: call void @sideeffect()
1414 ; CHECK-NEXT: ret void
1417 %c0 = call i1 @cond()
1418 br i1 %c0, label %if.then0, label %if.else
1421 invoke void @simple_throw() [ "abc"(i32 %a) ] to label %invoke.cont0 unwind label %lpad
1427 %eh = landingpad { ptr, i32 } cleanup
1428 call void @destructor()
1429 resume { ptr, i32 } %eh
1432 %c1 = call i1 @cond()
1433 br i1 %c1, label %if.then1, label %if.end
1436 invoke void @simple_throw() [ "abc"(i32 %b) ] to label %invoke.cont2 unwind label %lpad
1442 call void @sideeffect()
1446 ; Even though the normal destinations are unreachable,
1447 ; they may have (dead) PHI nodes, so we must cleanup them.
1448 define void @t22_dead_phi_in_normal_dest() personality ptr @__gxx_personality_v0 {
1449 ; CHECK-LABEL: define void @t22_dead_phi_in_normal_dest() personality ptr @__gxx_personality_v0 {
1450 ; CHECK-NEXT: [[ENTRY:.*:]]
1451 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1452 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1453 ; CHECK: [[LPAD:.*]]:
1454 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1455 ; CHECK-NEXT: cleanup
1456 ; CHECK-NEXT: call void @destructor()
1457 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1458 ; CHECK: [[IF_ELSE]]:
1459 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1460 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1461 ; CHECK: [[IF_THEN1_INVOKE]]:
1462 ; CHECK-NEXT: invoke void @maybe_throw()
1463 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1464 ; CHECK: [[IF_THEN1_CONT]]:
1465 ; CHECK-NEXT: unreachable
1466 ; CHECK: [[IF_END]]:
1467 ; CHECK-NEXT: call void @sideeffect()
1468 ; CHECK-NEXT: ret void
1471 %c0 = call i1 @cond()
1472 br i1 %c0, label %if.then0, label %if.else
1475 invoke void @maybe_throw() to label %invoke.cont0 unwind label %lpad
1478 %eh = landingpad { ptr, i32 } cleanup
1479 call void @destructor()
1480 resume { ptr, i32 } %eh
1483 %c1 = call i1 @cond()
1484 br i1 %c1, label %if.then1, label %if.end
1487 invoke void @maybe_throw() to label %invoke.cont2 unwind label %lpad
1490 %deadphi0 = phi i32 [ 0, %if.then0 ]
1494 %deadphi2 = phi i32 [ 0, %if.then1 ]
1498 call void @sideeffect()
1502 ; landingpad has PHI nodes, and out of three invokes, only two have compatible incoming values.
1503 define void @t23_phi_in_landingpad_compatible_incoming_values() personality ptr @__gxx_personality_v0 {
1504 ; CHECK-LABEL: define void @t23_phi_in_landingpad_compatible_incoming_values() personality ptr @__gxx_personality_v0 {
1505 ; CHECK-NEXT: [[ENTRY:.*:]]
1506 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1507 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE0:.*]]
1508 ; CHECK: [[LPAD:.*]]:
1509 ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, %[[IF_THEN2:.*]] ], [ 0, %[[IF_THEN1_INVOKE]] ]
1510 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1511 ; CHECK-NEXT: cleanup
1512 ; CHECK-NEXT: call void @consume(i32 [[PHI]])
1513 ; CHECK-NEXT: call void @destructor()
1514 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1515 ; CHECK: [[IF_ELSE0]]:
1516 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1517 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_ELSE1:.*]]
1518 ; CHECK: [[IF_THEN1_INVOKE]]:
1519 ; CHECK-NEXT: invoke void @simple_throw()
1520 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
1521 ; CHECK: [[IF_THEN1_CONT]]:
1522 ; CHECK-NEXT: unreachable
1523 ; CHECK: [[IF_ELSE1]]:
1524 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
1525 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN2]], label %[[IF_END:.*]]
1526 ; CHECK: [[IF_THEN2]]:
1527 ; CHECK-NEXT: invoke void @simple_throw()
1528 ; CHECK-NEXT: to label %[[INVOKE_CONT3:.*]] unwind label %[[LPAD]]
1529 ; CHECK: [[INVOKE_CONT3]]:
1530 ; CHECK-NEXT: unreachable
1531 ; CHECK: [[IF_END]]:
1532 ; CHECK-NEXT: call void @sideeffect()
1533 ; CHECK-NEXT: ret void
1536 %c0 = call i1 @cond()
1537 br i1 %c0, label %if.then0, label %if.else0
1540 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
1546 %phi = phi i32 [ 0, %if.then0 ], [ 0, %if.then1 ], [ -1, %if.then2 ]
1547 %eh = landingpad { ptr, i32 } cleanup
1548 call void @consume(i32 %phi)
1549 call void @destructor()
1550 resume { ptr, i32 } %eh
1553 %c1 = call i1 @cond()
1554 br i1 %c1, label %if.then1, label %if.else1
1557 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
1563 %c2 = call i1 @cond()
1564 br i1 %c2, label %if.then2, label %if.end
1567 invoke void @simple_throw() to label %invoke.cont3 unwind label %lpad
1573 call void @sideeffect()
1577 ; landingpad has two PHI nodes, but depending on which PHI you look,
1578 ; the invoke sets would be different, so we can't merge invokes here.
1579 define void @t24_phi_in_landingpad_semi_compatible_incoming_values() personality ptr @__gxx_personality_v0 {
1580 ; CHECK-LABEL: define void @t24_phi_in_landingpad_semi_compatible_incoming_values() personality ptr @__gxx_personality_v0 {
1581 ; CHECK-NEXT: [[ENTRY:.*:]]
1582 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1583 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE0:.*]]
1584 ; CHECK: [[IF_THEN0]]:
1585 ; CHECK-NEXT: invoke void @simple_throw()
1586 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
1587 ; CHECK: [[INVOKE_CONT0]]:
1588 ; CHECK-NEXT: unreachable
1590 ; CHECK-NEXT: [[PHI0:%.*]] = phi i32 [ 0, %[[IF_THEN0]] ], [ 0, %[[IF_THEN1:.*]] ], [ -1, %[[IF_THEN2:.*]] ]
1591 ; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ 0, %[[IF_THEN0]] ], [ 1, %[[IF_THEN1]] ], [ 1, %[[IF_THEN2]] ]
1592 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1593 ; CHECK-NEXT: cleanup
1594 ; CHECK-NEXT: call void @consume(i32 [[PHI0]])
1595 ; CHECK-NEXT: call void @consume(i32 [[PHI1]])
1596 ; CHECK-NEXT: call void @destructor()
1597 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1598 ; CHECK: [[IF_ELSE0]]:
1599 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1600 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1]], label %[[IF_ELSE1:.*]]
1601 ; CHECK: [[IF_THEN1]]:
1602 ; CHECK-NEXT: invoke void @simple_throw()
1603 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
1604 ; CHECK: [[INVOKE_CONT2]]:
1605 ; CHECK-NEXT: unreachable
1606 ; CHECK: [[IF_ELSE1]]:
1607 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
1608 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN2]], label %[[IF_END:.*]]
1609 ; CHECK: [[IF_THEN2]]:
1610 ; CHECK-NEXT: invoke void @simple_throw()
1611 ; CHECK-NEXT: to label %[[INVOKE_CONT3:.*]] unwind label %[[LPAD]]
1612 ; CHECK: [[INVOKE_CONT3]]:
1613 ; CHECK-NEXT: unreachable
1614 ; CHECK: [[IF_END]]:
1615 ; CHECK-NEXT: call void @sideeffect()
1616 ; CHECK-NEXT: ret void
1619 %c0 = call i1 @cond()
1620 br i1 %c0, label %if.then0, label %if.else0
1623 invoke void @simple_throw() to label %invoke.cont0 unwind label %lpad
1629 %phi0 = phi i32 [ 0, %if.then0 ], [ 0, %if.then1 ], [ -1, %if.then2 ]
1630 %phi1= phi i32 [ 0, %if.then0 ], [ 1, %if.then1 ], [ 1, %if.then2 ]
1631 %eh = landingpad { ptr, i32 } cleanup
1632 call void @consume(i32 %phi0)
1633 call void @consume(i32 %phi1)
1634 call void @destructor()
1635 resume { ptr, i32 } %eh
1638 %c1 = call i1 @cond()
1639 br i1 %c1, label %if.then1, label %if.else1
1642 invoke void @simple_throw() to label %invoke.cont2 unwind label %lpad
1648 %c2 = call i1 @cond()
1649 br i1 %c2, label %if.then2, label %if.end
1652 invoke void @simple_throw() to label %invoke.cont3 unwind label %lpad
1658 call void @sideeffect()
1662 ; The normal destinations are shared, but the incoming values are incompatible.
1663 define void @t25_incompatible_phis_in_normal_destination() personality ptr @__gxx_personality_v0 {
1664 ; CHECK-LABEL: define void @t25_incompatible_phis_in_normal_destination() personality ptr @__gxx_personality_v0 {
1665 ; CHECK-NEXT: [[ENTRY:.*:]]
1666 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1667 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
1668 ; CHECK: [[IF_THEN0]]:
1669 ; CHECK-NEXT: invoke void @maybe_throw()
1670 ; CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
1671 ; CHECK: [[INVOKE_CONT]]:
1672 ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[IF_THEN0]] ], [ -1, %[[IF_THEN1:.*]] ]
1673 ; CHECK-NEXT: call void @consume(i32 [[PHI]])
1674 ; CHECK-NEXT: call void @sideeffect()
1675 ; CHECK-NEXT: unreachable
1677 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1678 ; CHECK-NEXT: cleanup
1679 ; CHECK-NEXT: call void @destructor()
1680 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1681 ; CHECK: [[IF_ELSE]]:
1682 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1683 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1]], label %[[IF_END:.*]]
1684 ; CHECK: [[IF_THEN1]]:
1685 ; CHECK-NEXT: invoke void @maybe_throw()
1686 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
1687 ; CHECK: [[IF_END]]:
1688 ; CHECK-NEXT: call void @sideeffect()
1689 ; CHECK-NEXT: ret void
1692 %c0 = call i1 @cond()
1693 br i1 %c0, label %if.then0, label %if.else
1696 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
1699 %phi = phi i32 [ 0, %if.then0 ], [ -1, %if.then1 ]
1700 call void @consume(i32 %phi)
1701 call void @sideeffect()
1705 %eh = landingpad { ptr, i32 } cleanup
1706 call void @destructor()
1707 resume { ptr, i32 } %eh
1710 %c1 = call i1 @cond()
1711 br i1 %c1, label %if.then1, label %if.end
1714 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
1717 call void @sideeffect()
1721 ; shared normal destination has PHI nodes, and out of three invokes, only two have compatible incoming values.
1722 define void @t26_phi_in_normal_dest_compatible_incoming_values() personality ptr @__gxx_personality_v0 {
1723 ; CHECK-LABEL: define void @t26_phi_in_normal_dest_compatible_incoming_values() personality ptr @__gxx_personality_v0 {
1724 ; CHECK-NEXT: [[ENTRY:.*:]]
1725 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1726 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE0:.*]]
1727 ; CHECK: [[INVOKE_CONT:.*]]:
1728 ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, %[[IF_THEN2:.*]] ], [ 0, %[[IF_THEN1_INVOKE]] ]
1729 ; CHECK-NEXT: call void @consume(i32 [[PHI]])
1730 ; CHECK-NEXT: call void @sideeffect()
1731 ; CHECK-NEXT: unreachable
1732 ; CHECK: [[LPAD:.*]]:
1733 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1734 ; CHECK-NEXT: cleanup
1735 ; CHECK-NEXT: call void @destructor()
1736 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1737 ; CHECK: [[IF_ELSE0]]:
1738 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1739 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_ELSE1:.*]]
1740 ; CHECK: [[IF_THEN1_INVOKE]]:
1741 ; CHECK-NEXT: invoke void @maybe_throw()
1742 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
1743 ; CHECK: [[IF_ELSE1]]:
1744 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
1745 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN2]], label %[[IF_END:.*]]
1746 ; CHECK: [[IF_THEN2]]:
1747 ; CHECK-NEXT: invoke void @maybe_throw()
1748 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
1749 ; CHECK: [[IF_END]]:
1750 ; CHECK-NEXT: call void @sideeffect()
1751 ; CHECK-NEXT: ret void
1754 %c0 = call i1 @cond()
1755 br i1 %c0, label %if.then0, label %if.else0
1758 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
1761 %phi = phi i32 [ 0, %if.then0 ], [ 0, %if.then1 ], [ -1, %if.then2 ]
1762 call void @consume(i32 %phi)
1763 call void @sideeffect()
1767 %eh = landingpad { ptr, i32 } cleanup
1768 call void @destructor()
1769 resume { ptr, i32 } %eh
1772 %c1 = call i1 @cond()
1773 br i1 %c1, label %if.then1, label %if.else1
1776 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
1779 %c2 = call i1 @cond()
1780 br i1 %c2, label %if.then2, label %if.end
1783 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
1786 call void @sideeffect()
1790 ; Invokes return values, but they are unused.
1791 define void @t27_invoke_ret_value_is_used() personality ptr @__gxx_personality_v0 {
1792 ; CHECK-LABEL: define void @t27_invoke_ret_value_is_used() personality ptr @__gxx_personality_v0 {
1793 ; CHECK-NEXT: [[ENTRY:.*:]]
1794 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1795 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1796 ; CHECK: [[INVOKE_CONT:.*]]:
1797 ; CHECK-NEXT: call void @sideeffect()
1798 ; CHECK-NEXT: unreachable
1799 ; CHECK: [[LPAD:.*]]:
1800 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1801 ; CHECK-NEXT: cleanup
1802 ; CHECK-NEXT: call void @destructor()
1803 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1804 ; CHECK: [[IF_ELSE]]:
1805 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1806 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1807 ; CHECK: [[IF_THEN1_INVOKE]]:
1808 ; CHECK-NEXT: [[TMP0:%.*]] = invoke i32 @returning_maybe_throw()
1809 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
1810 ; CHECK: [[IF_END]]:
1811 ; CHECK-NEXT: call void @sideeffect()
1812 ; CHECK-NEXT: ret void
1815 %c0 = call i1 @cond()
1816 br i1 %c0, label %if.then0, label %if.else
1819 %v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
1822 call void @sideeffect()
1826 %eh = landingpad { ptr, i32 } cleanup
1827 call void @destructor()
1828 resume { ptr, i32 } %eh
1831 %c1 = call i1 @cond()
1832 br i1 %c1, label %if.then1, label %if.end
1835 %v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
1838 call void @sideeffect()
1842 ; Invokes return values, and they are used in a phi node, making the incoming values incompatible.
1843 define void @t28_invoke_ret_value_is_used_in_phi_node() personality ptr @__gxx_personality_v0 {
1844 ; CHECK-LABEL: define void @t28_invoke_ret_value_is_used_in_phi_node() personality ptr @__gxx_personality_v0 {
1845 ; CHECK-NEXT: [[ENTRY:.*:]]
1846 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1847 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
1848 ; CHECK: [[INVOKE_CONT:.*]]:
1849 ; CHECK-NEXT: call void @consume(i32 [[TMP0:%.*]])
1850 ; CHECK-NEXT: call void @sideeffect()
1851 ; CHECK-NEXT: unreachable
1852 ; CHECK: [[LPAD:.*]]:
1853 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1854 ; CHECK-NEXT: cleanup
1855 ; CHECK-NEXT: call void @destructor()
1856 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1857 ; CHECK: [[IF_ELSE]]:
1858 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1859 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
1860 ; CHECK: [[IF_THEN1_INVOKE]]:
1861 ; CHECK-NEXT: [[TMP0]] = invoke i32 @returning_maybe_throw()
1862 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
1863 ; CHECK: [[IF_END]]:
1864 ; CHECK-NEXT: call void @sideeffect()
1865 ; CHECK-NEXT: ret void
1868 %c0 = call i1 @cond()
1869 br i1 %c0, label %if.then0, label %if.else
1872 %v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
1875 %phi = phi i32 [ %v0, %if.then0 ], [ %v1, %if.then1 ]
1876 call void @consume(i32 %phi)
1877 call void @sideeffect()
1881 %eh = landingpad { ptr, i32 } cleanup
1882 call void @destructor()
1883 resume { ptr, i32 } %eh
1886 %c1 = call i1 @cond()
1887 br i1 %c1, label %if.then1, label %if.end
1890 %v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
1893 call void @sideeffect()
1897 ; out of three invokes, two share normal destination and another one has unreachable destination
1898 define void @t29_common_normal_destination_and_unreachable_normal_destination() personality ptr @__gxx_personality_v0 {
1899 ; CHECK-LABEL: define void @t29_common_normal_destination_and_unreachable_normal_destination() personality ptr @__gxx_personality_v0 {
1900 ; CHECK-NEXT: [[ENTRY:.*:]]
1901 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1902 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE0:.*]]
1903 ; CHECK: [[INVOKE_CONT0:.*]]:
1904 ; CHECK-NEXT: call void @sideeffect()
1905 ; CHECK-NEXT: unreachable
1906 ; CHECK: [[LPAD:.*]]:
1907 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1908 ; CHECK-NEXT: cleanup
1909 ; CHECK-NEXT: call void @destructor()
1910 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1911 ; CHECK: [[IF_ELSE0]]:
1912 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1913 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_ELSE1:.*]]
1914 ; CHECK: [[IF_THEN1_INVOKE]]:
1915 ; CHECK-NEXT: invoke void @maybe_throw()
1916 ; CHECK-NEXT: to label %[[INVOKE_CONT0]] unwind label %[[LPAD]]
1917 ; CHECK: [[IF_ELSE1]]:
1918 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
1919 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN2:.*]], label %[[IF_END:.*]]
1920 ; CHECK: [[IF_THEN2]]:
1921 ; CHECK-NEXT: invoke void @maybe_throw()
1922 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
1923 ; CHECK: [[INVOKE_CONT2]]:
1924 ; CHECK-NEXT: unreachable
1925 ; CHECK: [[IF_END]]:
1926 ; CHECK-NEXT: call void @sideeffect()
1927 ; CHECK-NEXT: ret void
1930 %c0 = call i1 @cond()
1931 br i1 %c0, label %if.then0, label %if.else0
1934 invoke void @maybe_throw() to label %invoke.cont0 unwind label %lpad
1937 call void @sideeffect()
1941 %eh = landingpad { ptr, i32 } cleanup
1942 call void @destructor()
1943 resume { ptr, i32 } %eh
1946 %c1 = call i1 @cond()
1947 br i1 %c1, label %if.then1, label %if.else1
1950 invoke void @maybe_throw() to label %invoke.cont0 unwind label %lpad
1953 %c2 = call i1 @cond()
1954 br i1 %c2, label %if.then2, label %if.end
1957 invoke void @maybe_throw() to label %invoke.cont2 unwind label %lpad
1963 call void @sideeffect()
1967 ; normal destinations are not unreachable and different but could be merged
1968 define void @t30_completely_different_normal_dests() personality ptr @__gxx_personality_v0 {
1969 ; CHECK-LABEL: define void @t30_completely_different_normal_dests() personality ptr @__gxx_personality_v0 {
1970 ; CHECK-NEXT: [[ENTRY:.*:]]
1971 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
1972 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
1973 ; CHECK: [[IF_THEN0]]:
1974 ; CHECK-NEXT: invoke void @maybe_throw()
1975 ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]]
1976 ; CHECK: [[INVOKE_CONT0]]:
1977 ; CHECK-NEXT: call void @sideeffect()
1978 ; CHECK-NEXT: unreachable
1980 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
1981 ; CHECK-NEXT: cleanup
1982 ; CHECK-NEXT: call void @destructor()
1983 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
1984 ; CHECK: [[IF_ELSE]]:
1985 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
1986 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]]
1987 ; CHECK: [[IF_THEN1]]:
1988 ; CHECK-NEXT: invoke void @maybe_throw()
1989 ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]]
1990 ; CHECK: [[INVOKE_CONT2]]:
1991 ; CHECK-NEXT: call void @sideeffect()
1992 ; CHECK-NEXT: unreachable
1993 ; CHECK: [[IF_END]]:
1994 ; CHECK-NEXT: call void @sideeffect()
1995 ; CHECK-NEXT: ret void
1998 %c0 = call i1 @cond()
1999 br i1 %c0, label %if.then0, label %if.else
2002 invoke void @maybe_throw() to label %invoke.cont0 unwind label %lpad
2005 call void @sideeffect()
2009 %eh = landingpad { ptr, i32 } cleanup
2010 call void @destructor()
2011 resume { ptr, i32 } %eh
2014 %c1 = call i1 @cond()
2015 br i1 %c1, label %if.then1, label %if.end
2018 invoke void @maybe_throw() to label %invoke.cont2 unwind label %lpad
2021 call void @sideeffect()
2025 call void @sideeffect()
2029 ; Even though the normal destinations are unreachable,
2030 ; they may have (dead) PHI nodes with incompatible incoming values,
2031 ; so we must cleanup them.
2032 define void @t31_incompatible_dead_phi_in_normal_dest() personality ptr @__gxx_personality_v0 {
2033 ; CHECK-LABEL: define void @t31_incompatible_dead_phi_in_normal_dest() personality ptr @__gxx_personality_v0 {
2034 ; CHECK-NEXT: [[ENTRY:.*:]]
2035 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2036 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
2037 ; CHECK: [[LPAD:.*]]:
2038 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2039 ; CHECK-NEXT: cleanup
2040 ; CHECK-NEXT: call void @destructor()
2041 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2042 ; CHECK: [[IF_ELSE]]:
2043 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2044 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
2045 ; CHECK: [[IF_THEN1_INVOKE]]:
2046 ; CHECK-NEXT: invoke void @maybe_throw()
2047 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
2048 ; CHECK: [[IF_THEN1_CONT]]:
2049 ; CHECK-NEXT: unreachable
2050 ; CHECK: [[IF_END]]:
2051 ; CHECK-NEXT: call void @sideeffect()
2052 ; CHECK-NEXT: ret void
2055 %c0 = call i1 @cond()
2056 br i1 %c0, label %if.then0, label %if.else
2059 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
2062 %eh = landingpad { ptr, i32 } cleanup
2063 call void @destructor()
2064 resume { ptr, i32 } %eh
2067 %c1 = call i1 @cond()
2068 br i1 %c1, label %if.then1, label %if.end
2071 invoke void @maybe_throw() to label %invoke.cont unwind label %lpad
2074 %deadphi0 = phi i32 [ 0, %if.then0 ], [ -1, %if.then1 ]
2078 call void @sideeffect()
2082 ; Invokes return values, and they are used in a phi node, making the incoming values incompatible,
2083 ; second phi has compatible incoming values
2084 define void @t32_invoke_ret_value_is_used_in_phi_node_other_phi_is_fine() personality ptr @__gxx_personality_v0 {
2085 ; CHECK-LABEL: define void @t32_invoke_ret_value_is_used_in_phi_node_other_phi_is_fine() personality ptr @__gxx_personality_v0 {
2086 ; CHECK-NEXT: [[ENTRY:.*:]]
2087 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2088 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
2089 ; CHECK: [[INVOKE_CONT:.*]]:
2090 ; CHECK-NEXT: call void @consume(i32 [[TMP0:%.*]])
2091 ; CHECK-NEXT: call void @consume(i32 0)
2092 ; CHECK-NEXT: call void @sideeffect()
2093 ; CHECK-NEXT: unreachable
2094 ; CHECK: [[LPAD:.*]]:
2095 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2096 ; CHECK-NEXT: cleanup
2097 ; CHECK-NEXT: call void @destructor()
2098 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2099 ; CHECK: [[IF_ELSE]]:
2100 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2101 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
2102 ; CHECK: [[IF_THEN1_INVOKE]]:
2103 ; CHECK-NEXT: [[TMP0]] = invoke i32 @returning_maybe_throw()
2104 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
2105 ; CHECK: [[IF_END]]:
2106 ; CHECK-NEXT: call void @sideeffect()
2107 ; CHECK-NEXT: ret void
2110 %c0 = call i1 @cond()
2111 br i1 %c0, label %if.then0, label %if.else
2114 %v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
2117 %phi0 = phi i32 [ %v0, %if.then0 ], [ %v1, %if.then1 ]
2118 %phi1 = phi i32 [ 0, %if.then0 ], [ 0, %if.then1 ]
2119 call void @consume(i32 %phi0)
2120 call void @consume(i32 %phi1)
2121 call void @sideeffect()
2125 %eh = landingpad { ptr, i32 } cleanup
2126 call void @destructor()
2127 resume { ptr, i32 } %eh
2130 %c1 = call i1 @cond()
2131 br i1 %c1, label %if.then1, label %if.end
2134 %v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
2137 call void @sideeffect()
2141 ; Invokes return values, and they are used in a phi node, making the incoming values incompatible,
2142 ; second phi has incompatible incoming values.
2143 define void @t33_invoke_ret_value_is_used_in_phi_node_other_phi_is_bad() personality ptr @__gxx_personality_v0 {
2144 ; CHECK-LABEL: define void @t33_invoke_ret_value_is_used_in_phi_node_other_phi_is_bad() personality ptr @__gxx_personality_v0 {
2145 ; CHECK-NEXT: [[ENTRY:.*:]]
2146 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2147 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
2148 ; CHECK: [[IF_THEN0]]:
2149 ; CHECK-NEXT: [[V0:%.*]] = invoke i32 @returning_maybe_throw()
2150 ; CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
2151 ; CHECK: [[INVOKE_CONT]]:
2152 ; CHECK-NEXT: [[PHI0:%.*]] = phi i32 [ [[V0]], %[[IF_THEN0]] ], [ [[V1:%.*]], %[[IF_THEN1:.*]] ]
2153 ; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ 0, %[[IF_THEN0]] ], [ -1, %[[IF_THEN1]] ]
2154 ; CHECK-NEXT: call void @consume(i32 [[PHI0]])
2155 ; CHECK-NEXT: call void @consume(i32 [[PHI1]])
2156 ; CHECK-NEXT: call void @sideeffect()
2157 ; CHECK-NEXT: unreachable
2159 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2160 ; CHECK-NEXT: cleanup
2161 ; CHECK-NEXT: call void @destructor()
2162 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2163 ; CHECK: [[IF_ELSE]]:
2164 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2165 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1]], label %[[IF_END:.*]]
2166 ; CHECK: [[IF_THEN1]]:
2167 ; CHECK-NEXT: [[V1]] = invoke i32 @returning_maybe_throw()
2168 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
2169 ; CHECK: [[IF_END]]:
2170 ; CHECK-NEXT: call void @sideeffect()
2171 ; CHECK-NEXT: ret void
2174 %c0 = call i1 @cond()
2175 br i1 %c0, label %if.then0, label %if.else
2178 %v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
2181 %phi0 = phi i32 [ %v0, %if.then0 ], [ %v1, %if.then1 ]
2182 %phi1 = phi i32 [ 0, %if.then0 ], [ -1, %if.then1 ]
2183 call void @consume(i32 %phi0)
2184 call void @consume(i32 %phi1)
2185 call void @sideeffect()
2189 %eh = landingpad { ptr, i32 } cleanup
2190 call void @destructor()
2191 resume { ptr, i32 } %eh
2194 %c1 = call i1 @cond()
2195 br i1 %c1, label %if.then1, label %if.end
2198 %v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
2201 call void @sideeffect()
2205 ; Invokes return values, and they are used in a phi node, but when coming from different invokes,
2206 ; the incoming value isn't always the invoke, which is not okay.
2207 define void @t34_invoke_ret_value_maybe_incompatibly_used_in_phi_node() personality ptr @__gxx_personality_v0 {
2208 ; CHECK-LABEL: define void @t34_invoke_ret_value_maybe_incompatibly_used_in_phi_node() personality ptr @__gxx_personality_v0 {
2209 ; CHECK-NEXT: [[ENTRY:.*:]]
2210 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2211 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]]
2212 ; CHECK: [[IF_THEN0]]:
2213 ; CHECK-NEXT: [[V0:%.*]] = invoke i32 @returning_maybe_throw()
2214 ; CHECK-NEXT: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
2215 ; CHECK: [[INVOKE_CONT]]:
2216 ; CHECK-NEXT: [[PHI0:%.*]] = phi i32 [ [[V0]], %[[IF_THEN0]] ], [ 0, %[[IF_THEN1:.*]] ]
2217 ; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ 0, %[[IF_THEN0]] ], [ [[V1:%.*]], %[[IF_THEN1]] ]
2218 ; CHECK-NEXT: call void @consume(i32 [[PHI0]])
2219 ; CHECK-NEXT: call void @consume(i32 [[PHI1]])
2220 ; CHECK-NEXT: call void @sideeffect()
2221 ; CHECK-NEXT: unreachable
2223 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2224 ; CHECK-NEXT: cleanup
2225 ; CHECK-NEXT: call void @destructor()
2226 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2227 ; CHECK: [[IF_ELSE]]:
2228 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2229 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1]], label %[[IF_END:.*]]
2230 ; CHECK: [[IF_THEN1]]:
2231 ; CHECK-NEXT: [[V1]] = invoke i32 @returning_maybe_throw()
2232 ; CHECK-NEXT: to label %[[INVOKE_CONT]] unwind label %[[LPAD]]
2233 ; CHECK: [[IF_END]]:
2234 ; CHECK-NEXT: call void @sideeffect()
2235 ; CHECK-NEXT: ret void
2238 %c0 = call i1 @cond()
2239 br i1 %c0, label %if.then0, label %if.else
2242 %v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
2245 %phi0 = phi i32 [ %v0, %if.then0 ], [ 0, %if.then1 ]
2246 %phi1 = phi i32 [ 0, %if.then0 ], [ %v1, %if.then1 ]
2247 call void @consume(i32 %phi0)
2248 call void @consume(i32 %phi1)
2249 call void @sideeffect()
2253 %eh = landingpad { ptr, i32 } cleanup
2254 call void @destructor()
2255 resume { ptr, i32 } %eh
2258 %c1 = call i1 @cond()
2259 br i1 %c1, label %if.then1, label %if.end
2262 %v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad
2265 call void @sideeffect()
2269 ; Two mergeable indirect calls, with identical callees.
2270 define void @t35_identical_indirect_callees(ptr %callee) personality ptr @__gxx_personality_v0 {
2271 ; CHECK-LABEL: define void @t35_identical_indirect_callees(
2272 ; CHECK-SAME: ptr [[CALLEE:%.*]]) personality ptr @__gxx_personality_v0 {
2273 ; CHECK-NEXT: [[ENTRY:.*:]]
2274 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2275 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
2276 ; CHECK: [[LPAD:.*]]:
2277 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2278 ; CHECK-NEXT: cleanup
2279 ; CHECK-NEXT: call void @destructor()
2280 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2281 ; CHECK: [[IF_ELSE]]:
2282 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2283 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
2284 ; CHECK: [[IF_THEN1_INVOKE]]:
2285 ; CHECK-NEXT: invoke void [[CALLEE]]()
2286 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
2287 ; CHECK: [[IF_THEN1_CONT]]:
2288 ; CHECK-NEXT: unreachable
2289 ; CHECK: [[IF_END]]:
2290 ; CHECK-NEXT: call void @sideeffect()
2291 ; CHECK-NEXT: ret void
2294 %c0 = call i1 @cond()
2295 br i1 %c0, label %if.then0, label %if.else
2298 invoke void %callee() to label %invoke.cont0 unwind label %lpad
2304 %eh = landingpad { ptr, i32 } cleanup
2305 call void @destructor()
2306 resume { ptr, i32 } %eh
2309 %c1 = call i1 @cond()
2310 br i1 %c1, label %if.then1, label %if.end
2313 invoke void %callee() to label %invoke.cont2 unwind label %lpad
2319 call void @sideeffect()
2323 ; Two mergeable indirect calls, with different callees.
2324 define void @t36_different_indirect_callees(ptr %callee0, ptr %callee1) personality ptr @__gxx_personality_v0 {
2325 ; CHECK-LABEL: define void @t36_different_indirect_callees(
2326 ; CHECK-SAME: ptr [[CALLEE0:%.*]], ptr [[CALLEE1:%.*]]) personality ptr @__gxx_personality_v0 {
2327 ; CHECK-NEXT: [[ENTRY:.*]]:
2328 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2329 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
2330 ; CHECK: [[LPAD:.*]]:
2331 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2332 ; CHECK-NEXT: cleanup
2333 ; CHECK-NEXT: call void @destructor()
2334 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2335 ; CHECK: [[IF_ELSE]]:
2336 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2337 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
2338 ; CHECK: [[IF_THEN1_INVOKE]]:
2339 ; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ [[CALLEE1]], %[[IF_ELSE]] ], [ [[CALLEE0]], %[[ENTRY]] ]
2340 ; CHECK-NEXT: invoke void [[TMP0]]()
2341 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
2342 ; CHECK: [[IF_THEN1_CONT]]:
2343 ; CHECK-NEXT: unreachable
2344 ; CHECK: [[IF_END]]:
2345 ; CHECK-NEXT: call void @sideeffect()
2346 ; CHECK-NEXT: ret void
2349 %c0 = call i1 @cond()
2350 br i1 %c0, label %if.then0, label %if.else
2353 invoke void %callee0() to label %invoke.cont0 unwind label %lpad
2359 %eh = landingpad { ptr, i32 } cleanup
2360 call void @destructor()
2361 resume { ptr, i32 } %eh
2364 %c1 = call i1 @cond()
2365 br i1 %c1, label %if.then1, label %if.end
2368 invoke void %callee1() to label %invoke.cont2 unwind label %lpad
2374 call void @sideeffect()
2378 ; Don't merge direct invoke with indirect ones.
2379 define void @t37_three_invokes_two_indirect_one_direct(ptr %callee) personality ptr @__gxx_personality_v0 {
2380 ; CHECK-LABEL: define void @t37_three_invokes_two_indirect_one_direct(
2381 ; CHECK-SAME: ptr [[CALLEE:%.*]]) personality ptr @__gxx_personality_v0 {
2382 ; CHECK-NEXT: [[ENTRY:.*:]]
2383 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2384 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE0:.*]]
2385 ; CHECK: [[LPAD:.*]]:
2386 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2387 ; CHECK-NEXT: cleanup
2388 ; CHECK-NEXT: call void @destructor()
2389 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2390 ; CHECK: [[IF_ELSE0]]:
2391 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2392 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_ELSE1:.*]]
2393 ; CHECK: [[IF_THEN1_INVOKE]]:
2394 ; CHECK-NEXT: invoke void [[CALLEE]]()
2395 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
2396 ; CHECK: [[IF_THEN1_CONT]]:
2397 ; CHECK-NEXT: unreachable
2398 ; CHECK: [[IF_ELSE1]]:
2399 ; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
2400 ; CHECK-NEXT: br i1 [[C2]], label %[[IF_THEN2:.*]], label %[[IF_END:.*]]
2401 ; CHECK: [[IF_THEN2]]:
2402 ; CHECK-NEXT: invoke void @simple_throw()
2403 ; CHECK-NEXT: to label %[[INVOKE_CONT3:.*]] unwind label %[[LPAD]]
2404 ; CHECK: [[INVOKE_CONT3]]:
2405 ; CHECK-NEXT: unreachable
2406 ; CHECK: [[IF_END]]:
2407 ; CHECK-NEXT: call void @sideeffect()
2408 ; CHECK-NEXT: ret void
2411 %c0 = call i1 @cond()
2412 br i1 %c0, label %if.then0, label %if.else0
2415 invoke void %callee() to label %invoke.cont0 unwind label %lpad
2421 %eh = landingpad { ptr, i32 } cleanup
2422 call void @destructor()
2423 resume { ptr, i32 } %eh
2426 %c1 = call i1 @cond()
2427 br i1 %c1, label %if.then1, label %if.else1
2430 invoke void %callee() to label %invoke.cont2 unwind label %lpad
2436 %c2 = call i1 @cond()
2437 br i1 %c2, label %if.then2, label %if.end
2440 invoke void @simple_throw() to label %invoke.cont3 unwind label %lpad
2446 call void @sideeffect()
2450 ; For indirect invokes, different arguments are fine.
2451 define void @t38_different_arguments_and_operand_bundes_are_fine(ptr %callee0, ptr %callee1) personality ptr @__gxx_personality_v0 {
2452 ; CHECK-LABEL: define void @t38_different_arguments_and_operand_bundes_are_fine(
2453 ; CHECK-SAME: ptr [[CALLEE0:%.*]], ptr [[CALLEE1:%.*]]) personality ptr @__gxx_personality_v0 {
2454 ; CHECK-NEXT: [[ENTRY:.*]]:
2455 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2456 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
2457 ; CHECK: [[LPAD:.*]]:
2458 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2459 ; CHECK-NEXT: cleanup
2460 ; CHECK-NEXT: call void @destructor()
2461 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2462 ; CHECK: [[IF_ELSE]]:
2463 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2464 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
2465 ; CHECK: [[IF_THEN1_INVOKE]]:
2466 ; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, %[[IF_ELSE]] ], [ 0, %[[ENTRY]] ]
2467 ; CHECK-NEXT: [[TMP1:%.*]] = phi ptr [ [[CALLEE1]], %[[IF_ELSE]] ], [ [[CALLEE0]], %[[ENTRY]] ]
2468 ; CHECK-NEXT: invoke void [[TMP1]](i32 [[TMP0]])
2469 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
2470 ; CHECK: [[IF_THEN1_CONT]]:
2471 ; CHECK-NEXT: unreachable
2472 ; CHECK: [[IF_END]]:
2473 ; CHECK-NEXT: call void @sideeffect()
2474 ; CHECK-NEXT: ret void
2477 %c0 = call i1 @cond()
2478 br i1 %c0, label %if.then0, label %if.else
2481 invoke void %callee0(i32 0) to label %invoke.cont0 unwind label %lpad
2487 %eh = landingpad { ptr, i32 } cleanup
2488 call void @destructor()
2489 resume { ptr, i32 } %eh
2492 %c1 = call i1 @cond()
2493 br i1 %c1, label %if.then1, label %if.end
2496 invoke void %callee1(i32 42) to label %invoke.cont2 unwind label %lpad
2502 call void @sideeffect()
2506 ; For indirect invokes, different operand bundle arguments are fine.
2507 define void @t39_different_arguments_and_operand_bundes_are_fine(ptr %callee0, ptr %callee1, i32 %a, i32 %b) personality ptr @__gxx_personality_v0 {
2508 ; CHECK-LABEL: define void @t39_different_arguments_and_operand_bundes_are_fine(
2509 ; CHECK-SAME: ptr [[CALLEE0:%.*]], ptr [[CALLEE1:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) personality ptr @__gxx_personality_v0 {
2510 ; CHECK-NEXT: [[ENTRY:.*]]:
2511 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2512 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
2513 ; CHECK: [[LPAD:.*]]:
2514 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2515 ; CHECK-NEXT: cleanup
2516 ; CHECK-NEXT: call void @destructor()
2517 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2518 ; CHECK: [[IF_ELSE]]:
2519 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2520 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
2521 ; CHECK: [[IF_THEN1_INVOKE]]:
2522 ; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[B]], %[[IF_ELSE]] ], [ [[A]], %[[ENTRY]] ]
2523 ; CHECK-NEXT: [[TMP1:%.*]] = phi ptr [ [[CALLEE1]], %[[IF_ELSE]] ], [ [[CALLEE0]], %[[ENTRY]] ]
2524 ; CHECK-NEXT: invoke void [[TMP1]]() [ "abc"(i32 [[TMP0]]) ]
2525 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
2526 ; CHECK: [[IF_THEN1_CONT]]:
2527 ; CHECK-NEXT: unreachable
2528 ; CHECK: [[IF_END]]:
2529 ; CHECK-NEXT: call void @sideeffect()
2530 ; CHECK-NEXT: ret void
2533 %c0 = call i1 @cond()
2534 br i1 %c0, label %if.then0, label %if.else
2537 invoke void %callee0() [ "abc"(i32 %a) ] to label %invoke.cont0 unwind label %lpad
2543 %eh = landingpad { ptr, i32 } cleanup
2544 call void @destructor()
2545 resume { ptr, i32 } %eh
2548 %c1 = call i1 @cond()
2549 br i1 %c1, label %if.then1, label %if.end
2552 invoke void %callee1() [ "abc"(i32 %b) ] to label %invoke.cont2 unwind label %lpad
2558 call void @sideeffect()
2562 ; For indirect invokes, both different arguments and operand bundle arguments are fine.
2563 define void @t40_different_arguments_and_operand_bundes_are_fine(ptr %callee0, ptr %callee1, i32 %a, i32 %b) personality ptr @__gxx_personality_v0 {
2564 ; CHECK-LABEL: define void @t40_different_arguments_and_operand_bundes_are_fine(
2565 ; CHECK-SAME: ptr [[CALLEE0:%.*]], ptr [[CALLEE1:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) personality ptr @__gxx_personality_v0 {
2566 ; CHECK-NEXT: [[ENTRY:.*]]:
2567 ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
2568 ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN1_INVOKE:.*]], label %[[IF_ELSE:.*]]
2569 ; CHECK: [[LPAD:.*]]:
2570 ; CHECK-NEXT: [[EH:%.*]] = landingpad { ptr, i32 }
2571 ; CHECK-NEXT: cleanup
2572 ; CHECK-NEXT: call void @destructor()
2573 ; CHECK-NEXT: resume { ptr, i32 } [[EH]]
2574 ; CHECK: [[IF_ELSE]]:
2575 ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
2576 ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]]
2577 ; CHECK: [[IF_THEN1_INVOKE]]:
2578 ; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 42, %[[IF_ELSE]] ], [ 0, %[[ENTRY]] ]
2579 ; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[B]], %[[IF_ELSE]] ], [ [[A]], %[[ENTRY]] ]
2580 ; CHECK-NEXT: [[TMP2:%.*]] = phi ptr [ [[CALLEE1]], %[[IF_ELSE]] ], [ [[CALLEE0]], %[[ENTRY]] ]
2581 ; CHECK-NEXT: invoke void [[TMP2]](i32 [[TMP0]]) [ "abc"(i32 [[TMP1]]) ]
2582 ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]]
2583 ; CHECK: [[IF_THEN1_CONT]]:
2584 ; CHECK-NEXT: unreachable
2585 ; CHECK: [[IF_END]]:
2586 ; CHECK-NEXT: call void @sideeffect()
2587 ; CHECK-NEXT: ret void
2590 %c0 = call i1 @cond()
2591 br i1 %c0, label %if.then0, label %if.else
2594 invoke void %callee0(i32 0) [ "abc"(i32 %a) ] to label %invoke.cont0 unwind label %lpad
2600 %eh = landingpad { ptr, i32 } cleanup
2601 call void @destructor()
2602 resume { ptr, i32 } %eh
2605 %c1 = call i1 @cond()
2606 br i1 %c1, label %if.then1, label %if.end
2609 invoke void %callee1(i32 42) [ "abc"(i32 %b) ] to label %invoke.cont2 unwind label %lpad
2615 call void @sideeffect()
2619 define void @dont_merge_different_immargs(i1 %c1) gc "statepoint-example" personality ptr null {
2620 ; CHECK-LABEL: define void @dont_merge_different_immargs(
2621 ; CHECK-SAME: i1 [[C1:%.*]]) gc "statepoint-example" personality ptr null {
2622 ; CHECK-NEXT: br i1 [[C1]], label %[[IF:.*]], label %[[ELSE:.*]]
2624 ; CHECK-NEXT: [[T1:%.*]] = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 1, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2625 ; CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[LPAD:.*]]
2627 ; CHECK-NEXT: [[T2:%.*]] = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2628 ; CHECK-NEXT: to label %[[UNREACHABLE]] unwind label %[[LPAD]]
2629 ; CHECK: [[UNREACHABLE]]:
2630 ; CHECK-NEXT: unreachable
2632 ; CHECK-NEXT: [[T3:%.*]] = landingpad token
2633 ; CHECK-NEXT: cleanup
2634 ; CHECK-NEXT: ret void
2636 br i1 %c1, label %if, label %else
2639 %t1 = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 1, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2640 to label %unreachable unwind label %lpad
2643 %t2 = invoke token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (ptr addrspace(1))) null, i32 1, i32 0, ptr addrspace(1) null, i64 0, i64 0)
2644 to label %unreachable unwind label %lpad
2650 %t3 = landingpad token
2655 declare token @llvm.experimental.gc.statepoint.p0(i64 immarg, i32 immarg, ptr, i32 immarg, i32 immarg, ...)
2659 declare void @sideeffect()
2660 declare void @another_sideeffect()
2662 declare void @maybe_throw()
2664 declare void @simple_throw() noreturn
2665 declare void @another_simple_throw() noreturn
2667 declare void @simple_throw_taking_argument(i32) noreturn
2669 declare i32 @returning_maybe_throw()
2671 declare void @destructor()
2672 declare void @another_destructor()
2674 declare void @consume(i32)
2676 declare dso_local i32 @__gxx_personality_v0(...)
2678 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { noreturn }
2679 ; CHECK: attributes #[[ATTR1]] = { nomerge }
2680 ; CHECK: attributes #[[ATTR2]] = { memory(none) }
2681 ; CHECK: attributes #[[ATTR3]] = { strictfp }