1*9880d681SAndroid Build Coastguard Worker; RUN: opt -inline -S %s | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Workerdeclare void @g() 4*9880d681SAndroid Build Coastguard Worker 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Worker;;; Test with a call in a funclet that needs to remain a call 7*9880d681SAndroid Build Coastguard Worker;;; when inlined because the funclet doesn't unwind to caller. 8*9880d681SAndroid Build Coastguard Worker;;; CHECK-LABEL: define void @test1( 9*9880d681SAndroid Build Coastguard Workerdefine void @test1() personality void ()* @g { 10*9880d681SAndroid Build Coastguard Workerentry: 11*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: entry: 12*9880d681SAndroid Build Coastguard Worker invoke void @test1_inlinee() 13*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup 14*9880d681SAndroid Build Coastguard Workercleanup: 15*9880d681SAndroid Build Coastguard Worker %pad = cleanuppad within none [] 16*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad) ] 17*9880d681SAndroid Build Coastguard Worker cleanupret from %pad unwind to caller 18*9880d681SAndroid Build Coastguard Workerexit: 19*9880d681SAndroid Build Coastguard Worker ret void 20*9880d681SAndroid Build Coastguard Worker} 21*9880d681SAndroid Build Coastguard Worker 22*9880d681SAndroid Build Coastguard Workerdefine void @test1_inlinee() alwaysinline personality void ()* @g { 23*9880d681SAndroid Build Coastguard Workerentry: 24*9880d681SAndroid Build Coastguard Worker invoke void @g() 25*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup.inner 26*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() 27*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[cleanup_inner:.+]] 28*9880d681SAndroid Build Coastguard Worker 29*9880d681SAndroid Build Coastguard Workercleanup.inner: 30*9880d681SAndroid Build Coastguard Worker %pad.inner = cleanuppad within none [] 31*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad.inner) ] 32*9880d681SAndroid Build Coastguard Worker cleanupret from %pad.inner unwind label %cleanup.outer 33*9880d681SAndroid Build Coastguard Worker; CHECK: [[cleanup_inner]]: 34*9880d681SAndroid Build Coastguard Worker; The call here needs to remain a call becuase pad.inner has a cleanupret 35*9880d681SAndroid Build Coastguard Worker; that stays within the inlinee. 36*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[pad_inner:[^ ]+]] = cleanuppad within none 37*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void @g() [ "funclet"(token %[[pad_inner]]) ] 38*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: cleanupret from %[[pad_inner]] unwind label %[[cleanup_outer:.+]] 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Workercleanup.outer: 41*9880d681SAndroid Build Coastguard Worker %pad.outer = cleanuppad within none [] 42*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad.outer) ] 43*9880d681SAndroid Build Coastguard Worker cleanupret from %pad.outer unwind to caller 44*9880d681SAndroid Build Coastguard Worker; CHECK: [[cleanup_outer]]: 45*9880d681SAndroid Build Coastguard Worker; The call and cleanupret here need to be redirected to caller cleanup 46*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[pad_outer:[^ ]+]] = cleanuppad within none 47*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[pad_outer]]) ] 48*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %cleanup 49*9880d681SAndroid Build Coastguard Worker; CHECK: cleanupret from %[[pad_outer]] unwind label %cleanup{{$}} 50*9880d681SAndroid Build Coastguard Worker 51*9880d681SAndroid Build Coastguard Workerexit: 52*9880d681SAndroid Build Coastguard Worker ret void 53*9880d681SAndroid Build Coastguard Worker} 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker 56*9880d681SAndroid Build Coastguard Worker 57*9880d681SAndroid Build Coastguard Worker;;; Test with an "unwind to caller" catchswitch in a parent funclet 58*9880d681SAndroid Build Coastguard Worker;;; that needs to remain "unwind to caller" because the parent 59*9880d681SAndroid Build Coastguard Worker;;; doesn't unwind to caller. 60*9880d681SAndroid Build Coastguard Worker;;; CHECK-LABEL: define void @test2( 61*9880d681SAndroid Build Coastguard Workerdefine void @test2() personality void ()* @g { 62*9880d681SAndroid Build Coastguard Workerentry: 63*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: entry: 64*9880d681SAndroid Build Coastguard Worker invoke void @test2_inlinee() 65*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup 66*9880d681SAndroid Build Coastguard Workercleanup: 67*9880d681SAndroid Build Coastguard Worker %pad = cleanuppad within none [] 68*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad) ] 69*9880d681SAndroid Build Coastguard Worker cleanupret from %pad unwind to caller 70*9880d681SAndroid Build Coastguard Workerexit: 71*9880d681SAndroid Build Coastguard Worker ret void 72*9880d681SAndroid Build Coastguard Worker} 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Workerdefine void @test2_inlinee() alwaysinline personality void ()* @g { 75*9880d681SAndroid Build Coastguard Workerentry: 76*9880d681SAndroid Build Coastguard Worker invoke void @g() 77*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup1 78*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() 79*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[cleanup1:.+]] 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Workercleanup1: 82*9880d681SAndroid Build Coastguard Worker %outer = cleanuppad within none [] 83*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %outer) ] 84*9880d681SAndroid Build Coastguard Worker to label %ret1 unwind label %catchswitch 85*9880d681SAndroid Build Coastguard Worker; CHECK: [[cleanup1]]: 86*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[outer:[^ ]+]] = cleanuppad within none 87*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[outer]]) ] 88*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[catchswitch:.+]] 89*9880d681SAndroid Build Coastguard Worker 90*9880d681SAndroid Build Coastguard Workercatchswitch: 91*9880d681SAndroid Build Coastguard Worker %cs = catchswitch within %outer [label %catch] unwind to caller 92*9880d681SAndroid Build Coastguard Worker; CHECK: [[catchswitch]]: 93*9880d681SAndroid Build Coastguard Worker; The catchswitch here needs to remain "unwind to caller" since %outer 94*9880d681SAndroid Build Coastguard Worker; has a cleanupret that remains within the inlinee. 95*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[cs:[^ ]+]] = catchswitch within %[[outer]] [label %[[catch:.+]]] unwind to caller 96*9880d681SAndroid Build Coastguard Worker 97*9880d681SAndroid Build Coastguard Workercatch: 98*9880d681SAndroid Build Coastguard Worker %inner = catchpad within %cs [] 99*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %inner) ] 100*9880d681SAndroid Build Coastguard Worker catchret from %inner to label %ret1 101*9880d681SAndroid Build Coastguard Worker; CHECK: [[catch]]: 102*9880d681SAndroid Build Coastguard Worker; The call here needs to remain a call since it too is within %outer 103*9880d681SAndroid Build Coastguard Worker; CHECK: %[[inner:[^ ]+]] = catchpad within %[[cs]] 104*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void @g() [ "funclet"(token %[[inner]]) ] 105*9880d681SAndroid Build Coastguard Worker 106*9880d681SAndroid Build Coastguard Workerret1: 107*9880d681SAndroid Build Coastguard Worker cleanupret from %outer unwind label %cleanup2 108*9880d681SAndroid Build Coastguard Worker; CHECK: cleanupret from %[[outer]] unwind label %[[cleanup2:.+]] 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Workercleanup2: 111*9880d681SAndroid Build Coastguard Worker %later = cleanuppad within none [] 112*9880d681SAndroid Build Coastguard Worker cleanupret from %later unwind to caller 113*9880d681SAndroid Build Coastguard Worker; CHECK: [[cleanup2]]: 114*9880d681SAndroid Build Coastguard Worker; The cleanupret here needs to get redirected to the caller cleanup 115*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[later:[^ ]+]] = cleanuppad within none 116*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: cleanupret from %[[later]] unwind label %cleanup{{$}} 117*9880d681SAndroid Build Coastguard Worker 118*9880d681SAndroid Build Coastguard Workerexit: 119*9880d681SAndroid Build Coastguard Worker ret void 120*9880d681SAndroid Build Coastguard Worker} 121*9880d681SAndroid Build Coastguard Worker 122*9880d681SAndroid Build Coastguard Worker 123*9880d681SAndroid Build Coastguard Worker;;; Test with a call in a cleanup that has no definitive unwind 124*9880d681SAndroid Build Coastguard Worker;;; destination, that must be rewritten to an invoke. 125*9880d681SAndroid Build Coastguard Worker;;; CHECK-LABEL: define void @test3( 126*9880d681SAndroid Build Coastguard Workerdefine void @test3() personality void ()* @g { 127*9880d681SAndroid Build Coastguard Workerentry: 128*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: entry: 129*9880d681SAndroid Build Coastguard Worker invoke void @test3_inlinee() 130*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup 131*9880d681SAndroid Build Coastguard Workercleanup: 132*9880d681SAndroid Build Coastguard Worker %pad = cleanuppad within none [] 133*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad) ] 134*9880d681SAndroid Build Coastguard Worker cleanupret from %pad unwind to caller 135*9880d681SAndroid Build Coastguard Workerexit: 136*9880d681SAndroid Build Coastguard Worker ret void 137*9880d681SAndroid Build Coastguard Worker} 138*9880d681SAndroid Build Coastguard Worker 139*9880d681SAndroid Build Coastguard Workerdefine void @test3_inlinee() alwaysinline personality void ()* @g { 140*9880d681SAndroid Build Coastguard Workerentry: 141*9880d681SAndroid Build Coastguard Worker invoke void @g() 142*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup 143*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() 144*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[cleanup:.+]] 145*9880d681SAndroid Build Coastguard Worker 146*9880d681SAndroid Build Coastguard Workercleanup: 147*9880d681SAndroid Build Coastguard Worker %pad = cleanuppad within none [] 148*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad) ] 149*9880d681SAndroid Build Coastguard Worker unreachable 150*9880d681SAndroid Build Coastguard Worker; CHECK: [[cleanup]]: 151*9880d681SAndroid Build Coastguard Worker; The call must be rewritten to an invoke targeting the caller cleanup 152*9880d681SAndroid Build Coastguard Worker; because it may well unwind to there. 153*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[pad:[^ ]+]] = cleanuppad within none 154*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[pad]]) ] 155*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %cleanup{{$}} 156*9880d681SAndroid Build Coastguard Worker 157*9880d681SAndroid Build Coastguard Workerexit: 158*9880d681SAndroid Build Coastguard Worker ret void 159*9880d681SAndroid Build Coastguard Worker} 160*9880d681SAndroid Build Coastguard Worker 161*9880d681SAndroid Build Coastguard Worker 162*9880d681SAndroid Build Coastguard Worker;;; Test with a catchswitch in a cleanup that has no definitive 163*9880d681SAndroid Build Coastguard Worker;;; unwind destination, that must be rewritten to unwind to the 164*9880d681SAndroid Build Coastguard Worker;;; inlined invoke's unwind dest 165*9880d681SAndroid Build Coastguard Worker;;; CHECK-LABEL: define void @test4( 166*9880d681SAndroid Build Coastguard Workerdefine void @test4() personality void ()* @g { 167*9880d681SAndroid Build Coastguard Workerentry: 168*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: entry: 169*9880d681SAndroid Build Coastguard Worker invoke void @test4_inlinee() 170*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup 171*9880d681SAndroid Build Coastguard Workercleanup: 172*9880d681SAndroid Build Coastguard Worker %pad = cleanuppad within none [] 173*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad) ] 174*9880d681SAndroid Build Coastguard Worker cleanupret from %pad unwind to caller 175*9880d681SAndroid Build Coastguard Workerexit: 176*9880d681SAndroid Build Coastguard Worker ret void 177*9880d681SAndroid Build Coastguard Worker} 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Workerdefine void @test4_inlinee() alwaysinline personality void ()* @g { 180*9880d681SAndroid Build Coastguard Workerentry: 181*9880d681SAndroid Build Coastguard Worker invoke void @g() 182*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup 183*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() 184*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[cleanup:.+]] 185*9880d681SAndroid Build Coastguard Worker 186*9880d681SAndroid Build Coastguard Workercleanup: 187*9880d681SAndroid Build Coastguard Worker %clean = cleanuppad within none [] 188*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %clean) ] 189*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %dispatch 190*9880d681SAndroid Build Coastguard Worker; CHECK: [[cleanup]]: 191*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[clean:[^ ]+]] = cleanuppad within none 192*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[clean]]) ] 193*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[dispatch:.+]] 194*9880d681SAndroid Build Coastguard Worker 195*9880d681SAndroid Build Coastguard Workerdispatch: 196*9880d681SAndroid Build Coastguard Worker %cs = catchswitch within %clean [label %catch] unwind to caller 197*9880d681SAndroid Build Coastguard Worker; CHECK: [[dispatch]]: 198*9880d681SAndroid Build Coastguard Worker; The catchswitch must be rewritten to unwind to %cleanup in the caller 199*9880d681SAndroid Build Coastguard Worker; because it may well unwind to there. 200*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[cs:[^ ]+]] = catchswitch within %[[clean]] [label %[[catch:.+]]] unwind label %cleanup{{$}} 201*9880d681SAndroid Build Coastguard Worker 202*9880d681SAndroid Build Coastguard Workercatch: 203*9880d681SAndroid Build Coastguard Worker catchpad within %cs [] 204*9880d681SAndroid Build Coastguard Worker br label %unreachable 205*9880d681SAndroid Build Coastguard Workerunreachable: 206*9880d681SAndroid Build Coastguard Worker unreachable 207*9880d681SAndroid Build Coastguard Workerexit: 208*9880d681SAndroid Build Coastguard Worker ret void 209*9880d681SAndroid Build Coastguard Worker} 210*9880d681SAndroid Build Coastguard Worker 211*9880d681SAndroid Build Coastguard Worker 212*9880d681SAndroid Build Coastguard Worker;;; Test with multiple levels of nesting, and unwind dests 213*9880d681SAndroid Build Coastguard Worker;;; that need to be inferred from ancestors, descendants, 214*9880d681SAndroid Build Coastguard Worker;;; and cousins. 215*9880d681SAndroid Build Coastguard Worker;;; CHECK-LABEL: define void @test5( 216*9880d681SAndroid Build Coastguard Workerdefine void @test5() personality void ()* @g { 217*9880d681SAndroid Build Coastguard Workerentry: 218*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: entry: 219*9880d681SAndroid Build Coastguard Worker invoke void @test5_inlinee() 220*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %cleanup 221*9880d681SAndroid Build Coastguard Workercleanup: 222*9880d681SAndroid Build Coastguard Worker %pad = cleanuppad within none [] 223*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad) ] 224*9880d681SAndroid Build Coastguard Worker cleanupret from %pad unwind to caller 225*9880d681SAndroid Build Coastguard Workerexit: 226*9880d681SAndroid Build Coastguard Worker ret void 227*9880d681SAndroid Build Coastguard Worker} 228*9880d681SAndroid Build Coastguard Worker 229*9880d681SAndroid Build Coastguard Workerdefine void @test5_inlinee() alwaysinline personality void ()* @g { 230*9880d681SAndroid Build Coastguard Workerentry: 231*9880d681SAndroid Build Coastguard Worker invoke void @g() 232*9880d681SAndroid Build Coastguard Worker to label %cont unwind label %noinfo.root 233*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() 234*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: to label %[[cont:[^ ]+]] unwind label %[[noinfo_root:.+]] 235*9880d681SAndroid Build Coastguard Worker 236*9880d681SAndroid Build Coastguard Workernoinfo.root: 237*9880d681SAndroid Build Coastguard Worker %noinfo.root.pad = cleanuppad within none [] 238*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %noinfo.root.pad) ] 239*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %noinfo.root.pad) ] 240*9880d681SAndroid Build Coastguard Worker to label %noinfo.root.cont unwind label %noinfo.left 241*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_root]]: 242*9880d681SAndroid Build Coastguard Worker; Nothing under "noinfo.root" has a definitive unwind destination, so 243*9880d681SAndroid Build Coastguard Worker; we must assume all of it may actually unwind, and redirect unwinds 244*9880d681SAndroid Build Coastguard Worker; to the cleanup in the caller. 245*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[noinfo_root_pad:[^ ]+]] = cleanuppad within none [] 246*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_root_pad]]) ] 247*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: to label %[[next:[^ ]+]] unwind label %cleanup{{$}} 248*9880d681SAndroid Build Coastguard Worker; CHECK: [[next]]: 249*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_root_pad]]) ] 250*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: to label %[[noinfo_root_cont:[^ ]+]] unwind label %[[noinfo_left:.+]] 251*9880d681SAndroid Build Coastguard Worker 252*9880d681SAndroid Build Coastguard Workernoinfo.left: 253*9880d681SAndroid Build Coastguard Worker %noinfo.left.pad = cleanuppad within %noinfo.root.pad [] 254*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %noinfo.left.pad) ] 255*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %noinfo.left.child 256*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_left]]: 257*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[noinfo_left_pad:[^ ]+]] = cleanuppad within %[[noinfo_root_pad]] 258*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_left_pad]]) ] 259*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[noinfo_left_child:.+]] 260*9880d681SAndroid Build Coastguard Worker 261*9880d681SAndroid Build Coastguard Workernoinfo.left.child: 262*9880d681SAndroid Build Coastguard Worker %noinfo.left.child.cs = catchswitch within %noinfo.left.pad [label %noinfo.left.child.catch] unwind to caller 263*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_left_child]]: 264*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[noinfo_left_child_cs:[^ ]+]] = catchswitch within %[[noinfo_left_pad]] [label %[[noinfo_left_child_catch:[^ ]+]]] unwind label %cleanup{{$}} 265*9880d681SAndroid Build Coastguard Worker 266*9880d681SAndroid Build Coastguard Workernoinfo.left.child.catch: 267*9880d681SAndroid Build Coastguard Worker %noinfo.left.child.pad = catchpad within %noinfo.left.child.cs [] 268*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %noinfo.left.child.pad) ] 269*9880d681SAndroid Build Coastguard Worker br label %unreachable 270*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_left_child_catch]]: 271*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[noinfo_left_child_pad:[^ ]+]] = catchpad within %[[noinfo_left_child_cs]] [] 272*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_left_child_pad]]) ] 273*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %cleanup{{$}} 274*9880d681SAndroid Build Coastguard Worker 275*9880d681SAndroid Build Coastguard Workernoinfo.root.cont: 276*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %noinfo.root.pad) ] 277*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %noinfo.right 278*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_root_cont]]: 279*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_root_pad]]) ] 280*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[noinfo_right:.+]] 281*9880d681SAndroid Build Coastguard Worker 282*9880d681SAndroid Build Coastguard Workernoinfo.right: 283*9880d681SAndroid Build Coastguard Worker %noinfo.right.cs = catchswitch within %noinfo.root.pad [label %noinfo.right.catch] unwind to caller 284*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_right]]: 285*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[noinfo_right_cs:[^ ]+]] = catchswitch within %[[noinfo_root_pad]] [label %[[noinfo_right_catch:[^ ]+]]] unwind label %cleanup{{$}} 286*9880d681SAndroid Build Coastguard Worker 287*9880d681SAndroid Build Coastguard Workernoinfo.right.catch: 288*9880d681SAndroid Build Coastguard Worker %noinfo.right.pad = catchpad within %noinfo.right.cs [] 289*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %noinfo.right.pad) ] 290*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %noinfo.right.child 291*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_right_catch]]: 292*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[noinfo_right_pad:[^ ]+]] = catchpad within %[[noinfo_right_cs]] 293*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_right_pad]]) ] 294*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[noinfo_right_child:.+]] 295*9880d681SAndroid Build Coastguard Worker 296*9880d681SAndroid Build Coastguard Workernoinfo.right.child: 297*9880d681SAndroid Build Coastguard Worker %noinfo.right.child.pad = cleanuppad within %noinfo.right.pad [] 298*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %noinfo.right.child.pad) ] 299*9880d681SAndroid Build Coastguard Worker br label %unreachable 300*9880d681SAndroid Build Coastguard Worker; CHECK: [[noinfo_right_child]]: 301*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[noinfo_right_child_pad:[^ ]+]] = cleanuppad within %[[noinfo_right_pad]] 302*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_right_child_pad]]) ] 303*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %cleanup{{$}} 304*9880d681SAndroid Build Coastguard Worker 305*9880d681SAndroid Build Coastguard Workercont: 306*9880d681SAndroid Build Coastguard Worker invoke void @g() 307*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %implicit.root 308*9880d681SAndroid Build Coastguard Worker; CHECK: [[cont]]: 309*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() 310*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[implicit_root:.+]] 311*9880d681SAndroid Build Coastguard Worker 312*9880d681SAndroid Build Coastguard Workerimplicit.root: 313*9880d681SAndroid Build Coastguard Worker %implicit.root.pad = cleanuppad within none [] 314*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %implicit.root.pad) ] 315*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %implicit.root.pad) ] 316*9880d681SAndroid Build Coastguard Worker to label %implicit.root.cont unwind label %implicit.left 317*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_root]]: 318*9880d681SAndroid Build Coastguard Worker; There's an unwind edge to %internal in implicit.right, and we need to propagate that 319*9880d681SAndroid Build Coastguard Worker; fact down to implicit.right.grandchild, up to implicit.root, and down to 320*9880d681SAndroid Build Coastguard Worker; implicit.left.child.catch, leaving all calls and "unwind to caller" catchswitches 321*9880d681SAndroid Build Coastguard Worker; alone to so they don't conflict with the unwind edge in implicit.right 322*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_root_pad:[^ ]+]] = cleanuppad within none 323*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void @g() [ "funclet"(token %[[implicit_root_pad]]) ] 324*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_root_pad]]) ] 325*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: to label %[[implicit_root_cont:[^ ]+]] unwind label %[[implicit_left:.+]] 326*9880d681SAndroid Build Coastguard Worker 327*9880d681SAndroid Build Coastguard Workerimplicit.left: 328*9880d681SAndroid Build Coastguard Worker %implicit.left.pad = cleanuppad within %implicit.root.pad [] 329*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %implicit.left.pad) ] 330*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %implicit.left.child 331*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_left]]: 332*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_left_pad:[^ ]+]] = cleanuppad within %[[implicit_root_pad:[^ ]+]] 333*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_left_pad]]) ] 334*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[implicit_left_child:.+]] 335*9880d681SAndroid Build Coastguard Worker 336*9880d681SAndroid Build Coastguard Workerimplicit.left.child: 337*9880d681SAndroid Build Coastguard Worker %implicit.left.child.cs = catchswitch within %implicit.left.pad [label %implicit.left.child.catch] unwind to caller 338*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_left_child]]: 339*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_left_child_cs:[^ ]+]] = catchswitch within %[[implicit_left_pad]] [label %[[implicit_left_child_catch:[^ ]+]]] unwind to caller 340*9880d681SAndroid Build Coastguard Worker 341*9880d681SAndroid Build Coastguard Workerimplicit.left.child.catch: 342*9880d681SAndroid Build Coastguard Worker %implicit.left.child.pad = catchpad within %implicit.left.child.cs [] 343*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %implicit.left.child.pad) ] 344*9880d681SAndroid Build Coastguard Worker br label %unreachable 345*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_left_child_catch]]: 346*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_left_child_pad:[^ ]+]] = catchpad within %[[implicit_left_child_cs]] 347*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void @g() [ "funclet"(token %[[implicit_left_child_pad]]) ] 348*9880d681SAndroid Build Coastguard Worker 349*9880d681SAndroid Build Coastguard Workerimplicit.root.cont: 350*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %implicit.root.pad) ] 351*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %implicit.right 352*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_root_cont]]: 353*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_root_pad]]) ] 354*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[implicit_right:.+]] 355*9880d681SAndroid Build Coastguard Worker 356*9880d681SAndroid Build Coastguard Workerimplicit.right: 357*9880d681SAndroid Build Coastguard Worker %implicit.right.cs = catchswitch within %implicit.root.pad [label %implicit.right.catch] unwind label %internal 358*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_right]]: 359*9880d681SAndroid Build Coastguard Worker; This is the unwind edge (to %internal) whose existence needs to get propagated around the "implicit" tree 360*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_right_cs:[^ ]+]] = catchswitch within %[[implicit_root_pad]] [label %[[implicit_right_catch:[^ ]+]]] unwind label %[[internal:.+]] 361*9880d681SAndroid Build Coastguard Worker 362*9880d681SAndroid Build Coastguard Workerimplicit.right.catch: 363*9880d681SAndroid Build Coastguard Worker %implicit.right.pad = catchpad within %implicit.right.cs [] 364*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %implicit.right.pad) ] 365*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %implicit.right.child 366*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_right_catch]]: 367*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_right_pad:[^ ]+]] = catchpad within %[[implicit_right_cs]] 368*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_right_pad]]) ] 369*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[implicit_right_child:.+]] 370*9880d681SAndroid Build Coastguard Worker 371*9880d681SAndroid Build Coastguard Workerimplicit.right.child: 372*9880d681SAndroid Build Coastguard Worker %implicit.right.child.pad = cleanuppad within %implicit.right.pad [] 373*9880d681SAndroid Build Coastguard Worker invoke void @g() [ "funclet"(token %implicit.right.child.pad) ] 374*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %implicit.right.grandchild 375*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_right_child]]: 376*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_right_child_pad:[^ ]+]] = cleanuppad within %[[implicit_right_pad]] 377*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_right_child_pad]]) ] 378*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[implicit_right_grandchild:.+]] 379*9880d681SAndroid Build Coastguard Worker 380*9880d681SAndroid Build Coastguard Workerimplicit.right.grandchild: 381*9880d681SAndroid Build Coastguard Worker %implicit.right.grandchild.cs = catchswitch within %implicit.right.child.pad [label %implicit.right.grandchild.catch] unwind to caller 382*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_right_grandchild]]: 383*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_right_grandchild_cs:[^ ]+]] = catchswitch within %[[implicit_right_child_pad]] [label %[[implicit_right_grandchild_catch:[^ ]+]]] unwind to caller 384*9880d681SAndroid Build Coastguard Worker 385*9880d681SAndroid Build Coastguard Workerimplicit.right.grandchild.catch: 386*9880d681SAndroid Build Coastguard Worker %implicit.right.grandhcild.pad = catchpad within %implicit.right.grandchild.cs [] 387*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %implicit.right.grandhcild.pad) ] 388*9880d681SAndroid Build Coastguard Worker br label %unreachable 389*9880d681SAndroid Build Coastguard Worker; CHECK: [[implicit_right_grandchild_catch]]: 390*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[implicit_right_grandhcild_pad:[^ ]+]] = catchpad within %[[implicit_right_grandchild_cs]] 391*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void @g() [ "funclet"(token %[[implicit_right_grandhcild_pad]]) ] 392*9880d681SAndroid Build Coastguard Worker 393*9880d681SAndroid Build Coastguard Workerinternal: 394*9880d681SAndroid Build Coastguard Worker %internal.pad = cleanuppad within none [] 395*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %internal.pad) ] 396*9880d681SAndroid Build Coastguard Worker cleanupret from %internal.pad unwind to caller 397*9880d681SAndroid Build Coastguard Worker; CHECK: [[internal]]: 398*9880d681SAndroid Build Coastguard Worker; internal is a cleanup with a "return to caller" cleanuppad; that needs to get redirected 399*9880d681SAndroid Build Coastguard Worker; to %cleanup in the caller, and the call needs to get similarly rewritten to an invoke. 400*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[internal_pad:[^ ]+]] = cleanuppad within none 401*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %internal.pad.i) ] 402*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: to label %[[next:[^ ]+]] unwind label %cleanup{{$}} 403*9880d681SAndroid Build Coastguard Worker; CHECK: [[next]]: 404*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: cleanupret from %[[internal_pad]] unwind label %cleanup{{$}} 405*9880d681SAndroid Build Coastguard Worker 406*9880d681SAndroid Build Coastguard Workerunreachable: 407*9880d681SAndroid Build Coastguard Worker unreachable 408*9880d681SAndroid Build Coastguard Workerexit: 409*9880d681SAndroid Build Coastguard Worker ret void 410*9880d681SAndroid Build Coastguard Worker} 411*9880d681SAndroid Build Coastguard Worker 412*9880d681SAndroid Build Coastguard Worker 413*9880d681SAndroid Build Coastguard Workerdeclare void @ProcessCLRException() 414*9880d681SAndroid Build Coastguard Worker 415*9880d681SAndroid Build Coastguard Worker; Make sure the logic doesn't get tripped up when the inlined invoke is 416*9880d681SAndroid Build Coastguard Worker; itself within a funclet in the caller. 417*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test6( 418*9880d681SAndroid Build Coastguard Workerdefine void @test6() personality void ()* @ProcessCLRException { 419*9880d681SAndroid Build Coastguard Workerentry: 420*9880d681SAndroid Build Coastguard Worker invoke void @g() 421*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %callsite_parent 422*9880d681SAndroid Build Coastguard Workercallsite_parent: 423*9880d681SAndroid Build Coastguard Worker %callsite_parent.pad = cleanuppad within none [] 424*9880d681SAndroid Build Coastguard Worker; CHECK: %callsite_parent.pad = cleanuppad within none 425*9880d681SAndroid Build Coastguard Worker invoke void @test6_inlinee() [ "funclet"(token %callsite_parent.pad) ] 426*9880d681SAndroid Build Coastguard Worker to label %ret unwind label %cleanup 427*9880d681SAndroid Build Coastguard Workerret: 428*9880d681SAndroid Build Coastguard Worker cleanupret from %callsite_parent.pad unwind label %cleanup 429*9880d681SAndroid Build Coastguard Workercleanup: 430*9880d681SAndroid Build Coastguard Worker %pad = cleanuppad within none [] 431*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %pad) ] 432*9880d681SAndroid Build Coastguard Worker cleanupret from %pad unwind to caller 433*9880d681SAndroid Build Coastguard Workerexit: 434*9880d681SAndroid Build Coastguard Worker ret void 435*9880d681SAndroid Build Coastguard Worker} 436*9880d681SAndroid Build Coastguard Worker 437*9880d681SAndroid Build Coastguard Workerdefine void @test6_inlinee() alwaysinline personality void ()* @ProcessCLRException { 438*9880d681SAndroid Build Coastguard Workerentry: 439*9880d681SAndroid Build Coastguard Worker invoke void @g() 440*9880d681SAndroid Build Coastguard Worker to label %exit unwind label %inlinee_cleanup 441*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %callsite_parent.pad) ] 442*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %[[inlinee_cleanup:.+]] 443*9880d681SAndroid Build Coastguard Worker 444*9880d681SAndroid Build Coastguard Workerinlinee_cleanup: 445*9880d681SAndroid Build Coastguard Worker %inlinee.pad = cleanuppad within none [] 446*9880d681SAndroid Build Coastguard Worker call void @g() [ "funclet"(token %inlinee.pad) ] 447*9880d681SAndroid Build Coastguard Worker unreachable 448*9880d681SAndroid Build Coastguard Worker; CHECK: [[inlinee_cleanup]]: 449*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[inlinee_pad:[^ ]+]] = cleanuppad within %callsite_parent.pad 450*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[inlinee_pad]]) ] 451*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unwind label %cleanup{{$}} 452*9880d681SAndroid Build Coastguard Worker 453*9880d681SAndroid Build Coastguard Workerexit: 454*9880d681SAndroid Build Coastguard Worker ret void 455*9880d681SAndroid Build Coastguard Worker} 456