[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Coroutines / coro-catchswitch-cleanuppad.ll
blob4650820c84eac1444da79f489d575e43cac7dafe
1 ; Tests the PHI nodes in cleanuppads for catchswitch instructions are correctly
2 ; split up.
3 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
5 declare i32 @__CxxFrameHandler3(...)
6 define i8* @f2(i1 %val) "coroutine.presplit"="1" personality i32 (...)* @__CxxFrameHandler3 {
7 entry:
8   %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* 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
14 dyn.alloc:
15   %size = call i32 @llvm.coro.size.i32()
16   %alloc = call i8* @malloc(i32 %size)
17   br label %dowork.0
19 dowork.0:
20   %phi = phi i8* [ null, %entry ], [ %alloc, %dyn.alloc ]
21   %hdl = call i8* @llvm.coro.begin(token %id, i8* %phi)
22   invoke void @print(i32 0)
23     to label %checksuspend unwind label %catch.dispatch.1
25 checksuspend:
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]
30 dowork.1:
31   invoke void @print(i32 0)
32     to label %checksuspend unwind label %catch.dispatch.1
34 cleanup:
35   %mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
36   call void @free(i8* %mem)
37   br label %suspend
39 suspend:
40   call i1 @llvm.coro.end(i8* %hdl, i1 0)
41   ret i8* %hdl
43 catch.dispatch.1:
44   %cs1 = catchswitch within none [label %handler1] unwind to caller
45 handler1:
46   %h1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
47   invoke void @print(i32 2) [ "funclet"(token %h1) ]
48           to label %catchret1 unwind label %catch.dispatch.2
49 catchret1:
50   catchret from %h1 to label %cleanup
52 catch.dispatch.2:
53   %cs2 = catchswitch within %h1 [label %handler2] unwind label %cleanup2
54 handler2:
55   %h2 = catchpad within %cs2 [i8* null, i32 64, i8* null]
56   invoke void @print(i32 3) [ "funclet"(token %h2) ]
57           to label %cleanup unwind label %cleanup2
58 cleanup2:
59   %cleanupval2 = phi i32 [%valueA, %catch.dispatch.2], [%valueB, %handler2]
60   cleanuppad within %h1 []
61   call void @print(i32 %cleanupval2)
62   br label %cleanup
64 ; Verifiers that a "dispatcher" cleanuppad is created.
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.
73 ; CHECK: catch.dispatch.2:
74 ; CHECK:   %cs2 = catchswitch within %h1 [label %handler2] unwind label %cleanup2.corodispatch
76 ; CHECK: handler2:
77 ; CHECK:   invoke void @print(i32 3)
78 ; CHECK:           to label %cleanup unwind label %cleanup2.corodispatch
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
86 ; CHECK: cleanup2.from.handler2:
87 ; CHECK:   %valueB.reload = load i32, i32* %valueB.spill.addr, align 4
88 ; CHECK:   br label %cleanup2
90 ; CHECK: cleanup2.from.catch.dispatch.2:
91 ; CHECK:   %valueA.reload = load i32, i32* %valueA.spill.addr, align 4
92 ; CHECK:   br label %cleanup2
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
100 declare i8* @llvm.coro.free(token, i8*)
101 declare i32 @llvm.coro.size.i32()
102 declare i8  @llvm.coro.suspend(token, i1)
103 declare void @llvm.coro.resume(i8*)
104 declare void @llvm.coro.destroy(i8*)
106 declare token @llvm.coro.id(i32, i8*, i8*, i8*)
107 declare i1 @llvm.coro.alloc(token)
108 declare i8* @llvm.coro.begin(token, i8*)
109 declare i1 @llvm.coro.end(i8*, i1)
111 declare noalias i8* @malloc(i32)
112 declare void @print(i32)
113 declare void @free(i8*)
115 declare i32 @f()