Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / test / CodeGen / WebAssembly / cfg-stackify-eh.ll
blob037730141b3142470d935d08ec5323fa62aba29b
1 ; RUN: llc < %s -asm-verbose=false -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
3 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
4 target triple = "wasm32-unknown-unknown"
6 @_ZTIi = external constant i8*
7 @_ZTId = external constant i8*
9 ; Simple test case with two catch clauses
10 ; void test0() {
11 ;   try {
12 ;     foo();
13 ;   } catch (int n) {
14 ;     bar();
15 ;   } catch (double d) {
16 ;   }
17 ; }
19 ; CHECK-LABEL: test0
20 ; CHECK:   try
21 ; CHECK:   call      foo@FUNCTION
22 ; CHECK:   catch     $[[EXCEPT_REF:[0-9]+]]=
23 ; CHECK:   block i32
24 ; CHECK:   br_on_exn 0, __cpp_exception@EVENT, $[[EXCEPT_REF]]
25 ; CHECK:   rethrow
26 ; CHECK:   end_block
27 ; CHECK:   i32.call  $drop=, _Unwind_CallPersonality@FUNCTION
28 ; CHECK:   end_try
29 ; CHECK:   return
30 define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
31 entry:
32   invoke void @foo()
33           to label %try.cont unwind label %catch.dispatch
35 catch.dispatch:                                   ; preds = %entry
36   %0 = catchswitch within none [label %catch.start] unwind to caller
38 catch.start:                                      ; preds = %catch.dispatch
39   %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
40   %2 = call i8* @llvm.wasm.get.exception(token %1)
41   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
42   %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
43   %matches = icmp eq i32 %3, %4
44   br i1 %matches, label %catch2, label %catch.fallthrough
46 catch2:                                           ; preds = %catch.start
47   %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
48   %6 = bitcast i8* %5 to i32*
49   %7 = load i32, i32* %6, align 4
50   call void @bar() [ "funclet"(token %1) ]
51   call void @__cxa_end_catch() [ "funclet"(token %1) ]
52   catchret from %1 to label %try.cont
54 catch.fallthrough:                                ; preds = %catch.start
55   %8 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
56   %matches1 = icmp eq i32 %3, %8
57   br i1 %matches1, label %catch, label %rethrow
59 catch:                                            ; preds = %catch.fallthrough
60   %9 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
61   %10 = bitcast i8* %9 to double*
62   %11 = load double, double* %10, align 8
63   call void @__cxa_end_catch() [ "funclet"(token %1) ]
64   catchret from %1 to label %try.cont
66 rethrow:                                          ; preds = %catch.fallthrough
67   call void @__cxa_rethrow() [ "funclet"(token %1) ]
68   unreachable
70 try.cont:                                         ; preds = %entry, %catch, %catch2
71   ret void
74 ; Nested try-catches within a catch
75 ; void test1() {
76 ;   try {
77 ;     foo();
78 ;   } catch (int n) {
79 ;     try {
80 ;       foo();
81 ;     } catch (int n) {
82 ;       foo();
83 ;     }
84 ;   }
85 ; }
87 ; CHECK-LABEL: test1
88 ; CHECK:   try
89 ; CHECK:   call      foo@FUNCTION
90 ; CHECK:   catch
91 ; CHECK:   br_on_exn 0, __cpp_exception@EVENT
92 ; CHECK:   rethrow
93 ; CHECK:   i32.call  $drop=, _Unwind_CallPersonality@FUNCTION
94 ; CHECK:   try
95 ; CHECK:   call      foo@FUNCTION
96 ; CHECK:   catch
97 ; CHECK:   br_on_exn   0, __cpp_exception@EVENT
98 ; CHECK:   rethrow
99 ; CHECK:   i32.call  $drop=, _Unwind_CallPersonality@FUNCTION
100 ; CHECK:   try
101 ; CHECK:   i32.call  $drop=, __cxa_begin_catch@FUNCTION
102 ; CHECK:   try
103 ; CHECK:   call      foo@FUNCTION
104 ; CHECK:   catch     $drop=
105 ; CHECK:   rethrow
106 ; CHECK:   end_try
107 ; CHECK:   catch     $drop=
108 ; CHECK:   rethrow
109 ; CHECK:   end_try
110 ; CHECK:   end_try
111 ; CHECK:   end_try
112 ; CHECK:   return
113 define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
114 entry:
115   invoke void @foo()
116           to label %try.cont11 unwind label %catch.dispatch
118 catch.dispatch:                                   ; preds = %entry
119   %0 = catchswitch within none [label %catch.start] unwind to caller
121 catch.start:                                      ; preds = %catch.dispatch
122   %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
123   %2 = call i8* @llvm.wasm.get.exception(token %1)
124   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
125   %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
126   %matches = icmp eq i32 %3, %4
127   br i1 %matches, label %catch, label %rethrow
129 catch:                                            ; preds = %catch.start
130   %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
131   %6 = bitcast i8* %5 to i32*
132   %7 = load i32, i32* %6, align 4
133   invoke void @foo() [ "funclet"(token %1) ]
134           to label %try.cont unwind label %catch.dispatch2
136 catch.dispatch2:                                  ; preds = %catch
137   %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
139 catch.start3:                                     ; preds = %catch.dispatch2
140   %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
141   %10 = call i8* @llvm.wasm.get.exception(token %9)
142   %11 = call i32 @llvm.wasm.get.ehselector(token %9)
143   %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
144   %matches4 = icmp eq i32 %11, %12
145   br i1 %matches4, label %catch6, label %rethrow5
147 catch6:                                           ; preds = %catch.start3
148   %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
149   %14 = bitcast i8* %13 to i32*
150   %15 = load i32, i32* %14, align 4
151   invoke void @foo() [ "funclet"(token %9) ]
152           to label %invoke.cont8 unwind label %ehcleanup
154 invoke.cont8:                                     ; preds = %catch6
155   call void @__cxa_end_catch() [ "funclet"(token %9) ]
156   catchret from %9 to label %try.cont
158 rethrow5:                                         ; preds = %catch.start3
159   invoke void @__cxa_rethrow() [ "funclet"(token %9) ]
160           to label %unreachable unwind label %ehcleanup9
162 try.cont:                                         ; preds = %catch, %invoke.cont8
163   call void @__cxa_end_catch() [ "funclet"(token %1) ]
164   catchret from %1 to label %try.cont11
166 rethrow:                                          ; preds = %catch.start
167   call void @__cxa_rethrow() [ "funclet"(token %1) ]
168   unreachable
170 try.cont11:                                       ; preds = %entry, %try.cont
171   ret void
173 ehcleanup:                                        ; preds = %catch6
174   %16 = cleanuppad within %9 []
175   call void @__cxa_end_catch() [ "funclet"(token %16) ]
176   cleanupret from %16 unwind label %ehcleanup9
178 ehcleanup9:                                       ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
179   %17 = cleanuppad within %1 []
180   call void @__cxa_end_catch() [ "funclet"(token %17) ]
181   cleanupret from %17 unwind to caller
183 unreachable:                                      ; preds = %rethrow5
184   unreachable
187 ; Nested loop within a catch clause
188 ; void test2() {
189 ;   try {
190 ;     foo();
191 ;   } catch (...) {
192 ;     for (int i = 0; i < 50; i++)
193 ;       foo();
194 ;   }
195 ; }
197 ; CHECK-LABEL: test2
198 ; CHECK:   try
199 ; CHECK:   call      foo@FUNCTION
200 ; CHECK:   catch
201 ; CHECK:   br_on_exn   0, __cpp_exception@EVENT
202 ; CHECK:   rethrow
203 ; CHECK:   loop
204 ; CHECK:   try
205 ; CHECK:   call      foo@FUNCTION
206 ; CHECK:   catch     $drop=
207 ; CHECK:   try
208 ; CHECK:   call      __cxa_end_catch@FUNCTION
209 ; CHECK:   catch
210 ; CHECK:   br_on_exn   0, __cpp_exception@EVENT
211 ; CHECK:   call      __clang_call_terminate@FUNCTION, 0
212 ; CHECK:   unreachable
213 ; CHECK:   call      __clang_call_terminate@FUNCTION
214 ; CHECK:   unreachable
215 ; CHECK:   end_try
216 ; CHECK:   rethrow
217 ; CHECK:   end_try
218 ; CHECK:   end_loop
219 ; CHECK:   end_try
220 ; CHECK:   return
221 define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
222 entry:
223   invoke void @foo()
224           to label %try.cont unwind label %catch.dispatch
226 catch.dispatch:                                   ; preds = %entry
227   %0 = catchswitch within none [label %catch.start] unwind to caller
229 catch.start:                                      ; preds = %catch.dispatch
230   %1 = catchpad within %0 [i8* null]
231   %2 = call i8* @llvm.wasm.get.exception(token %1)
232   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
233   %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
234   br label %for.cond
236 for.cond:                                         ; preds = %for.inc, %catch.start
237   %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
238   %cmp = icmp slt i32 %i.0, 50
239   br i1 %cmp, label %for.body, label %for.end
241 for.body:                                         ; preds = %for.cond
242   invoke void @foo() [ "funclet"(token %1) ]
243           to label %for.inc unwind label %ehcleanup
245 for.inc:                                          ; preds = %for.body
246   %inc = add nsw i32 %i.0, 1
247   br label %for.cond
249 for.end:                                          ; preds = %for.cond
250   call void @__cxa_end_catch() [ "funclet"(token %1) ]
251   catchret from %1 to label %try.cont
253 try.cont:                                         ; preds = %for.end, %entry
254   ret void
256 ehcleanup:                                        ; preds = %for.body
257   %5 = cleanuppad within %1 []
258   invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
259           to label %invoke.cont2 unwind label %terminate
261 invoke.cont2:                                     ; preds = %ehcleanup
262   cleanupret from %5 unwind to caller
264 terminate:                                        ; preds = %ehcleanup
265   %6 = cleanuppad within %5 []
266   %7 = call i8* @llvm.wasm.get.exception(token %6)
267   call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
268   unreachable
271 declare void @foo()
272 declare void @bar()
273 declare i32 @__gxx_wasm_personality_v0(...)
274 declare i8* @llvm.wasm.get.exception(token)
275 declare i32 @llvm.wasm.get.ehselector(token)
276 declare i32 @llvm.eh.typeid.for(i8*)
277 declare i8* @__cxa_begin_catch(i8*)
278 declare void @__cxa_end_catch()
279 declare void @__cxa_rethrow()
280 declare void @__clang_call_terminate(i8*)
281 declare void @_ZSt9terminatev()