• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -winehprepare -demote-catchswitch-only -wasmehprepare -S | FileCheck %s
2
3target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
4target triple = "wasm32-unknown-unknown"
5
6; CHECK: @__wasm_lpad_context = external global { i32, i8*, i32 }
7
8@_ZTIi = external constant i8*
9%struct.Temp = type { i8 }
10
11; A single 'catch (int)' clause.
12; A wasm.catch() call, wasm.lsda() call, and personality call to generate a
13; selector should all be genereated after the catchpad.
14;
15; void foo();
16; void test0() {
17;   try {
18;     foo();
19;   } catch (int) {
20;   }
21; }
22define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
23; CHECK-LABEL: @test0()
24entry:
25  invoke void @foo()
26          to label %try.cont unwind label %catch.dispatch
27
28catch.dispatch:                                   ; preds = %entry
29  %0 = catchswitch within none [label %catch.start] unwind to caller
30
31catch.start:                                      ; preds = %catch.dispatch
32  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
33  %2 = call i8* @llvm.wasm.get.exception(token %1)
34  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
35  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
36  %matches = icmp eq i32 %3, %4
37  br i1 %matches, label %catch, label %rethrow
38; CHECK: catch.start:
39; CHECK-NEXT:   %[[CATCHPAD:.*]] = catchpad
40; CHECK-NEXT:   %[[EXN:.*]] = call i8* @llvm.wasm.extract.exception()
41; CHECK-NEXT:   call void @llvm.wasm.landingpad.index(token %[[CATCHPAD]], i32 0)
42; CHECK-NEXT:   store i32 0, i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0)
43; CHECK-NEXT:   %[[LSDA:.*]] = call i8* @llvm.wasm.lsda()
44; CHECK-NEXT:   store i8* %[[LSDA]], i8** getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 1)
45; CHECK-NEXT:   call i32 @_Unwind_CallPersonality(i8* %[[EXN]]) {{.*}} [ "funclet"(token %[[CATCHPAD]]) ]
46; CHECK-NEXT:   %[[SELECTOR:.*]] = load i32, i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 2)
47; CHECK:   icmp eq i32 %[[SELECTOR]]
48
49catch:                                            ; preds = %catch.start
50  %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
51  call void @__cxa_end_catch() [ "funclet"(token %1) ]
52  catchret from %1 to label %try.cont
53; CHECK: catch:
54; CHECK-NEXT:  call i8* @__cxa_begin_catch(i8* %[[EXN]])
55
56rethrow:                                          ; preds = %catch.start
57  call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
58  unreachable
59
60try.cont:                                         ; preds = %entry, %catch
61  ret void
62}
63
64; Two try-catches.
65; For the catchpad with a single 'catch (...)', only a wasm.catch() call should
66; be generated after the catchpad; wasm.landingpad.index() and personality call
67; should NOT be generated. For the other catchpad, the argument of
68; wasm.landingpad.index() should be not 1 but 0.
69;
70; void foo();
71; void test1() {
72;   try {
73;     foo();
74;   } catch (...) {
75;   }
76;   try {
77;     foo();
78;   } catch (int) {
79;   }
80; }
81define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
82; CHECK-LABEL: @test1()
83entry:
84  invoke void @foo()
85          to label %try.cont unwind label %catch.dispatch
86
87catch.dispatch:                                   ; preds = %entry
88  %0 = catchswitch within none [label %catch.start] unwind to caller
89
90catch.start:                                      ; preds = %catch.dispatch
91  %1 = catchpad within %0 [i8* null]
92  %2 = call i8* @llvm.wasm.get.exception(token %1)
93  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
94  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
95  call void @__cxa_end_catch() [ "funclet"(token %1) ]
96  catchret from %1 to label %try.cont
97; CHECK: catch.start:
98; CHECK-NEXT:   catchpad within %0 [i8* null]
99; CHECK-NOT:   call void @llvm.wasm.landingpad.index
100; CHECK-NOT:   store {{.*}} @__wasm_lpad_context
101; CHECK-NOT:   call i8* @llvm.wasm.lsda()
102; CHECK-NOT:   call i32 @_Unwind_CallPersonality
103; CHECK-NOT:   load {{.*}} @__wasm_lpad_context
104
105try.cont:                                         ; preds = %entry, %catch.start
106  invoke void @foo()
107          to label %try.cont7 unwind label %catch.dispatch2
108
109catch.dispatch2:                                  ; preds = %try.cont
110  %5 = catchswitch within none [label %catch.start3] unwind to caller
111
112catch.start3:                                     ; preds = %catch.dispatch2
113  %6 = catchpad within %5 [i8* bitcast (i8** @_ZTIi to i8*)]
114  %7 = call i8* @llvm.wasm.get.exception(token %6)
115  %8 = call i32 @llvm.wasm.get.ehselector(token %6)
116  %9 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
117  %matches = icmp eq i32 %8, %9
118  br i1 %matches, label %catch4, label %rethrow
119; CHECK: catch.start3:
120; CHECK:   call void @llvm.wasm.landingpad.index(token %{{.+}}, i32 0)
121
122catch4:                                           ; preds = %catch.start3
123  %10 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
124  call void @__cxa_end_catch() [ "funclet"(token %6) ]
125  catchret from %6 to label %try.cont7
126
127rethrow:                                          ; preds = %catch.start3
128  call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %6) ]
129  unreachable
130
131try.cont7:                                        ; preds = %try.cont, %catch4
132  ret void
133}
134
135; A nested try-catch within a catch. The outer catch catches 'int'.
136;
137; void foo();
138; void test2() {
139;   try {
140;     foo();
141;   } catch (int) {
142;     try {
143;       foo();
144;     } catch (int) {
145;     }
146;   }
147; }
148; Within the nested catchpad, wasm.lsda() call should NOT be generated.
149define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
150; CHECK-LABEL: @test2()
151entry:
152  invoke void @foo()
153          to label %try.cont9 unwind label %catch.dispatch
154
155catch.dispatch:                                   ; preds = %entry
156  %0 = catchswitch within none [label %catch.start] unwind to caller
157
158catch.start:                                      ; preds = %catch.dispatch
159  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
160  %2 = call i8* @llvm.wasm.get.exception(token %1)
161  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
162  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
163  %matches = icmp eq i32 %3, %4
164  br i1 %matches, label %catch, label %rethrow
165; CHECK: catch.start:
166; CHECK:   call i8* @llvm.wasm.lsda()
167
168catch:                                            ; preds = %catch.start
169  %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
170  invoke void @foo() [ "funclet"(token %1) ]
171          to label %try.cont unwind label %catch.dispatch2
172
173catch.dispatch2:                                  ; preds = %catch
174  %6 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup
175
176catch.start3:                                     ; preds = %catch.dispatch2
177  %7 = catchpad within %6 [i8* bitcast (i8** @_ZTIi to i8*)]
178  %8 = call i8* @llvm.wasm.get.exception(token %7)
179  %9 = call i32 @llvm.wasm.get.ehselector(token %7)
180  %10 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
181  %matches4 = icmp eq i32 %9, %10
182  br i1 %matches4, label %catch6, label %rethrow5
183; CHECK: catch.start3:
184; CHECK-NOT:   call i8* @llvm.wasm.lsda()
185
186catch6:                                           ; preds = %catch.start3
187  %11 = call i8* @__cxa_begin_catch(i8* %8) [ "funclet"(token %7) ]
188  call void @__cxa_end_catch() [ "funclet"(token %7) ]
189  catchret from %7 to label %try.cont
190
191rethrow5:                                         ; preds = %catch.start3
192  invoke void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %7) ]
193          to label %unreachable unwind label %ehcleanup
194
195try.cont:                                         ; preds = %catch, %catch6
196  call void @__cxa_end_catch() [ "funclet"(token %1) ]
197  catchret from %1 to label %try.cont9
198
199rethrow:                                          ; preds = %catch.start
200  call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
201  unreachable
202
203try.cont9:                                        ; preds = %entry, %try.cont
204  ret void
205
206ehcleanup:                                        ; preds = %rethrow5, %catch.dispatch2
207  %12 = cleanuppad within %1 []
208  call void @__cxa_end_catch() [ "funclet"(token %12) ]
209  cleanupret from %12 unwind to caller
210; CHECK: ehcleanup:
211; CHECK-NEXT:   cleanuppad
212; CHECK-NOT:   call void @llvm.wasm.landingpad.index
213; CHECK-NOT:   store {{.*}} @__wasm_lpad_context
214; CHECK-NOT:   call i8* @llvm.wasm.lsda()
215; CHECK-NOT:   call i32 @_Unwind_CallPersonality
216; CHECK-NOT:   load {{.*}} @__wasm_lpad_context
217
218unreachable:                                      ; preds = %rethrow5
219  unreachable
220}
221
222; A nested try-catch within a catch. The outer catch is (...).
223;
224; void foo();
225; void test2() {
226;   try {
227;     foo();
228;   } catch (...) {
229;     try {
230;       foo();
231;     } catch (int) {
232;     }
233;   }
234; }
235; Within the innermost catchpad, wasm.lsda() call should be generated, because
236; the outer catch is 'catch (...)', which does not need wasm.lsda() call.
237define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
238; CHECK-LABEL: @test3()
239entry:
240  invoke void @foo()
241          to label %try.cont8 unwind label %catch.dispatch
242
243catch.dispatch:                                   ; preds = %entry
244  %0 = catchswitch within none [label %catch.start] unwind to caller
245
246catch.start:                                      ; preds = %catch.dispatch
247  %1 = catchpad within %0 [i8* null]
248  %2 = call i8* @llvm.wasm.get.exception(token %1)
249  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
250  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
251  invoke void @foo() [ "funclet"(token %1) ]
252          to label %try.cont unwind label %catch.dispatch2
253; CHECK: catch.start:
254; CHECK-NOT:   call i8* @llvm.wasm.lsda()
255
256catch.dispatch2:                                  ; preds = %catch.start
257  %5 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup
258
259catch.start3:                                     ; preds = %catch.dispatch2
260  %6 = catchpad within %5 [i8* bitcast (i8** @_ZTIi to i8*)]
261  %7 = call i8* @llvm.wasm.get.exception(token %6)
262  %8 = call i32 @llvm.wasm.get.ehselector(token %6)
263  %9 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
264  %matches = icmp eq i32 %8, %9
265  br i1 %matches, label %catch4, label %rethrow
266; CHECK: catch.start3:
267; CHECK:   call i8* @llvm.wasm.lsda()
268
269catch4:                                           ; preds = %catch.start3
270  %10 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
271  %11 = bitcast i8* %10 to i32*
272  %12 = load i32, i32* %11, align 4
273  call void @__cxa_end_catch() [ "funclet"(token %6) ]
274  catchret from %6 to label %try.cont
275
276rethrow:                                          ; preds = %catch.start3
277  invoke void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %6) ]
278          to label %unreachable unwind label %ehcleanup
279
280try.cont:                                         ; preds = %catch.start, %catch4
281  call void @__cxa_end_catch() [ "funclet"(token %1) ]
282  catchret from %1 to label %try.cont8
283
284try.cont8:                                        ; preds = %entry, %try.cont
285  ret void
286
287ehcleanup:                                        ; preds = %rethrow, %catch.dispatch2
288  %13 = cleanuppad within %1 []
289  invoke void @__cxa_end_catch() [ "funclet"(token %13) ]
290          to label %invoke.cont6 unwind label %terminate
291
292invoke.cont6:                                     ; preds = %ehcleanup
293  cleanupret from %13 unwind to caller
294
295unreachable:                                      ; preds = %rethrow
296  unreachable
297
298terminate:                                        ; preds = %ehcleanup
299  %14 = cleanuppad within %13 []
300  %15 = call i8* @llvm.wasm.get.exception(token %14)
301  call void @__clang_call_terminate(i8* %15) [ "funclet"(token %14) ]
302  unreachable
303}
304
305; void foo();
306; void test4() {
307;   try {
308;     foo();
309;   } catch (int) {
310;     try {
311;       foo();
312;     } catch (...) {
313;       try {
314;         foo();
315;       } catch (int) {
316;       }
317;     }
318;   }
319; }
320; wasm.lsda() call should be generated only once in the outermost catchpad. The
321; innermost 'catch (int)' can reuse the wasm.lsda() generated in the outermost
322; catch.
323define void @test4() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
324; CHECK-LABEL: @test4()
325entry:
326  invoke void @foo()
327          to label %try.cont19 unwind label %catch.dispatch
328
329catch.dispatch:                                   ; preds = %entry
330  %0 = catchswitch within none [label %catch.start] unwind to caller
331
332catch.start:                                      ; preds = %catch.dispatch
333  %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
334  %2 = call i8* @llvm.wasm.get.exception(token %1)
335  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
336  %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
337  %matches = icmp eq i32 %3, %4
338  br i1 %matches, label %catch, label %rethrow
339; CHECK: catch.start:
340; CHECK:   call i8* @llvm.wasm.lsda()
341
342catch:                                            ; preds = %catch.start
343  %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
344  %6 = bitcast i8* %5 to i32*
345  %7 = load i32, i32* %6, align 4
346  invoke void @foo() [ "funclet"(token %1) ]
347          to label %try.cont16 unwind label %catch.dispatch2
348
349catch.dispatch2:                                  ; preds = %catch
350  %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup17
351
352catch.start3:                                     ; preds = %catch.dispatch2
353  %9 = catchpad within %8 [i8* null]
354  %10 = call i8* @llvm.wasm.get.exception(token %9)
355  %11 = call i32 @llvm.wasm.get.ehselector(token %9)
356  %12 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
357  invoke void @foo() [ "funclet"(token %9) ]
358          to label %try.cont unwind label %catch.dispatch7
359; CHECK: catch.start3:
360; CHECK-NOT:   call i8* @llvm.wasm.lsda()
361
362catch.dispatch7:                                  ; preds = %catch.start3
363  %13 = catchswitch within %9 [label %catch.start8] unwind label %ehcleanup
364
365catch.start8:                                     ; preds = %catch.dispatch7
366  %14 = catchpad within %13 [i8* bitcast (i8** @_ZTIi to i8*)]
367  %15 = call i8* @llvm.wasm.get.exception(token %14)
368  %16 = call i32 @llvm.wasm.get.ehselector(token %14)
369  %17 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
370  %matches9 = icmp eq i32 %16, %17
371  br i1 %matches9, label %catch11, label %rethrow10
372; CHECK: catch.start8:
373; CHECK-NOT:   call i8* @llvm.wasm.lsda()
374
375catch11:                                          ; preds = %catch.start8
376  %18 = call i8* @__cxa_begin_catch(i8* %15) [ "funclet"(token %14) ]
377  %19 = bitcast i8* %18 to i32*
378  %20 = load i32, i32* %19, align 4
379  call void @__cxa_end_catch() [ "funclet"(token %14) ]
380  catchret from %14 to label %try.cont
381
382rethrow10:                                        ; preds = %catch.start8
383  invoke void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %14) ]
384          to label %unreachable unwind label %ehcleanup
385
386try.cont:                                         ; preds = %catch.start3, %catch11
387  invoke void @__cxa_end_catch() [ "funclet"(token %9) ]
388          to label %invoke.cont13 unwind label %ehcleanup17
389
390invoke.cont13:                                    ; preds = %try.cont
391  catchret from %9 to label %try.cont16
392
393try.cont16:                                       ; preds = %catch, %invoke.cont13
394  call void @__cxa_end_catch() [ "funclet"(token %1) ]
395  catchret from %1 to label %try.cont19
396
397rethrow:                                          ; preds = %catch.start
398  call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
399  unreachable
400
401try.cont19:                                       ; preds = %entry, %try.cont16
402  ret void
403
404ehcleanup:                                        ; preds = %rethrow10, %catch.dispatch7
405  %21 = cleanuppad within %9 []
406  invoke void @__cxa_end_catch() [ "funclet"(token %21) ]
407          to label %invoke.cont14 unwind label %terminate
408
409invoke.cont14:                                    ; preds = %ehcleanup
410  cleanupret from %21 unwind label %ehcleanup17
411
412ehcleanup17:                                      ; preds = %invoke.cont14, %try.cont, %catch.dispatch2
413  %22 = cleanuppad within %1 []
414  call void @__cxa_end_catch() [ "funclet"(token %22) ]
415  cleanupret from %22 unwind to caller
416
417unreachable:                                      ; preds = %rethrow10
418  unreachable
419
420terminate:                                        ; preds = %ehcleanup
421  %23 = cleanuppad within %21 []
422  %24 = call i8* @llvm.wasm.get.exception(token %23)
423  call void @__clang_call_terminate(i8* %24) [ "funclet"(token %23) ]
424  unreachable
425}
426
427; A cleanuppad with a call to __clang_call_terminate().
428;
429; void foo();
430; void test5() {
431;   try {
432;     foo();
433;   } catch (...) {
434;     foo();
435;   }
436; }
437define void @test5() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
438; CHECK-LABEL: @test5
439entry:
440  invoke void @foo()
441          to label %try.cont unwind label %catch.dispatch
442
443catch.dispatch:                                   ; preds = %entry
444  %0 = catchswitch within none [label %catch.start] unwind to caller
445
446catch.start:                                      ; preds = %catch.dispatch
447  %1 = catchpad within %0 [i8* null]
448  %2 = call i8* @llvm.wasm.get.exception(token %1)
449  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
450  %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
451  invoke void @foo() [ "funclet"(token %1) ]
452          to label %invoke.cont1 unwind label %ehcleanup
453
454invoke.cont1:                                     ; preds = %catch.start
455  call void @__cxa_end_catch() [ "funclet"(token %1) ]
456  catchret from %1 to label %try.cont
457
458try.cont:                                         ; preds = %entry, %invoke.cont1
459  ret void
460
461ehcleanup:                                        ; preds = %catch.start
462  %5 = cleanuppad within %1 []
463  invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
464          to label %invoke.cont2 unwind label %terminate
465
466invoke.cont2:                                     ; preds = %ehcleanup
467  cleanupret from %5 unwind to caller
468
469terminate:                                        ; preds = %ehcleanup
470  %6 = cleanuppad within %5 []
471  %7 = call i8* @llvm.wasm.get.exception(token %6)
472  call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
473  unreachable
474; CHECK: terminate:
475; CHECK-NEXT: cleanuppad
476; CHECK-NEXT:   %[[EXN:.*]] = call i8* @llvm.wasm.extract.exception
477; CHECK-NEXT:   call void @__clang_call_terminate(i8* %[[EXN]])
478}
479
480; PHI demotion test. Only the phi before catchswitch should be demoted; the phi
481; before cleanuppad should NOT.
482;
483; void foo();
484; int bar(int) noexcept;
485; struct Temp {
486;   ~Temp() {}
487; };
488;
489; void test6() {
490;   int num;
491;   try {
492;     Temp t;
493;     num = 1;
494;     foo();
495;     num = 2;
496;     foo();
497;   } catch (...) {
498;     bar(num);
499;   }
500;   try {
501;     foo();
502;     num = 1;
503;     foo();
504;     num = 2;
505;   } catch (...) {
506;     bar(num);
507;   }
508; }
509define void @test6() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
510; CHECK-LABEL: @test6
511entry:
512  %t = alloca %struct.Temp, align 1
513  invoke void @foo()
514          to label %invoke.cont unwind label %ehcleanup
515
516invoke.cont:                                      ; preds = %entry
517  invoke void @foo()
518          to label %invoke.cont1 unwind label %ehcleanup
519
520invoke.cont1:                                     ; preds = %invoke.cont
521  %call = call %struct.Temp* @_ZN4TempD2Ev(%struct.Temp* %t)
522  br label %try.cont
523
524ehcleanup:                                        ; preds = %invoke.cont, %entry
525  %num.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
526  %0 = cleanuppad within none []
527  %call2 = call %struct.Temp* @_ZN4TempD2Ev(%struct.Temp* %t) [ "funclet"(token %0) ]
528  cleanupret from %0 unwind label %catch.dispatch
529; CHECK: ehcleanup:
530; CHECK-NEXT:   = phi
531
532catch.dispatch:                                   ; preds = %ehcleanup
533  %1 = catchswitch within none [label %catch.start] unwind to caller
534
535catch.start:                                      ; preds = %catch.dispatch
536  %2 = catchpad within %1 [i8* null]
537  %3 = call i8* @llvm.wasm.get.exception(token %2)
538  %4 = call i32 @llvm.wasm.get.ehselector(token %2)
539  %5 = call i8* @__cxa_begin_catch(i8* %3) [ "funclet"(token %2) ]
540  call void @bar(i32 %num.0) [ "funclet"(token %2) ]
541  call void @__cxa_end_catch() [ "funclet"(token %2) ]
542  catchret from %2 to label %try.cont
543
544try.cont:                                         ; preds = %catch.start, %invoke.cont1
545  invoke void @foo()
546          to label %invoke.cont3 unwind label %catch.dispatch5
547
548invoke.cont3:                                     ; preds = %try.cont
549  invoke void @foo()
550          to label %try.cont10 unwind label %catch.dispatch5
551
552catch.dispatch5:                                  ; preds = %invoke.cont3, %try.cont
553  %num.1 = phi i32 [ 2, %invoke.cont3 ], [ 1, %try.cont ]
554  %6 = catchswitch within none [label %catch.start6] unwind to caller
555; CHECK: catch.dispatch5:
556; CHECK-NOT:   = phi
557
558catch.start6:                                     ; preds = %catch.dispatch5
559  %7 = catchpad within %6 [i8* null]
560  %8 = call i8* @llvm.wasm.get.exception(token %7)
561  %9 = call i32 @llvm.wasm.get.ehselector(token %7)
562  %10 = call i8* @__cxa_begin_catch(i8* %8) [ "funclet"(token %7) ]
563  call void @bar(i32 %num.1) [ "funclet"(token %7) ]
564  call void @__cxa_end_catch() [ "funclet"(token %7) ]
565  catchret from %7 to label %try.cont10
566
567try.cont10:                                       ; preds = %invoke.cont3, %catch.start6
568  ret void
569}
570
571; Tests if instructions after a call to @llvm.wasm.throw are deleted and the
572; BB's dead children are deleted.
573
574; CHECK-LABEL: @test7
575define i32 @test7(i1 %b, i8* %p) {
576entry:
577  br i1 %b, label %bb.true, label %bb.false
578
579; CHECK:      bb.true:
580; CHECK-NEXT:   call void @llvm.wasm.throw(i32 0, i8* %p)
581; CHECK-NEXT:   unreachable
582bb.true:                                          ; preds = %entry
583  call void @llvm.wasm.throw(i32 0, i8* %p)
584  br label %bb.true.0
585
586; CHECK-NOT:  bb.true.0
587bb.true.0:                                        ; preds = %bb.true
588  br label %merge
589
590; CHECK:      bb.false
591bb.false:                                         ; preds = %entry
592  br label %merge
593
594; CHECK:      merge
595merge:                                            ; preds = %bb.true.0, %bb.false
596  ret i32 0
597}
598
599declare void @foo()
600declare void @bar(i32)
601declare %struct.Temp* @_ZN4TempD2Ev(%struct.Temp* returned)
602declare i32 @__gxx_wasm_personality_v0(...)
603declare i8* @llvm.wasm.get.exception(token)
604declare i32 @llvm.wasm.get.ehselector(token)
605declare i32 @llvm.eh.typeid.for(i8*)
606declare void @llvm.wasm.throw(i32, i8*)
607declare void @llvm.wasm.rethrow.in.catch()
608declare i8* @__cxa_begin_catch(i8*)
609declare void @__cxa_end_catch()
610declare void @__clang_call_terminate(i8*)
611
612; CHECK-DAG: declare void @llvm.wasm.landingpad.index(token, i32 immarg)
613; CHECK-DAG: declare i8* @llvm.wasm.lsda()
614; CHECK-DAG: declare i32 @_Unwind_CallPersonality(i8*)
615