[ARM] Split large truncating MVE stores
[llvm-complete.git] / test / CodeGen / WebAssembly / cfg-stackify-eh.ll
blob9cb5a057ef14f7f1312f9a42b71d8a3d147c763c
1 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling | FileCheck %s
2 ; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -exception-model=wasm -mattr=+exception-handling | FileCheck %s --check-prefix=NOOPT
3 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT
5 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6 target triple = "wasm32-unknown-unknown"
8 @_ZTIi = external constant i8*
9 @_ZTId = external constant i8*
11 ; Simple test case with two catch clauses
13 ; void foo();
14 ; void test0() {
15 ;   try {
16 ;     foo();
17 ;   } catch (int) {
18 ;   } catch (double) {
19 ;   }
20 ; }
22 ; CHECK-LABEL: test0
23 ; CHECK: try
24 ; CHECK:   call      foo
25 ; CHECK: catch
26 ; CHECK:   block
27 ; CHECK:     br_if     0, {{.*}}                       # 0: down to label2
28 ; CHECK:     i32.call  $drop=, __cxa_begin_catch
29 ; CHECK:     call      __cxa_end_catch
30 ; CHECK:     br        1                               # 1: down to label0
31 ; CHECK:   end_block                                   # label2:
32 ; CHECK:   block
33 ; CHECK:     br_if     0, {{.*}}                       # 0: down to label3
34 ; CHECK:     i32.call  $drop=, __cxa_begin_catch
35 ; CHECK:     call      __cxa_end_catch
36 ; CHECK:     br        1                               # 1: down to label0
37 ; CHECK:   end_block                                   # label3:
38 ; CHECK:   rethrow   {{.*}}                            # to caller
39 ; CHECK: end_try                                       # label0:
40 define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
41 entry:
42   invoke void @foo()
43           to label %try.cont unwind label %catch.dispatch
45 catch.dispatch:                                   ; preds = %entry
46   %0 = catchswitch within none [label %catch.start] unwind to caller
48 catch.start:                                      ; preds = %catch.dispatch
49   %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
50   %2 = call i8* @llvm.wasm.get.exception(token %1)
51   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
52   %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
53   %matches = icmp eq i32 %3, %4
54   br i1 %matches, label %catch2, label %catch.fallthrough
56 catch2:                                           ; preds = %catch.start
57   %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
58   call void @__cxa_end_catch() [ "funclet"(token %1) ]
59   catchret from %1 to label %try.cont
61 catch.fallthrough:                                ; preds = %catch.start
62   %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
63   %matches1 = icmp eq i32 %3, %6
64   br i1 %matches1, label %catch, label %rethrow
66 catch:                                            ; preds = %catch.fallthrough
67   %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
68   call void @__cxa_end_catch() [ "funclet"(token %1) ]
69   catchret from %1 to label %try.cont
71 rethrow:                                          ; preds = %catch.fallthrough
72   call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
73   unreachable
75 try.cont:                                         ; preds = %catch, %catch2, %entry
76   ret void
79 ; Nested try-catches within a catch
80 ; void test1() {
81 ;   try {
82 ;     foo();
83 ;   } catch (int) {
84 ;     try {
85 ;       foo();
86 ;     } catch (int) {
87 ;       foo();
88 ;     }
89 ;   }
90 ; }
92 ; CHECK-LABEL: test1
93 ; CHECK: try
94 ; CHECK:   call      foo
95 ; CHECK: catch
96 ; CHECK:   block
97 ; CHECK:     block
98 ; CHECK:       br_if     0, {{.*}}                     # 0: down to label7
99 ; CHECK:       i32.call  $drop=, __cxa_begin_catch
100 ; CHECK:       try
101 ; CHECK:         call      foo
102 ; CHECK:         br        2                           # 2: down to label6
103 ; CHECK:       catch
104 ; CHECK:         try
105 ; CHECK:           block
106 ; CHECK:             br_if     0, {{.*}}               # 0: down to label11
107 ; CHECK:             i32.call  $drop=, __cxa_begin_catch
108 ; CHECK:             try
109 ; CHECK:               call      foo
110 ; CHECK:               br        2                     # 2: down to label9
111 ; CHECK:             catch
112 ; CHECK:               call      __cxa_end_catch
113 ; CHECK:               rethrow   {{.*}}                # down to catch3
114 ; CHECK:             end_try
115 ; CHECK:           end_block                           # label11:
116 ; CHECK:           rethrow   {{.*}}                    # down to catch3
117 ; CHECK:         catch     {{.*}}                      # catch3:
118 ; CHECK:           call      __cxa_end_catch
119 ; CHECK:           rethrow   {{.*}}                    # to caller
120 ; CHECK:         end_try                               # label9:
121 ; CHECK:         call      __cxa_end_catch
122 ; CHECK:         br        2                           # 2: down to label6
123 ; CHECK:       end_try
124 ; CHECK:     end_block                                 # label7:
125 ; CHECK:     rethrow   {{.*}}                          # to caller
126 ; CHECK:   end_block                                   # label6:
127 ; CHECK:   call      __cxa_end_catch
128 ; CHECK: end_try
129 define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
130 entry:
131   invoke void @foo()
132           to label %try.cont11 unwind label %catch.dispatch
134 catch.dispatch:                                   ; preds = %entry
135   %0 = catchswitch within none [label %catch.start] unwind to caller
137 catch.start:                                      ; preds = %catch.dispatch
138   %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
139   %2 = call i8* @llvm.wasm.get.exception(token %1)
140   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
141   %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
142   %matches = icmp eq i32 %3, %4
143   br i1 %matches, label %catch, label %rethrow
145 catch:                                            ; preds = %catch.start
146   %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
147   %6 = bitcast i8* %5 to i32*
148   %7 = load i32, i32* %6, align 4
149   invoke void @foo() [ "funclet"(token %1) ]
150           to label %try.cont unwind label %catch.dispatch2
152 catch.dispatch2:                                  ; preds = %catch
153   %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
155 catch.start3:                                     ; preds = %catch.dispatch2
156   %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
157   %10 = call i8* @llvm.wasm.get.exception(token %9)
158   %11 = call i32 @llvm.wasm.get.ehselector(token %9)
159   %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
160   %matches4 = icmp eq i32 %11, %12
161   br i1 %matches4, label %catch6, label %rethrow5
163 catch6:                                           ; preds = %catch.start3
164   %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
165   %14 = bitcast i8* %13 to i32*
166   %15 = load i32, i32* %14, align 4
167   invoke void @foo() [ "funclet"(token %9) ]
168           to label %invoke.cont8 unwind label %ehcleanup
170 invoke.cont8:                                     ; preds = %catch6
171   call void @__cxa_end_catch() [ "funclet"(token %9) ]
172   catchret from %9 to label %try.cont
174 rethrow5:                                         ; preds = %catch.start3
175   invoke void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %9) ]
176           to label %unreachable unwind label %ehcleanup9
178 try.cont:                                         ; preds = %invoke.cont8, %catch
179   call void @__cxa_end_catch() [ "funclet"(token %1) ]
180   catchret from %1 to label %try.cont11
182 rethrow:                                          ; preds = %catch.start
183   call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
184   unreachable
186 try.cont11:                                       ; preds = %try.cont, %entry
187   ret void
189 ehcleanup:                                        ; preds = %catch6
190   %16 = cleanuppad within %9 []
191   call void @__cxa_end_catch() [ "funclet"(token %16) ]
192   cleanupret from %16 unwind label %ehcleanup9
194 ehcleanup9:                                       ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
195   %17 = cleanuppad within %1 []
196   call void @__cxa_end_catch() [ "funclet"(token %17) ]
197   cleanupret from %17 unwind to caller
199 unreachable:                                      ; preds = %rethrow5
200   unreachable
203 ; Nested loop within a catch clause
204 ; void test2() {
205 ;   try {
206 ;     foo();
207 ;   } catch (...) {
208 ;     for (int i = 0; i < 50; i++)
209 ;       foo();
210 ;   }
211 ; }
213 ; CHECK-LABEL: test2
214 ; CHECK: try
215 ; CHECK:   call      foo
216 ; CHECK: catch
217 ; CHECK:   i32.call  $drop=, __cxa_begin_catch
218 ; CHECK:   loop                                        # label15:
219 ; CHECK:     block
220 ; CHECK:       block
221 ; CHECK:         br_if     0, {{.*}}                   # 0: down to label17
222 ; CHECK:         try
223 ; CHECK:           call      foo
224 ; CHECK:           br        2                         # 2: down to label16
225 ; CHECK:         catch
226 ; CHECK:           try
227 ; CHECK:             call      __cxa_end_catch
228 ; CHECK:           catch
229 ; CHECK:             call      __clang_call_terminate
230 ; CHECK:             unreachable
231 ; CHECK:           end_try
232 ; CHECK:           rethrow   {{.*}}                    # to caller
233 ; CHECK:         end_try
234 ; CHECK:       end_block                               # label17:
235 ; CHECK:       call      __cxa_end_catch
236 ; CHECK:       br        2                             # 2: down to label13
237 ; CHECK:     end_block                                 # label16:
238 ; CHECK:     br        0                               # 0: up to label15
239 ; CHECK:   end_loop
240 ; CHECK: end_try                                       # label13:
241 define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
242 entry:
243   invoke void @foo()
244           to label %try.cont unwind label %catch.dispatch
246 catch.dispatch:                                   ; preds = %entry
247   %0 = catchswitch within none [label %catch.start] unwind to caller
249 catch.start:                                      ; preds = %catch.dispatch
250   %1 = catchpad within %0 [i8* null]
251   %2 = call i8* @llvm.wasm.get.exception(token %1)
252   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
253   %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
254   br label %for.cond
256 for.cond:                                         ; preds = %for.inc, %catch.start
257   %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
258   %cmp = icmp slt i32 %i.0, 50
259   br i1 %cmp, label %for.body, label %for.end
261 for.body:                                         ; preds = %for.cond
262   invoke void @foo() [ "funclet"(token %1) ]
263           to label %for.inc unwind label %ehcleanup
265 for.inc:                                          ; preds = %for.body
266   %inc = add nsw i32 %i.0, 1
267   br label %for.cond
269 for.end:                                          ; preds = %for.cond
270   call void @__cxa_end_catch() [ "funclet"(token %1) ]
271   catchret from %1 to label %try.cont
273 try.cont:                                         ; preds = %for.end, %entry
274   ret void
276 ehcleanup:                                        ; preds = %for.body
277   %5 = cleanuppad within %1 []
278   invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
279           to label %invoke.cont2 unwind label %terminate
281 invoke.cont2:                                     ; preds = %ehcleanup
282   cleanupret from %5 unwind to caller
284 terminate:                                        ; preds = %ehcleanup
285   %6 = cleanuppad within %5 []
286   %7 = call i8* @llvm.wasm.get.exception(token %6)
287   call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
288   unreachable
291 ; Tests if block and try markers are correctly placed. Even if two predecessors
292 ; of the EH pad are bb2 and bb3 and their nearest common dominator is bb1, the
293 ; TRY marker should be placed at bb0 because there's a branch from bb0 to bb2,
294 ; and scopes cannot be interleaved.
296 ; NOOPT-LABEL: test3
297 ; NOOPT: try
298 ; NOOPT:   block
299 ; NOOPT:     block
300 ; NOOPT:       block
301 ; NOOPT:       end_block
302 ; NOOPT:     end_block
303 ; NOOPT:     call      foo
304 ; NOOPT:   end_block
305 ; NOOPT:   call      bar
306 ; NOOPT: catch     {{.*}}
307 ; NOOPT: end_try
308 define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
309 bb0:
310   br i1 undef, label %bb1, label %bb2
312 bb1:                                              ; preds = %bb0
313   br i1 undef, label %bb3, label %bb4
315 bb2:                                              ; preds = %bb0
316   br label %try.cont
318 bb3:                                              ; preds = %bb1
319   invoke void @foo()
320           to label %try.cont unwind label %catch.dispatch
322 bb4:                                              ; preds = %bb1
323   invoke void @bar()
324           to label %try.cont unwind label %catch.dispatch
326 catch.dispatch:                                   ; preds = %bb4, %bb3
327   %0 = catchswitch within none [label %catch.start] unwind to caller
329 catch.start:                                      ; preds = %catch.dispatch
330   %1 = catchpad within %0 [i8* null]
331   %2 = call i8* @llvm.wasm.get.exception(token %1)
332   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
333   catchret from %1 to label %try.cont
335 try.cont:                                         ; preds = %catch.start, %bb4, %bb3, %bb2
336   ret void
339 ; Tests if try/end_try markers are placed correctly wrt loop/end_loop markers,
340 ; when try and loop markers are in the same BB and end_try and end_loop are in
341 ; another BB.
342 ; CHECK: loop
343 ; CHECK:   try
344 ; CHECK:     call      foo
345 ; CHECK:   catch
346 ; CHECK:   end_try
347 ; CHECK: end_loop
348 define void @test4(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
349 entry:
350   store volatile i32 0, i32* %p
351   br label %loop
353 loop:                                             ; preds = %try.cont, %entry
354   store volatile i32 1, i32* %p
355   invoke void @foo()
356           to label %try.cont unwind label %catch.dispatch
358 catch.dispatch:                                   ; preds = %loop
359   %0 = catchswitch within none [label %catch.start] unwind to caller
361 catch.start:                                      ; preds = %catch.dispatch
362   %1 = catchpad within %0 [i8* null]
363   %2 = call i8* @llvm.wasm.get.exception(token %1)
364   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
365   catchret from %1 to label %try.cont
367 try.cont:                                         ; preds = %catch.start, %loop
368   br label %loop
371 ; Some of test cases below are hand-tweaked by deleting some library calls to
372 ; simplify tests and changing the order of basic blocks to cause unwind
373 ; destination mismatches. And we use -wasm-disable-ehpad-sort to create maximum
374 ; number of mismatches in several tests below.
376 ; 'call bar''s original unwind destination was 'catch14', but after control flow
377 ; linearization, its unwind destination incorrectly becomes 'catch15'. We fix
378 ; this by wrapping the call with a nested try/catch/end_try and branching to the
379 ; right destination (label32).
381 ; NOSORT-LABEL: test5
382 ; NOSORT:   block
383 ; NOSORT:     try
384 ; NOSORT:       try
385 ; NOSORT:         call      foo
386 ; --- Nested try/catch/end_try starts
387 ; NOSORT:         try
388 ; NOSORT:           call      bar
389 ; NOSORT:         catch     $drop=
390 ; NOSORT:           br        2                        # 2: down to label32
391 ; NOSORT:         end_try
392 ; --- Nested try/catch/end_try ends
393 ; NOSORT:         br        2                          # 2: down to label31
394 ; NOSORT:       catch     $drop=                       # catch15:
395 ; NOSORT:         br        2                          # 2: down to label31
396 ; NOSORT:       end_try
397 ; NOSORT:     catch     $drop=                         # catch14:
398 ; NOSORT:     end_try                                  # label32:
399 ; NOSORT:   end_block                                  # label31:
400 ; NOSORT:   return
402 define void @test5() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
403 bb0:
404   invoke void @foo()
405           to label %bb1 unwind label %catch.dispatch0
407 bb1:                                              ; preds = %bb0
408   invoke void @bar()
409           to label %try.cont unwind label %catch.dispatch1
411 catch.dispatch0:                                  ; preds = %bb0
412   %0 = catchswitch within none [label %catch.start0] unwind to caller
414 catch.start0:                                     ; preds = %catch.dispatch0
415   %1 = catchpad within %0 [i8* null]
416   %2 = call i8* @llvm.wasm.get.exception(token %1)
417   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
418   catchret from %1 to label %try.cont
420 catch.dispatch1:                                  ; preds = %bb1
421   %4 = catchswitch within none [label %catch.start1] unwind to caller
423 catch.start1:                                     ; preds = %catch.dispatch1
424   %5 = catchpad within %4 [i8* null]
425   %6 = call i8* @llvm.wasm.get.exception(token %5)
426   %7 = call i32 @llvm.wasm.get.ehselector(token %5)
427   catchret from %5 to label %try.cont
429 try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
430   ret void
433 ; Two 'call bar''s original unwind destination was the caller, but after control
434 ; flow linearization, their unwind destination incorrectly becomes 'catch17'. We
435 ; fix this by wrapping the call with a nested try/catch/end_try and branching to
436 ; the right destination (label4), from which we rethrow the exception to the
437 ; caller.
439 ; NOSORT-LABEL: test6
440 ; NOSORT:   try
441 ; NOSORT:     call      foo
442 ; --- Nested try/catch/end_try starts
443 ; NOSORT:     try
444 ; NOSORT:       call      bar
445 ; NOSORT:       call      bar
446 ; NOSORT:     catch     $[[REG:[0-9]+]]=
447 ; NOSORT:       br        1                            # 1: down to label35
448 ; NOSORT:     end_try
449 ; --- Nested try/catch/end_try ends
450 ; NOSORT:     return
451 ; NOSORT:   catch     $drop=                           # catch17:
452 ; NOSORT:     return
453 ; NOSORT:   end_try                                    # label35:
454 ; NOSORT:   rethrow   $[[REG]]                         # to caller
456 define void @test6() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
457 bb0:
458   invoke void @foo()
459           to label %bb1 unwind label %catch.dispatch0
461 bb1:                                              ; preds = %bb0
462   call void @bar()
463   call void @bar()
464   ret void
466 catch.dispatch0:                                  ; preds = %bb0
467   %0 = catchswitch within none [label %catch.start0] unwind to caller
469 catch.start0:                                     ; preds = %catch.dispatch0
470   %1 = catchpad within %0 [i8* null]
471   %2 = call i8* @llvm.wasm.get.exception(token %1)
472   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
473   catchret from %1 to label %try.cont
475 try.cont:                                         ; preds = %catch.start0
476   ret void
479 ; If not for the unwind destination mismatch, the LOOP marker here would have an
480 ; i32 signature. But because we add a rethrow instruction at the end of the
481 ; appendix block, now the LOOP marker does not have a signature (= has a void
482 ; signature). Here the two calls two 'bar' are supposed to throw up to the
483 ; caller, but incorrectly unwind to 'catch19' after linearizing the CFG.
485 ; NOSORT-LABEL: test7
486 ; NOSORT: block
487 ; NOSORT-NOT: loop      i32
488 ; NOSORT:   loop                                       # label38:
489 ; NOSORT:     try
490 ; NOSORT:       call      foo
491 ; --- Nested try/catch/end_try starts
492 ; NOSORT:       try
493 ; NOSORT:         call      bar
494 ; NOSORT:         call      bar
495 ; NOSORT:       catch     $[[REG:[0-9]+]]=
496 ; NOSORT:         br        1                          # 1: down to label39
497 ; NOSORT:       end_try
498 ; --- Nested try/catch/end_try ends
499 ; NOSORT:       return    {{.*}}
500 ; NOSORT:     catch     $drop=                         # catch19:
501 ; NOSORT:       br        1                            # 1: up to label38
502 ; NOSORT:     end_try                                  # label39:
503 ; NOSORT:   end_loop
504 ; NOSORT: end_block
505 ; NOSORT: rethrow   $[[REG]]                           # to caller
507 define i32 @test7(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
508 entry:
509   store volatile i32 0, i32* %p
510   br label %loop
512 loop:                                             ; preds = %try.cont, %entry
513   store volatile i32 1, i32* %p
514   invoke void @foo()
515           to label %bb unwind label %catch.dispatch
517 bb:                                               ; preds = %loop
518   call void @bar()
519   call void @bar()
520   ret i32 0
522 catch.dispatch:                                   ; preds = %loop
523   %0 = catchswitch within none [label %catch.start] unwind to caller
525 catch.start:                                      ; preds = %catch.dispatch
526   %1 = catchpad within %0 [i8* null]
527   %2 = call i8* @llvm.wasm.get.exception(token %1)
528   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
529   catchret from %1 to label %try.cont
531 try.cont:                                         ; preds = %catch.start
532   br label %loop
535 ; When we have both kinds of EH pad unwind mismatches:
536 ; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
537 ;   CFG, when it is supposed to unwind to another EH pad.
538 ; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
539 ;   CFG, when it is supposed to unwind to the caller.
541 ; NOSORT-LABEL: test8
542 ; NOSORT: block
543 ; NOSORT:   block
544 ; NOSORT:     try
545 ; NOSORT:       try
546 ; NOSORT:         call      foo
547 ; --- Nested try/catch/end_try starts
548 ; NOSORT:         try
549 ; NOSORT:           call      bar
550 ; NOSORT:         catch     $[[REG0:[0-9]+]]=
551 ; NOSORT:           br        2                        # 2: down to label43
552 ; NOSORT:         end_try
553 ; --- Nested try/catch/end_try ends
554 ; NOSORT:         br        2                          # 2: down to label42
555 ; NOSORT:       catch     {{.*}}
556 ; NOSORT:         block     i32
557 ; NOSORT:           br_on_exn   0, {{.*}}              # 0: down to label46
558 ; --- Nested try/catch/end_try starts
559 ; NOSORT:           try
560 ; NOSORT:             rethrow   {{.*}}                 # down to catch24
561 ; NOSORT:           catch     $[[REG1:[0-9]+]]=        # catch24:
562 ; NOSORT:             br        5                      # 5: down to label41
563 ; NOSORT:           end_try
564 ; --- Nested try/catch/end_try ends
565 ; NOSORT:         end_block                            # label46:
566 ; NOSORT:         i32.call  $drop=, __cxa_begin_catch
567 ; --- Nested try/catch/end_try starts
568 ; NOSORT:         try
569 ; NOSORT:           call      __cxa_end_catch
570 ; NOSORT:         catch     $[[REG1]]=
571 ; NOSORT:           br        4                        # 4: down to label41
572 ; NOSORT:         end_try
573 ; --- Nested try/catch/end_try ends
574 ; NOSORT:         br        2                          # 2: down to label42
575 ; NOSORT:       end_try
576 ; NOSORT:     catch     $[[REG0]]=
577 ; NOSORT:     end_try                                  # label43:
578 ; NOSORT:     i32.call  $drop=, __cxa_begin_catch
579 ; NOSORT:     call      __cxa_end_catch
580 ; NOSORT:   end_block                                  # label42:
581 ; NOSORT:   return
582 ; NOSORT: end_block                                    # label41:
583 ; NOSORT: rethrow   $[[REG1]]                          # to caller
584 define void @test8() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
585 bb0:
586   invoke void @foo()
587           to label %bb1 unwind label %catch.dispatch0
589 bb1:                                              ; preds = %bb0
590   invoke void @bar()
591           to label %try.cont unwind label %catch.dispatch1
593 catch.dispatch0:                                  ; preds = %bb0
594   %0 = catchswitch within none [label %catch.start0] unwind to caller
596 catch.start0:                                     ; preds = %catch.dispatch0
597   %1 = catchpad within %0 [i8* null]
598   %2 = call i8* @llvm.wasm.get.exception(token %1)
599   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
600   %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
601   call void @__cxa_end_catch() [ "funclet"(token %1) ]
602   catchret from %1 to label %try.cont
604 catch.dispatch1:                                  ; preds = %bb1
605   %5 = catchswitch within none [label %catch.start1] unwind to caller
607 catch.start1:                                     ; preds = %catch.dispatch1
608   %6 = catchpad within %5 [i8* null]
609   %7 = call i8* @llvm.wasm.get.exception(token %6)
610   %8 = call i32 @llvm.wasm.get.ehselector(token %6)
611   %9 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
612   call void @__cxa_end_catch() [ "funclet"(token %6) ]
613   catchret from %6 to label %try.cont
615 try.cont:                                         ; preds = %catch.start1, %catch.start0, %bb1
616   ret void
619 declare void @foo()
620 declare void @bar()
621 declare i32 @__gxx_wasm_personality_v0(...)
622 declare i8* @llvm.wasm.get.exception(token)
623 declare i32 @llvm.wasm.get.ehselector(token)
624 declare void @llvm.wasm.rethrow.in.catch()
625 declare i32 @llvm.eh.typeid.for(i8*)
626 declare i8* @__cxa_begin_catch(i8*)
627 declare void @__cxa_end_catch()
628 declare void @__clang_call_terminate(i8*)
629 declare void @_ZSt9terminatev()