1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -simplifycfg -S | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Worker; ModuleID = 'cppeh-simplify.cpp' 4*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" 5*9880d681SAndroid Build Coastguard Workertarget triple = "x86_64-pc-windows-msvc18.0.0" 6*9880d681SAndroid Build Coastguard Worker 7*9880d681SAndroid Build Coastguard Worker 8*9880d681SAndroid Build Coastguard Worker; This case arises when two objects with empty destructors are cleaned up. 9*9880d681SAndroid Build Coastguard Worker; 10*9880d681SAndroid Build Coastguard Worker; void f1() { 11*9880d681SAndroid Build Coastguard Worker; S a; 12*9880d681SAndroid Build Coastguard Worker; S b; 13*9880d681SAndroid Build Coastguard Worker; g(); 14*9880d681SAndroid Build Coastguard Worker; } 15*9880d681SAndroid Build Coastguard Worker; 16*9880d681SAndroid Build Coastguard Worker; In this case, both cleanup pads can be eliminated and the invoke can be 17*9880d681SAndroid Build Coastguard Worker; converted to a call. 18*9880d681SAndroid Build Coastguard Worker; 19*9880d681SAndroid Build Coastguard Worker; CHECK: define void @f1() 20*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 21*9880d681SAndroid Build Coastguard Worker; CHECK: call void @g() 22*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 23*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad 24*9880d681SAndroid Build Coastguard Worker; CHECK: } 25*9880d681SAndroid Build Coastguard Worker; 26*9880d681SAndroid Build Coastguard Workerdefine void @f1() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 27*9880d681SAndroid Build Coastguard Workerentry: 28*9880d681SAndroid Build Coastguard Worker invoke void @g() to label %invoke.cont unwind label %ehcleanup 29*9880d681SAndroid Build Coastguard Worker 30*9880d681SAndroid Build Coastguard Workerinvoke.cont: ; preds = %entry 31*9880d681SAndroid Build Coastguard Worker ret void 32*9880d681SAndroid Build Coastguard Worker 33*9880d681SAndroid Build Coastguard Workerehcleanup: ; preds = %entry 34*9880d681SAndroid Build Coastguard Worker %0 = cleanuppad within none [] 35*9880d681SAndroid Build Coastguard Worker cleanupret from %0 unwind label %ehcleanup.1 36*9880d681SAndroid Build Coastguard Worker 37*9880d681SAndroid Build Coastguard Workerehcleanup.1: ; preds = %ehcleanup 38*9880d681SAndroid Build Coastguard Worker %1 = cleanuppad within none [] 39*9880d681SAndroid Build Coastguard Worker cleanupret from %1 unwind to caller 40*9880d681SAndroid Build Coastguard Worker} 41*9880d681SAndroid Build Coastguard Worker 42*9880d681SAndroid Build Coastguard Worker 43*9880d681SAndroid Build Coastguard Worker; This case arises when an object with an empty destructor must be cleaned up 44*9880d681SAndroid Build Coastguard Worker; outside of a try-block and an object with a non-empty destructor must be 45*9880d681SAndroid Build Coastguard Worker; cleaned up within the try-block. 46*9880d681SAndroid Build Coastguard Worker; 47*9880d681SAndroid Build Coastguard Worker; void f2() { 48*9880d681SAndroid Build Coastguard Worker; S a; 49*9880d681SAndroid Build Coastguard Worker; try { 50*9880d681SAndroid Build Coastguard Worker; S2 b; 51*9880d681SAndroid Build Coastguard Worker; g(); 52*9880d681SAndroid Build Coastguard Worker; } catch (...) {} 53*9880d681SAndroid Build Coastguard Worker; } 54*9880d681SAndroid Build Coastguard Worker; 55*9880d681SAndroid Build Coastguard Worker; In this case, the outermost cleanup pad can be eliminated and the catch block 56*9880d681SAndroid Build Coastguard Worker; should unwind to the caller (that is, exception handling continues with the 57*9880d681SAndroid Build Coastguard Worker; parent frame of the caller). 58*9880d681SAndroid Build Coastguard Worker; 59*9880d681SAndroid Build Coastguard Worker; CHECK: define void @f2() 60*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 61*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 62*9880d681SAndroid Build Coastguard Worker; CHECK: ehcleanup: 63*9880d681SAndroid Build Coastguard Worker; CHECK: cleanuppad within none 64*9880d681SAndroid Build Coastguard Worker; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b) 65*9880d681SAndroid Build Coastguard Worker; CHECK: cleanupret from %0 unwind label %catch.dispatch 66*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch: 67*9880d681SAndroid Build Coastguard Worker; CHECK: catchswitch within none [label %catch] unwind to caller 68*9880d681SAndroid Build Coastguard Worker; CHECK: catch: 69*9880d681SAndroid Build Coastguard Worker; CHECK: catchpad 70*9880d681SAndroid Build Coastguard Worker; CHECK: catchret 71*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad 72*9880d681SAndroid Build Coastguard Worker; CHECK: } 73*9880d681SAndroid Build Coastguard Worker; 74*9880d681SAndroid Build Coastguard Workerdefine void @f2() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 75*9880d681SAndroid Build Coastguard Workerentry: 76*9880d681SAndroid Build Coastguard Worker %b = alloca %struct.S2, align 1 77*9880d681SAndroid Build Coastguard Worker invoke void @g() to label %invoke.cont unwind label %ehcleanup 78*9880d681SAndroid Build Coastguard Worker 79*9880d681SAndroid Build Coastguard Workerinvoke.cont: ; preds = %entry 80*9880d681SAndroid Build Coastguard Worker br label %try.cont 81*9880d681SAndroid Build Coastguard Worker 82*9880d681SAndroid Build Coastguard Workerehcleanup: ; preds = %entry 83*9880d681SAndroid Build Coastguard Worker %0 = cleanuppad within none [] 84*9880d681SAndroid Build Coastguard Worker call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b) 85*9880d681SAndroid Build Coastguard Worker cleanupret from %0 unwind label %catch.dispatch 86*9880d681SAndroid Build Coastguard Worker 87*9880d681SAndroid Build Coastguard Workercatch.dispatch: ; preds = %ehcleanup 88*9880d681SAndroid Build Coastguard Worker %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1 89*9880d681SAndroid Build Coastguard Worker 90*9880d681SAndroid Build Coastguard Workercatch: ; preds = %catch.dispatch 91*9880d681SAndroid Build Coastguard Worker %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] 92*9880d681SAndroid Build Coastguard Worker catchret from %1 to label %catchret.dest 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Workercatchret.dest: ; preds = %catch 95*9880d681SAndroid Build Coastguard Worker br label %try.cont 96*9880d681SAndroid Build Coastguard Worker 97*9880d681SAndroid Build Coastguard Workertry.cont: ; preds = %catchret.dest, %invoke.cont 98*9880d681SAndroid Build Coastguard Worker ret void 99*9880d681SAndroid Build Coastguard Worker 100*9880d681SAndroid Build Coastguard Workerehcleanup.1: 101*9880d681SAndroid Build Coastguard Worker %2 = cleanuppad within none [] 102*9880d681SAndroid Build Coastguard Worker cleanupret from %2 unwind to caller 103*9880d681SAndroid Build Coastguard Worker} 104*9880d681SAndroid Build Coastguard Worker 105*9880d681SAndroid Build Coastguard Worker 106*9880d681SAndroid Build Coastguard Worker; This case arises when an object with a non-empty destructor must be cleaned up 107*9880d681SAndroid Build Coastguard Worker; outside of a try-block and an object with an empty destructor must be cleaned 108*9880d681SAndroid Build Coastguard Worker; within the try-block. 109*9880d681SAndroid Build Coastguard Worker; 110*9880d681SAndroid Build Coastguard Worker; void f3() { 111*9880d681SAndroid Build Coastguard Worker; S2 a; 112*9880d681SAndroid Build Coastguard Worker; try { 113*9880d681SAndroid Build Coastguard Worker; S b; 114*9880d681SAndroid Build Coastguard Worker; g(); 115*9880d681SAndroid Build Coastguard Worker; } catch (...) {} 116*9880d681SAndroid Build Coastguard Worker; } 117*9880d681SAndroid Build Coastguard Worker; 118*9880d681SAndroid Build Coastguard Worker; In this case the inner cleanup pad should be eliminated and the invoke of g() 119*9880d681SAndroid Build Coastguard Worker; should unwind directly to the catchpad. 120*9880d681SAndroid Build Coastguard Worker; 121*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f3() 122*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 123*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 124*9880d681SAndroid Build Coastguard Worker; CHECK: to label %try.cont unwind label %catch.dispatch 125*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch: 126*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: catchswitch within none [label %catch] unwind label %ehcleanup.1 127*9880d681SAndroid Build Coastguard Worker; CHECK: catch: 128*9880d681SAndroid Build Coastguard Worker; CHECK: catchpad within %cs1 [i8* null, i32 64, i8* null] 129*9880d681SAndroid Build Coastguard Worker; CHECK: catchret 130*9880d681SAndroid Build Coastguard Worker; CHECK: ehcleanup.1: 131*9880d681SAndroid Build Coastguard Worker; CHECK: cleanuppad 132*9880d681SAndroid Build Coastguard Worker; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) 133*9880d681SAndroid Build Coastguard Worker; CHECK: cleanupret from %cp3 unwind to caller 134*9880d681SAndroid Build Coastguard Worker; CHECK: } 135*9880d681SAndroid Build Coastguard Worker; 136*9880d681SAndroid Build Coastguard Workerdefine void @f3() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 137*9880d681SAndroid Build Coastguard Workerentry: 138*9880d681SAndroid Build Coastguard Worker %a = alloca %struct.S2, align 1 139*9880d681SAndroid Build Coastguard Worker invoke void @g() to label %invoke.cont unwind label %ehcleanup 140*9880d681SAndroid Build Coastguard Worker 141*9880d681SAndroid Build Coastguard Workerinvoke.cont: ; preds = %entry 142*9880d681SAndroid Build Coastguard Worker br label %try.cont 143*9880d681SAndroid Build Coastguard Worker 144*9880d681SAndroid Build Coastguard Workerehcleanup: ; preds = %entry 145*9880d681SAndroid Build Coastguard Worker %0 = cleanuppad within none [] 146*9880d681SAndroid Build Coastguard Worker cleanupret from %0 unwind label %catch.dispatch 147*9880d681SAndroid Build Coastguard Worker 148*9880d681SAndroid Build Coastguard Workercatch.dispatch: ; preds = %ehcleanup 149*9880d681SAndroid Build Coastguard Worker %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Workercatch: ; preds = %catch.dispatch 152*9880d681SAndroid Build Coastguard Worker %cp2 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] 153*9880d681SAndroid Build Coastguard Worker catchret from %cp2 to label %catchret.dest 154*9880d681SAndroid Build Coastguard Worker 155*9880d681SAndroid Build Coastguard Workercatchret.dest: ; preds = %catch 156*9880d681SAndroid Build Coastguard Worker br label %try.cont 157*9880d681SAndroid Build Coastguard Worker 158*9880d681SAndroid Build Coastguard Workertry.cont: ; preds = %catchret.dest, %invoke.cont 159*9880d681SAndroid Build Coastguard Worker ret void 160*9880d681SAndroid Build Coastguard Worker 161*9880d681SAndroid Build Coastguard Workerehcleanup.1: 162*9880d681SAndroid Build Coastguard Worker %cp3 = cleanuppad within none [] 163*9880d681SAndroid Build Coastguard Worker call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) 164*9880d681SAndroid Build Coastguard Worker cleanupret from %cp3 unwind to caller 165*9880d681SAndroid Build Coastguard Worker} 166*9880d681SAndroid Build Coastguard Worker 167*9880d681SAndroid Build Coastguard Worker 168*9880d681SAndroid Build Coastguard Worker; This case arises when an object with an empty destructor may require cleanup 169*9880d681SAndroid Build Coastguard Worker; from either inside or outside of a try-block. 170*9880d681SAndroid Build Coastguard Worker; 171*9880d681SAndroid Build Coastguard Worker; void f4() { 172*9880d681SAndroid Build Coastguard Worker; S a; 173*9880d681SAndroid Build Coastguard Worker; g(); 174*9880d681SAndroid Build Coastguard Worker; try { 175*9880d681SAndroid Build Coastguard Worker; g(); 176*9880d681SAndroid Build Coastguard Worker; } catch (...) {} 177*9880d681SAndroid Build Coastguard Worker; } 178*9880d681SAndroid Build Coastguard Worker; 179*9880d681SAndroid Build Coastguard Worker; In this case, the cleanuppad should be eliminated, the invoke outside of the 180*9880d681SAndroid Build Coastguard Worker; catch block should be converted to a call (that is, that is, exception 181*9880d681SAndroid Build Coastguard Worker; handling continues with the parent frame of the caller).) 182*9880d681SAndroid Build Coastguard Worker; 183*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f4() 184*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 185*9880d681SAndroid Build Coastguard Worker; CHECK: call void @g 186*9880d681SAndroid Build Coastguard Worker; Note: The cleanuppad simplification will insert an unconditional branch here 187*9880d681SAndroid Build Coastguard Worker; but it will be eliminated, placing the following invoke in the entry BB. 188*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 189*9880d681SAndroid Build Coastguard Worker; CHECK: to label %try.cont unwind label %catch.dispatch 190*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch: 191*9880d681SAndroid Build Coastguard Worker; CHECK: catchswitch within none [label %catch] unwind to caller 192*9880d681SAndroid Build Coastguard Worker; CHECK: catch: 193*9880d681SAndroid Build Coastguard Worker; CHECK: catchpad 194*9880d681SAndroid Build Coastguard Worker; CHECK: catchret 195*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad 196*9880d681SAndroid Build Coastguard Worker; CHECK: } 197*9880d681SAndroid Build Coastguard Worker; 198*9880d681SAndroid Build Coastguard Workerdefine void @f4() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 199*9880d681SAndroid Build Coastguard Workerentry: 200*9880d681SAndroid Build Coastguard Worker invoke void @g() 201*9880d681SAndroid Build Coastguard Worker to label %invoke.cont unwind label %ehcleanup 202*9880d681SAndroid Build Coastguard Worker 203*9880d681SAndroid Build Coastguard Workerinvoke.cont: ; preds = %entry 204*9880d681SAndroid Build Coastguard Worker invoke void @g() 205*9880d681SAndroid Build Coastguard Worker to label %try.cont unwind label %catch.dispatch 206*9880d681SAndroid Build Coastguard Worker 207*9880d681SAndroid Build Coastguard Workercatch.dispatch: ; preds = %invoke.cont 208*9880d681SAndroid Build Coastguard Worker %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup 209*9880d681SAndroid Build Coastguard Worker 210*9880d681SAndroid Build Coastguard Workercatch: ; preds = %catch.dispatch 211*9880d681SAndroid Build Coastguard Worker %0 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] 212*9880d681SAndroid Build Coastguard Worker catchret from %0 to label %try.cont 213*9880d681SAndroid Build Coastguard Worker 214*9880d681SAndroid Build Coastguard Workertry.cont: ; preds = %catch, %invoke.cont 215*9880d681SAndroid Build Coastguard Worker ret void 216*9880d681SAndroid Build Coastguard Worker 217*9880d681SAndroid Build Coastguard Workerehcleanup: 218*9880d681SAndroid Build Coastguard Worker %cp2 = cleanuppad within none [] 219*9880d681SAndroid Build Coastguard Worker cleanupret from %cp2 unwind to caller 220*9880d681SAndroid Build Coastguard Worker} 221*9880d681SAndroid Build Coastguard Worker 222*9880d681SAndroid Build Coastguard Worker; This case tests simplification of an otherwise empty cleanup pad that contains 223*9880d681SAndroid Build Coastguard Worker; a PHI node. 224*9880d681SAndroid Build Coastguard Worker; 225*9880d681SAndroid Build Coastguard Worker; int f6() { 226*9880d681SAndroid Build Coastguard Worker; int state = 1; 227*9880d681SAndroid Build Coastguard Worker; try { 228*9880d681SAndroid Build Coastguard Worker; S a; 229*9880d681SAndroid Build Coastguard Worker; g(); 230*9880d681SAndroid Build Coastguard Worker; state = 2; 231*9880d681SAndroid Build Coastguard Worker; g(); 232*9880d681SAndroid Build Coastguard Worker; } catch (...) { 233*9880d681SAndroid Build Coastguard Worker; return state; 234*9880d681SAndroid Build Coastguard Worker; } 235*9880d681SAndroid Build Coastguard Worker; return 0; 236*9880d681SAndroid Build Coastguard Worker; } 237*9880d681SAndroid Build Coastguard Worker; 238*9880d681SAndroid Build Coastguard Worker; In this case, the cleanup pad should be eliminated and the PHI node in the 239*9880d681SAndroid Build Coastguard Worker; cleanup pad should be sunk into the catch dispatch block. 240*9880d681SAndroid Build Coastguard Worker; 241*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i32 @f6() 242*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 243*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 244*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont: 245*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 246*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ehcleanup: 247*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad 248*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch: 249*9880d681SAndroid Build Coastguard Worker; CHECK: %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] 250*9880d681SAndroid Build Coastguard Worker; CHECK: } 251*9880d681SAndroid Build Coastguard Workerdefine i32 @f6() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 252*9880d681SAndroid Build Coastguard Workerentry: 253*9880d681SAndroid Build Coastguard Worker invoke void @g() 254*9880d681SAndroid Build Coastguard Worker to label %invoke.cont unwind label %ehcleanup 255*9880d681SAndroid Build Coastguard Worker 256*9880d681SAndroid Build Coastguard Workerinvoke.cont: ; preds = %entry 257*9880d681SAndroid Build Coastguard Worker invoke void @g() 258*9880d681SAndroid Build Coastguard Worker to label %return unwind label %ehcleanup 259*9880d681SAndroid Build Coastguard Worker 260*9880d681SAndroid Build Coastguard Workerehcleanup: ; preds = %invoke.cont, %entry 261*9880d681SAndroid Build Coastguard Worker %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] 262*9880d681SAndroid Build Coastguard Worker %0 = cleanuppad within none [] 263*9880d681SAndroid Build Coastguard Worker cleanupret from %0 unwind label %catch.dispatch 264*9880d681SAndroid Build Coastguard Worker 265*9880d681SAndroid Build Coastguard Workercatch.dispatch: ; preds = %ehcleanup 266*9880d681SAndroid Build Coastguard Worker %cs1 = catchswitch within none [label %catch] unwind to caller 267*9880d681SAndroid Build Coastguard Worker 268*9880d681SAndroid Build Coastguard Workercatch: ; preds = %catch.dispatch 269*9880d681SAndroid Build Coastguard Worker %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] 270*9880d681SAndroid Build Coastguard Worker catchret from %1 to label %return 271*9880d681SAndroid Build Coastguard Worker 272*9880d681SAndroid Build Coastguard Workerreturn: ; preds = %invoke.cont, %catch 273*9880d681SAndroid Build Coastguard Worker %retval.0 = phi i32 [ %state.0, %catch ], [ 0, %invoke.cont ] 274*9880d681SAndroid Build Coastguard Worker ret i32 %retval.0 275*9880d681SAndroid Build Coastguard Worker} 276*9880d681SAndroid Build Coastguard Worker 277*9880d681SAndroid Build Coastguard Worker; This case tests another variation of simplification of an otherwise empty 278*9880d681SAndroid Build Coastguard Worker; cleanup pad that contains a PHI node. 279*9880d681SAndroid Build Coastguard Worker; 280*9880d681SAndroid Build Coastguard Worker; int f7() { 281*9880d681SAndroid Build Coastguard Worker; int state = 1; 282*9880d681SAndroid Build Coastguard Worker; try { 283*9880d681SAndroid Build Coastguard Worker; g(); 284*9880d681SAndroid Build Coastguard Worker; state = 2; 285*9880d681SAndroid Build Coastguard Worker; S a; 286*9880d681SAndroid Build Coastguard Worker; g(); 287*9880d681SAndroid Build Coastguard Worker; state = 3; 288*9880d681SAndroid Build Coastguard Worker; g(); 289*9880d681SAndroid Build Coastguard Worker; } catch (...) { 290*9880d681SAndroid Build Coastguard Worker; return state; 291*9880d681SAndroid Build Coastguard Worker; } 292*9880d681SAndroid Build Coastguard Worker; return 0; 293*9880d681SAndroid Build Coastguard Worker; } 294*9880d681SAndroid Build Coastguard Worker; 295*9880d681SAndroid Build Coastguard Worker; In this case, the cleanup pad should be eliminated and the PHI node in the 296*9880d681SAndroid Build Coastguard Worker; cleanup pad should be merged with the PHI node in the catch dispatch block. 297*9880d681SAndroid Build Coastguard Worker; 298*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i32 @f7() 299*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 300*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 301*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont: 302*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 303*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont.1: 304*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 305*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ehcleanup: 306*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad 307*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch: 308*9880d681SAndroid Build Coastguard Worker; CHECK: %state.1 = phi i32 [ 1, %entry ], [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ] 309*9880d681SAndroid Build Coastguard Worker; CHECK: } 310*9880d681SAndroid Build Coastguard Workerdefine i32 @f7() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 311*9880d681SAndroid Build Coastguard Workerentry: 312*9880d681SAndroid Build Coastguard Worker invoke void @g() 313*9880d681SAndroid Build Coastguard Worker to label %invoke.cont unwind label %catch.dispatch 314*9880d681SAndroid Build Coastguard Worker 315*9880d681SAndroid Build Coastguard Workerinvoke.cont: ; preds = %entry 316*9880d681SAndroid Build Coastguard Worker invoke void @g() 317*9880d681SAndroid Build Coastguard Worker to label %invoke.cont.1 unwind label %ehcleanup 318*9880d681SAndroid Build Coastguard Worker 319*9880d681SAndroid Build Coastguard Workerinvoke.cont.1: ; preds = %invoke.cont 320*9880d681SAndroid Build Coastguard Worker invoke void @g() 321*9880d681SAndroid Build Coastguard Worker to label %return unwind label %ehcleanup 322*9880d681SAndroid Build Coastguard Worker 323*9880d681SAndroid Build Coastguard Workerehcleanup: ; preds = %invoke.cont.1, %invoke.cont 324*9880d681SAndroid Build Coastguard Worker %state.0 = phi i32 [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ] 325*9880d681SAndroid Build Coastguard Worker %0 = cleanuppad within none [] 326*9880d681SAndroid Build Coastguard Worker cleanupret from %0 unwind label %catch.dispatch 327*9880d681SAndroid Build Coastguard Worker 328*9880d681SAndroid Build Coastguard Workercatch.dispatch: ; preds = %ehcleanup, %entry 329*9880d681SAndroid Build Coastguard Worker %state.1 = phi i32 [ %state.0, %ehcleanup ], [ 1, %entry ] 330*9880d681SAndroid Build Coastguard Worker %cs1 = catchswitch within none [label %catch] unwind to caller 331*9880d681SAndroid Build Coastguard Worker 332*9880d681SAndroid Build Coastguard Workercatch: ; preds = %catch.dispatch 333*9880d681SAndroid Build Coastguard Worker %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] 334*9880d681SAndroid Build Coastguard Worker catchret from %1 to label %return 335*9880d681SAndroid Build Coastguard Worker 336*9880d681SAndroid Build Coastguard Workerreturn: ; preds = %invoke.cont.1, %catch 337*9880d681SAndroid Build Coastguard Worker %retval.0 = phi i32 [ %state.1, %catch ], [ 0, %invoke.cont.1 ] 338*9880d681SAndroid Build Coastguard Worker ret i32 %retval.0 339*9880d681SAndroid Build Coastguard Worker} 340*9880d681SAndroid Build Coastguard Worker 341*9880d681SAndroid Build Coastguard Worker; This case tests a scenario where an empty cleanup pad is not dominated by all 342*9880d681SAndroid Build Coastguard Worker; of the predecessors of its successor, but the successor references a PHI node 343*9880d681SAndroid Build Coastguard Worker; in the empty cleanup pad. 344*9880d681SAndroid Build Coastguard Worker; 345*9880d681SAndroid Build Coastguard Worker; Conceptually, the case being modeled is something like this: 346*9880d681SAndroid Build Coastguard Worker; 347*9880d681SAndroid Build Coastguard Worker; int f8() { 348*9880d681SAndroid Build Coastguard Worker; int x = 1; 349*9880d681SAndroid Build Coastguard Worker; try { 350*9880d681SAndroid Build Coastguard Worker; S a; 351*9880d681SAndroid Build Coastguard Worker; g(); 352*9880d681SAndroid Build Coastguard Worker; x = 2; 353*9880d681SAndroid Build Coastguard Worker; retry: 354*9880d681SAndroid Build Coastguard Worker; g(); 355*9880d681SAndroid Build Coastguard Worker; return 356*9880d681SAndroid Build Coastguard Worker; } catch (...) { 357*9880d681SAndroid Build Coastguard Worker; use_x(x); 358*9880d681SAndroid Build Coastguard Worker; } 359*9880d681SAndroid Build Coastguard Worker; goto retry; 360*9880d681SAndroid Build Coastguard Worker; } 361*9880d681SAndroid Build Coastguard Worker; 362*9880d681SAndroid Build Coastguard Worker; While that C++ syntax isn't legal, the IR below is. 363*9880d681SAndroid Build Coastguard Worker; 364*9880d681SAndroid Build Coastguard Worker; In this case, the PHI node that is sunk from ehcleanup to catch.dispatch 365*9880d681SAndroid Build Coastguard Worker; should have an incoming value entry for path from 'foo' that references the 366*9880d681SAndroid Build Coastguard Worker; PHI node itself. 367*9880d681SAndroid Build Coastguard Worker; 368*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f8() 369*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 370*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 371*9880d681SAndroid Build Coastguard Worker; CHECK: invoke.cont: 372*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @g() 373*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ehcleanup: 374*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad 375*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch: 376*9880d681SAndroid Build Coastguard Worker; CHECK: %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ], [ %x, %catch.cont ] 377*9880d681SAndroid Build Coastguard Worker; CHECK: } 378*9880d681SAndroid Build Coastguard Workerdefine void @f8() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 379*9880d681SAndroid Build Coastguard Workerentry: 380*9880d681SAndroid Build Coastguard Worker invoke void @g() 381*9880d681SAndroid Build Coastguard Worker to label %invoke.cont unwind label %ehcleanup 382*9880d681SAndroid Build Coastguard Worker 383*9880d681SAndroid Build Coastguard Workerinvoke.cont: ; preds = %entry 384*9880d681SAndroid Build Coastguard Worker invoke void @g() 385*9880d681SAndroid Build Coastguard Worker to label %return unwind label %ehcleanup 386*9880d681SAndroid Build Coastguard Worker 387*9880d681SAndroid Build Coastguard Workerehcleanup: ; preds = %invoke.cont, %entry 388*9880d681SAndroid Build Coastguard Worker %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] 389*9880d681SAndroid Build Coastguard Worker %0 = cleanuppad within none [] 390*9880d681SAndroid Build Coastguard Worker cleanupret from %0 unwind label %catch.dispatch 391*9880d681SAndroid Build Coastguard Worker 392*9880d681SAndroid Build Coastguard Workercatch.dispatch: ; preds = %ehcleanup, %catch.cont 393*9880d681SAndroid Build Coastguard Worker %cs1 = catchswitch within none [label %catch] unwind to caller 394*9880d681SAndroid Build Coastguard Worker 395*9880d681SAndroid Build Coastguard Workercatch: ; preds = %catch.dispatch 396*9880d681SAndroid Build Coastguard Worker %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] 397*9880d681SAndroid Build Coastguard Worker call void @use_x(i32 %x) 398*9880d681SAndroid Build Coastguard Worker catchret from %1 to label %catch.cont 399*9880d681SAndroid Build Coastguard Worker 400*9880d681SAndroid Build Coastguard Workercatch.cont: ; preds = %catch 401*9880d681SAndroid Build Coastguard Worker invoke void @g() 402*9880d681SAndroid Build Coastguard Worker to label %return unwind label %catch.dispatch 403*9880d681SAndroid Build Coastguard Worker 404*9880d681SAndroid Build Coastguard Workerreturn: ; preds = %invoke.cont, %catch.cont 405*9880d681SAndroid Build Coastguard Worker ret void 406*9880d681SAndroid Build Coastguard Worker} 407*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i32 @f9() 408*9880d681SAndroid Build Coastguard Worker; CHECK: entry: 409*9880d681SAndroid Build Coastguard Worker; CHECK: invoke void @"\01??1S2@@QEAA@XZ"( 410*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: cleanuppad 411*9880d681SAndroid Build Coastguard Worker; CHECK: catch.dispatch: 412*9880d681SAndroid Build Coastguard Worker; CHECK: } 413*9880d681SAndroid Build Coastguard Workerdefine i32 @f9() personality i32 (...)* @__CxxFrameHandler3 { 414*9880d681SAndroid Build Coastguard Workerentry: 415*9880d681SAndroid Build Coastguard Worker %s = alloca i8, align 1 416*9880d681SAndroid Build Coastguard Worker call void @llvm.lifetime.start(i64 1, i8* nonnull %s) 417*9880d681SAndroid Build Coastguard Worker %bc = bitcast i8* %s to %struct.S2* 418*9880d681SAndroid Build Coastguard Worker invoke void @"\01??1S2@@QEAA@XZ"(%struct.S2* %bc) 419*9880d681SAndroid Build Coastguard Worker to label %try.cont unwind label %ehcleanup 420*9880d681SAndroid Build Coastguard Worker 421*9880d681SAndroid Build Coastguard Workerehcleanup: 422*9880d681SAndroid Build Coastguard Worker %cleanup.pad = cleanuppad within none [] 423*9880d681SAndroid Build Coastguard Worker call void @llvm.lifetime.end(i64 1, i8* nonnull %s) 424*9880d681SAndroid Build Coastguard Worker cleanupret from %cleanup.pad unwind label %catch.dispatch 425*9880d681SAndroid Build Coastguard Worker 426*9880d681SAndroid Build Coastguard Workercatch.dispatch: 427*9880d681SAndroid Build Coastguard Worker %catch.switch = catchswitch within none [label %catch] unwind to caller 428*9880d681SAndroid Build Coastguard Worker 429*9880d681SAndroid Build Coastguard Workercatch: 430*9880d681SAndroid Build Coastguard Worker %catch.pad = catchpad within %catch.switch [i8* null, i32 0, i8* null] 431*9880d681SAndroid Build Coastguard Worker catchret from %catch.pad to label %try.cont 432*9880d681SAndroid Build Coastguard Worker 433*9880d681SAndroid Build Coastguard Workertry.cont: 434*9880d681SAndroid Build Coastguard Worker ret i32 0 435*9880d681SAndroid Build Coastguard Worker} 436*9880d681SAndroid Build Coastguard Worker 437*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @f10( 438*9880d681SAndroid Build Coastguard Workerdefine void @f10(i32 %V) personality i32 (...)* @__CxxFrameHandler3 { 439*9880d681SAndroid Build Coastguard Workerentry: 440*9880d681SAndroid Build Coastguard Worker invoke void @g() 441*9880d681SAndroid Build Coastguard Worker to label %unreachable unwind label %cleanup 442*9880d681SAndroid Build Coastguard Worker; CHECK: call void @g() 443*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: unreachable 444*9880d681SAndroid Build Coastguard Worker 445*9880d681SAndroid Build Coastguard Workerunreachable: 446*9880d681SAndroid Build Coastguard Worker unreachable 447*9880d681SAndroid Build Coastguard Worker 448*9880d681SAndroid Build Coastguard Workercleanup: 449*9880d681SAndroid Build Coastguard Worker %cp = cleanuppad within none [] 450*9880d681SAndroid Build Coastguard Worker switch i32 %V, label %cleanupret1 [ 451*9880d681SAndroid Build Coastguard Worker i32 0, label %cleanupret2 452*9880d681SAndroid Build Coastguard Worker ] 453*9880d681SAndroid Build Coastguard Worker 454*9880d681SAndroid Build Coastguard Workercleanupret1: 455*9880d681SAndroid Build Coastguard Worker cleanupret from %cp unwind to caller 456*9880d681SAndroid Build Coastguard Worker 457*9880d681SAndroid Build Coastguard Workercleanupret2: 458*9880d681SAndroid Build Coastguard Worker cleanupret from %cp unwind to caller 459*9880d681SAndroid Build Coastguard Worker} 460*9880d681SAndroid Build Coastguard Worker 461*9880d681SAndroid Build Coastguard Worker%struct.S = type { i8 } 462*9880d681SAndroid Build Coastguard Worker%struct.S2 = type { i8 } 463*9880d681SAndroid Build Coastguard Workerdeclare void @"\01??1S2@@QEAA@XZ"(%struct.S2*) 464*9880d681SAndroid Build Coastguard Workerdeclare void @g() 465*9880d681SAndroid Build Coastguard Workerdeclare void @use_x(i32 %x) 466*9880d681SAndroid Build Coastguard Worker 467*9880d681SAndroid Build Coastguard Workerdeclare i32 @__CxxFrameHandler3(...) 468*9880d681SAndroid Build Coastguard Worker 469*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.start(i64, i8* nocapture) 470*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.end(i64, i8* nocapture) 471