[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / WebAssembly / wasmehprepare.ll
blob742989f10384d9083a304955bc95d059bf95156a
1 ; RUN: opt < %s -winehprepare -demote-catchswitch-only -wasmehprepare -S | FileCheck %s
3 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
4 target triple = "wasm32-unknown-unknown"
6 ; CHECK: @__wasm_lpad_context = external global { i32, i8*, i32 }
8 @_ZTIi = external constant i8*
9 %struct.Temp = type { i8 }
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.
15 ; void foo();
16 ; void test0() {
17 ;   try {
18 ;     foo();
19 ;   } catch (int) {
20 ;   }
21 ; }
22 define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
23 ; CHECK-LABEL: @test0()
24 entry:
25   invoke void @foo()
26           to label %try.cont unwind label %catch.dispatch
28 catch.dispatch:                                   ; preds = %entry
29   %0 = catchswitch within none [label %catch.start] unwind to caller
31 catch.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]]
49 catch:                                            ; 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]])
56 rethrow:                                          ; preds = %catch.start
57   call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
58   unreachable
60 try.cont:                                         ; preds = %entry, %catch
61   ret void
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.
70 ; void foo();
71 ; void test1() {
72 ;   try {
73 ;     foo();
74 ;   } catch (...) {
75 ;   }
76 ;   try {
77 ;     foo();
78 ;   } catch (int) {
79 ;   }
80 ; }
81 define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
82 ; CHECK-LABEL: @test1()
83 entry:
84   invoke void @foo()
85           to label %try.cont unwind label %catch.dispatch
87 catch.dispatch:                                   ; preds = %entry
88   %0 = catchswitch within none [label %catch.start] unwind to caller
90 catch.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
105 try.cont:                                         ; preds = %entry, %catch.start
106   invoke void @foo()
107           to label %try.cont7 unwind label %catch.dispatch2
109 catch.dispatch2:                                  ; preds = %try.cont
110   %5 = catchswitch within none [label %catch.start3] unwind to caller
112 catch.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)
122 catch4:                                           ; 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
127 rethrow:                                          ; preds = %catch.start3
128   call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %6) ]
129   unreachable
131 try.cont7:                                        ; preds = %try.cont, %catch4
132   ret void
135 ; A nested try-catch within a catch.
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.
149 define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
150 ; CHECK-LABEL: @test2()
151 entry:
152   invoke void @foo()
153           to label %try.cont9 unwind label %catch.dispatch
155 catch.dispatch:                                   ; preds = %entry
156   %0 = catchswitch within none [label %catch.start] unwind to caller
158 catch.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()
168 catch:                                            ; 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
173 catch.dispatch2:                                  ; preds = %catch
174   %6 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup
176 catch.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()
186 catch6:                                           ; 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
191 rethrow5:                                         ; preds = %catch.start3
192   invoke void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %7) ]
193           to label %unreachable unwind label %ehcleanup
195 try.cont:                                         ; preds = %catch, %catch6
196   call void @__cxa_end_catch() [ "funclet"(token %1) ]
197   catchret from %1 to label %try.cont9
199 rethrow:                                          ; preds = %catch.start
200   call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
201   unreachable
203 try.cont9:                                        ; preds = %entry, %try.cont
204   ret void
206 ehcleanup:                                        ; 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
218 unreachable:                                      ; preds = %rethrow5
219   unreachable
222 ; A cleanuppad with a call to __clang_call_terminate().
223 ; A call to wasm.catch() should be generated after the cleanuppad.
225 ; void foo();
226 ; void test3() {
227 ;   try {
228 ;     foo();
229 ;   } catch (...) {
230 ;     foo();
231 ;   }
232 ; }
233 define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
234 ; CHECK-LABEL: @test3
235 entry:
236   invoke void @foo()
237           to label %try.cont unwind label %catch.dispatch
239 catch.dispatch:                                   ; preds = %entry
240   %0 = catchswitch within none [label %catch.start] unwind to caller
242 catch.start:                                      ; preds = %catch.dispatch
243   %1 = catchpad within %0 [i8* null]
244   %2 = call i8* @llvm.wasm.get.exception(token %1)
245   %3 = call i32 @llvm.wasm.get.ehselector(token %1)
246   %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
247   invoke void @foo() [ "funclet"(token %1) ]
248           to label %invoke.cont1 unwind label %ehcleanup
250 invoke.cont1:                                     ; preds = %catch.start
251   call void @__cxa_end_catch() [ "funclet"(token %1) ]
252   catchret from %1 to label %try.cont
254 try.cont:                                         ; preds = %entry, %invoke.cont1
255   ret void
257 ehcleanup:                                        ; preds = %catch.start
258   %5 = cleanuppad within %1 []
259   invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
260           to label %invoke.cont2 unwind label %terminate
262 invoke.cont2:                                     ; preds = %ehcleanup
263   cleanupret from %5 unwind to caller
265 terminate:                                        ; preds = %ehcleanup
266   %6 = cleanuppad within %5 []
267   %7 = call i8* @llvm.wasm.get.exception(token %6)
268   call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
269   unreachable
270 ; CHECK: terminate:
271 ; CHECK-NEXT: cleanuppad
272 ; CHECK-NEXT:   %[[EXN:.*]] = call i8* @llvm.wasm.extract.exception
273 ; CHECK-NEXT:   call void @__clang_call_terminate(i8* %[[EXN]])
276 ; PHI demotion test. Only the phi before catchswitch should be demoted; the phi
277 ; before cleanuppad should NOT.
279 ; void foo();
280 ; int bar(int) noexcept;
281 ; struct Temp {
282 ;   ~Temp() {}
283 ; };
285 ; void test4() {
286 ;   int num;
287 ;   try {
288 ;     Temp t;
289 ;     num = 1;
290 ;     foo();
291 ;     num = 2;
292 ;     foo();
293 ;   } catch (...) {
294 ;     bar(num);
295 ;   }
296 ;   try {
297 ;     foo();
298 ;     num = 1;
299 ;     foo();
300 ;     num = 2;
301 ;   } catch (...) {
302 ;     bar(num);
303 ;   }
304 ; }
305 define void @test4() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
306 ; CHECK-LABEL: @test4
307 entry:
308   %t = alloca %struct.Temp, align 1
309   invoke void @foo()
310           to label %invoke.cont unwind label %ehcleanup
312 invoke.cont:                                      ; preds = %entry
313   invoke void @foo()
314           to label %invoke.cont1 unwind label %ehcleanup
316 invoke.cont1:                                     ; preds = %invoke.cont
317   %call = call %struct.Temp* @_ZN4TempD2Ev(%struct.Temp* %t)
318   br label %try.cont
320 ehcleanup:                                        ; preds = %invoke.cont, %entry
321   %num.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
322   %0 = cleanuppad within none []
323   %call2 = call %struct.Temp* @_ZN4TempD2Ev(%struct.Temp* %t) [ "funclet"(token %0) ]
324   cleanupret from %0 unwind label %catch.dispatch
325 ; CHECK: ehcleanup:
326 ; CHECK-NEXT:   = phi
328 catch.dispatch:                                   ; preds = %ehcleanup
329   %1 = catchswitch within none [label %catch.start] unwind to caller
331 catch.start:                                      ; preds = %catch.dispatch
332   %2 = catchpad within %1 [i8* null]
333   %3 = call i8* @llvm.wasm.get.exception(token %2)
334   %4 = call i32 @llvm.wasm.get.ehselector(token %2)
335   %5 = call i8* @__cxa_begin_catch(i8* %3) [ "funclet"(token %2) ]
336   call void @bar(i32 %num.0) [ "funclet"(token %2) ]
337   call void @__cxa_end_catch() [ "funclet"(token %2) ]
338   catchret from %2 to label %try.cont
340 try.cont:                                         ; preds = %catch.start, %invoke.cont1
341   invoke void @foo()
342           to label %invoke.cont3 unwind label %catch.dispatch5
344 invoke.cont3:                                     ; preds = %try.cont
345   invoke void @foo()
346           to label %try.cont10 unwind label %catch.dispatch5
348 catch.dispatch5:                                  ; preds = %invoke.cont3, %try.cont
349   %num.1 = phi i32 [ 2, %invoke.cont3 ], [ 1, %try.cont ]
350   %6 = catchswitch within none [label %catch.start6] unwind to caller
351 ; CHECK: catch.dispatch5:
352 ; CHECK-NOT:   = phi
354 catch.start6:                                     ; preds = %catch.dispatch5
355   %7 = catchpad within %6 [i8* null]
356   %8 = call i8* @llvm.wasm.get.exception(token %7)
357   %9 = call i32 @llvm.wasm.get.ehselector(token %7)
358   %10 = call i8* @__cxa_begin_catch(i8* %8) [ "funclet"(token %7) ]
359   call void @bar(i32 %num.1) [ "funclet"(token %7) ]
360   call void @__cxa_end_catch() [ "funclet"(token %7) ]
361   catchret from %7 to label %try.cont10
363 try.cont10:                                       ; preds = %invoke.cont3, %catch.start6
364   ret void
367 ; Tests if instructions after a call to @llvm.wasm.throw are deleted and the
368 ; BB's dead children are deleted.
370 ; CHECK-LABEL: @test5
371 define i32 @test5(i1 %b, i8* %p) {
372 entry:
373   br i1 %b, label %bb.true, label %bb.false
375 ; CHECK:      bb.true:
376 ; CHECK-NEXT:   call void @llvm.wasm.throw(i32 0, i8* %p)
377 ; CHECK-NEXT:   unreachable
378 bb.true:                                          ; preds = %entry
379   call void @llvm.wasm.throw(i32 0, i8* %p)
380   br label %bb.true.0
382 ; CHECK-NOT:  bb.true.0
383 bb.true.0:                                        ; preds = %bb.true
384   br label %merge
386 ; CHECK:      bb.false
387 bb.false:                                         ; preds = %entry
388   br label %merge
390 ; CHECK:      merge
391 merge:                                            ; preds = %bb.true.0, %bb.false
392   ret i32 0
395 declare void @foo()
396 declare void @bar(i32)
397 declare %struct.Temp* @_ZN4TempD2Ev(%struct.Temp* returned)
398 declare i32 @__gxx_wasm_personality_v0(...)
399 declare i8* @llvm.wasm.get.exception(token)
400 declare i32 @llvm.wasm.get.ehselector(token)
401 declare i32 @llvm.eh.typeid.for(i8*)
402 declare void @llvm.wasm.throw(i32, i8*)
403 declare void @llvm.wasm.rethrow.in.catch()
404 declare i8* @__cxa_begin_catch(i8*)
405 declare void @__cxa_end_catch()
406 declare void @__clang_call_terminate(i8*)
408 ; CHECK-DAG: declare void @llvm.wasm.landingpad.index(token, i32 immarg)
409 ; CHECK-DAG: declare i8* @llvm.wasm.lsda()
410 ; CHECK-DAG: declare i32 @_Unwind_CallPersonality(i8*)