xref: /llvm-project/llvm/test/Transforms/Coroutines/coro-catchswitch-cleanuppad.ll (revision 51d5d7bbae92493a5bfa7cc6b519de8a5bb32fdb)
1; Tests the PHI nodes in cleanuppads for catchswitch instructions are correctly
2; split up.
3; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg<switch-range-to-icmp>,early-cse' -S | FileCheck %s
4
5declare i32 @__CxxFrameHandler3(...)
6define ptr @f2(i1 %val) presplitcoroutine personality ptr @__CxxFrameHandler3 {
7entry:
8  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
9  %valueA = call i32 @f();
10  %valueB = call i32 @f();
11  %need.alloc = call i1 @llvm.coro.alloc(token %id)
12  br i1 %need.alloc, label %dyn.alloc, label %dowork.0
13
14dyn.alloc:
15  %size = call i32 @llvm.coro.size.i32()
16  %alloc = call ptr @malloc(i32 %size)
17  br label %dowork.0
18
19dowork.0:
20  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]
21  %hdl = call ptr @llvm.coro.begin(token %id, ptr %phi)
22  invoke void @print(i32 0)
23    to label %checksuspend unwind label %catch.dispatch.1
24
25checksuspend:
26  %0 = call i8 @llvm.coro.suspend(token none, i1 false)
27  switch i8 %0, label %suspend [i8 0, label %dowork.1
28                                i8 1, label %cleanup]
29
30dowork.1:
31  invoke void @print(i32 0)
32    to label %checksuspend unwind label %catch.dispatch.1
33
34cleanup:
35  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
36  call void @free(ptr %mem)
37  br label %suspend
38
39suspend:
40  call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
41  ret ptr %hdl
42
43catch.dispatch.1:
44  %cs1 = catchswitch within none [label %handler1] unwind to caller
45handler1:
46  %h1 = catchpad within %cs1 [ptr null, i32 64, ptr null]
47  invoke void @print(i32 2) [ "funclet"(token %h1) ]
48          to label %catchret1 unwind label %catch.dispatch.2
49catchret1:
50  catchret from %h1 to label %cleanup
51
52catch.dispatch.2:
53  %cs2 = catchswitch within %h1 [label %handler2] unwind label %cleanup2
54handler2:
55  %h2 = catchpad within %cs2 [ptr null, i32 64, ptr null]
56  invoke void @print(i32 3) [ "funclet"(token %h2) ]
57          to label %cleanup unwind label %cleanup2
58cleanup2:
59  %cleanupval2 = phi i32 [%valueA, %catch.dispatch.2], [%valueB, %handler2]
60  cleanuppad within %h1 []
61  call void @print(i32 %cleanupval2)
62  br label %cleanup
63
64; Verifiers that a "dispatcher" cleanuppad is created.
65
66; catchswitch and all associated catchpads are required to have the same unwind
67; edge, but coro requires that PHI nodes are split up so that reload
68; instructions can be generated, therefore we create a new "dispatcher"
69; cleanuppad which forwards to individual blocks that contain the reload
70; instructions per catchswitch/catchpad and then all branch back to the
71; original cleanuppad block.
72
73; CHECK: catch.dispatch.2:
74; CHECK:   %cs2 = catchswitch within %h1 [label %handler2] unwind label %cleanup2.corodispatch
75
76; CHECK: handler2:
77; CHECK:   invoke void @print(i32 3)
78; CHECK:           to label %cleanup unwind label %cleanup2.corodispatch
79
80; CHECK: cleanup2.corodispatch:
81; CHECK:   %1 = phi i8 [ 0, %handler2 ], [ 1, %catch.dispatch.2 ]
82; CHECK:   %2 = cleanuppad within %h1 []
83; CHECK:   %switch = icmp ult i8 %1, 1
84; CHECK:   br i1 %switch, label %cleanup2.from.handler2, label %cleanup2.from.catch.dispatch.2
85
86; CHECK: cleanup2.from.handler2:
87; CHECK:   %valueB.reload = load i32, ptr %valueB.spill.addr, align 4
88; CHECK:   br label %cleanup2
89
90; CHECK: cleanup2.from.catch.dispatch.2:
91; CHECK:   %valueA.reload = load i32, ptr %valueA.spill.addr, align 4
92; CHECK:   br label %cleanup2
93
94; CHECK: cleanup2:
95; CHECK:   %cleanupval2 = phi i32 [ %valueA.reload, %cleanup2.from.catch.dispatch.2 ], [ %valueB.reload, %cleanup2.from.handler2 ]
96; CHECK:   call void @print(i32 %cleanupval2)
97; CHECK:   br label %cleanup
98}
99
100declare ptr @llvm.coro.free(token, ptr)
101declare i32 @llvm.coro.size.i32()
102declare i8  @llvm.coro.suspend(token, i1)
103declare void @llvm.coro.resume(ptr)
104declare void @llvm.coro.destroy(ptr)
105
106declare token @llvm.coro.id(i32, ptr, ptr, ptr)
107declare i1 @llvm.coro.alloc(token)
108declare ptr @llvm.coro.begin(token, ptr)
109declare i1 @llvm.coro.end(ptr, i1, token)
110
111declare noalias ptr @malloc(i32)
112declare void @print(i32)
113declare void @free(ptr)
114
115declare i32 @f()
116