1*9880d681SAndroid Build Coastguard Worker; RUN: opt -S -guard-widening < %s | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker; RUN: opt -S -passes=guard-widening < %s | FileCheck %s 3*9880d681SAndroid Build Coastguard Worker 4*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.experimental.guard(i1,...) 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Worker; Basic test case: we wide the first check to check both the 7*9880d681SAndroid Build Coastguard Worker; conditions. 8*9880d681SAndroid Build Coastguard Workerdefine void @f_0(i1 %cond_0, i1 %cond_1) { 9*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_0( 10*9880d681SAndroid Build Coastguard Workerentry: 11*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %cond_0, %cond_1 12*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 13*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 16*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 17*9880d681SAndroid Build Coastguard Worker ret void 18*9880d681SAndroid Build Coastguard Worker} 19*9880d681SAndroid Build Coastguard Worker 20*9880d681SAndroid Build Coastguard Worker; Same as @f_0, but with using a more general notion of postdominance. 21*9880d681SAndroid Build Coastguard Workerdefine void @f_1(i1 %cond_0, i1 %cond_1) { 22*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_1( 23*9880d681SAndroid Build Coastguard Workerentry: 24*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %cond_0, %cond_1 25*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 26*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %left, label %right 27*9880d681SAndroid Build Coastguard Worker 28*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 29*9880d681SAndroid Build Coastguard Worker br i1 undef, label %left, label %right 30*9880d681SAndroid Build Coastguard Worker 31*9880d681SAndroid Build Coastguard Workerleft: 32*9880d681SAndroid Build Coastguard Worker br label %merge 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Workerright: 35*9880d681SAndroid Build Coastguard Worker br label %merge 36*9880d681SAndroid Build Coastguard Worker 37*9880d681SAndroid Build Coastguard Workermerge: 38*9880d681SAndroid Build Coastguard Worker; CHECK: merge: 39*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: call void (i1, ...) @llvm.experimental.guard( 40*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 41*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 42*9880d681SAndroid Build Coastguard Worker ret void 43*9880d681SAndroid Build Coastguard Worker} 44*9880d681SAndroid Build Coastguard Worker 45*9880d681SAndroid Build Coastguard Worker; Like @f_1, but we have some code we need to hoist before we can 46*9880d681SAndroid Build Coastguard Worker; widen a dominanting check. 47*9880d681SAndroid Build Coastguard Workerdefine void @f_2(i32 %a, i32 %b) { 48*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_2( 49*9880d681SAndroid Build Coastguard Workerentry: 50*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_0 = icmp ult i32 %a, 10 51*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_1 = icmp ult i32 %b, 10 52*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %cond_0, %cond_1 53*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 54*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %left, label %right 55*9880d681SAndroid Build Coastguard Worker 56*9880d681SAndroid Build Coastguard Worker %cond_0 = icmp ult i32 %a, 10 57*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 58*9880d681SAndroid Build Coastguard Worker br i1 undef, label %left, label %right 59*9880d681SAndroid Build Coastguard Worker 60*9880d681SAndroid Build Coastguard Workerleft: 61*9880d681SAndroid Build Coastguard Worker br label %merge 62*9880d681SAndroid Build Coastguard Worker 63*9880d681SAndroid Build Coastguard Workerright: 64*9880d681SAndroid Build Coastguard Worker br label %merge 65*9880d681SAndroid Build Coastguard Worker 66*9880d681SAndroid Build Coastguard Workermerge: 67*9880d681SAndroid Build Coastguard Worker %cond_1 = icmp ult i32 %b, 10 68*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 69*9880d681SAndroid Build Coastguard Worker ret void 70*9880d681SAndroid Build Coastguard Worker} 71*9880d681SAndroid Build Coastguard Worker 72*9880d681SAndroid Build Coastguard Worker; Negative test: don't hoist stuff out of control flow 73*9880d681SAndroid Build Coastguard Worker; indiscriminately, since that can make us do more work than needed. 74*9880d681SAndroid Build Coastguard Workerdefine void @f_3(i32 %a, i32 %b) { 75*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_3( 76*9880d681SAndroid Build Coastguard Workerentry: 77*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_0 = icmp ult i32 %a, 10 78*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 79*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %left, label %right 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Worker %cond_0 = icmp ult i32 %a, 10 82*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 83*9880d681SAndroid Build Coastguard Worker br i1 undef, label %left, label %right 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard Workerleft: 86*9880d681SAndroid Build Coastguard Worker; CHECK: left: 87*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_1 = icmp ult i32 %b, 10 88*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 89*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker %cond_1 = icmp ult i32 %b, 10 92*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 93*9880d681SAndroid Build Coastguard Worker ret void 94*9880d681SAndroid Build Coastguard Worker 95*9880d681SAndroid Build Coastguard Workerright: 96*9880d681SAndroid Build Coastguard Worker ret void 97*9880d681SAndroid Build Coastguard Worker} 98*9880d681SAndroid Build Coastguard Worker 99*9880d681SAndroid Build Coastguard Worker; But hoisting out of control flow is fine if it makes a loop computed 100*9880d681SAndroid Build Coastguard Worker; condition loop invariant. This behavior may require some tuning in 101*9880d681SAndroid Build Coastguard Worker; the future. 102*9880d681SAndroid Build Coastguard Workerdefine void @f_4(i32 %a, i32 %b) { 103*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_4( 104*9880d681SAndroid Build Coastguard Workerentry: 105*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_0 = icmp ult i32 %a, 10 106*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_1 = icmp ult i32 %b, 10 107*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %cond_0, %cond_1 108*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 109*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %loop, label %leave 110*9880d681SAndroid Build Coastguard Worker 111*9880d681SAndroid Build Coastguard Worker %cond_0 = icmp ult i32 %a, 10 112*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 113*9880d681SAndroid Build Coastguard Worker br i1 undef, label %loop, label %leave 114*9880d681SAndroid Build Coastguard Worker 115*9880d681SAndroid Build Coastguard Workerloop: 116*9880d681SAndroid Build Coastguard Worker %cond_1 = icmp ult i32 %b, 10 117*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 118*9880d681SAndroid Build Coastguard Worker br i1 undef, label %loop, label %leave 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Workerleave: 121*9880d681SAndroid Build Coastguard Worker ret void 122*9880d681SAndroid Build Coastguard Worker} 123*9880d681SAndroid Build Coastguard Worker 124*9880d681SAndroid Build Coastguard Worker; Hoisting out of control flow is also fine if we can widen the 125*9880d681SAndroid Build Coastguard Worker; dominating check without doing any extra work. 126*9880d681SAndroid Build Coastguard Workerdefine void @f_5(i32 %a) { 127*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_5( 128*9880d681SAndroid Build Coastguard Workerentry: 129*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = icmp uge i32 %a, 11 130*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 131*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %left, label %right 132*9880d681SAndroid Build Coastguard Worker 133*9880d681SAndroid Build Coastguard Worker %cond_0 = icmp ugt i32 %a, 7 134*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 135*9880d681SAndroid Build Coastguard Worker br i1 undef, label %left, label %right 136*9880d681SAndroid Build Coastguard Worker 137*9880d681SAndroid Build Coastguard Workerleft: 138*9880d681SAndroid Build Coastguard Worker %cond_1 = icmp ugt i32 %a, 10 139*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 140*9880d681SAndroid Build Coastguard Worker ret void 141*9880d681SAndroid Build Coastguard Worker 142*9880d681SAndroid Build Coastguard Workerright: 143*9880d681SAndroid Build Coastguard Worker ret void 144*9880d681SAndroid Build Coastguard Worker} 145*9880d681SAndroid Build Coastguard Worker 146*9880d681SAndroid Build Coastguard Worker; Negative test: the load from %a can be safely speculated to before 147*9880d681SAndroid Build Coastguard Worker; the first guard, but there is no guarantee that it will produce the 148*9880d681SAndroid Build Coastguard Worker; same value. 149*9880d681SAndroid Build Coastguard Workerdefine void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) { 150*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_6( 151*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard( 152*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard( 153*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 154*9880d681SAndroid Build Coastguard Workerentry: 155*9880d681SAndroid Build Coastguard Worker %cond_0 = load i1, i1* %a 156*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 157*9880d681SAndroid Build Coastguard Worker store i1 %unknown, i1* %b 158*9880d681SAndroid Build Coastguard Worker %cond_1 = load i1, i1* %a 159*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 160*9880d681SAndroid Build Coastguard Worker ret void 161*9880d681SAndroid Build Coastguard Worker} 162*9880d681SAndroid Build Coastguard Worker 163*9880d681SAndroid Build Coastguard Worker; All else equal, we try to widen the earliest guard we can. This 164*9880d681SAndroid Build Coastguard Worker; heuristic can use some tuning. 165*9880d681SAndroid Build Coastguard Workerdefine void @f_7(i32 %a, i1* %cond_buf) { 166*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_7( 167*9880d681SAndroid Build Coastguard Workerentry: 168*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_1 = load volatile i1, i1* %cond_buf 169*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_3 = icmp ult i32 %a, 7 170*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %cond_1, %cond_3 171*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 172*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_2 = load volatile i1, i1* %cond_buf 173*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ] 174*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %left, label %right 175*9880d681SAndroid Build Coastguard Worker 176*9880d681SAndroid Build Coastguard Worker %cond_1 = load volatile i1, i1* %cond_buf 177*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 178*9880d681SAndroid Build Coastguard Worker %cond_2 = load volatile i1, i1* %cond_buf 179*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ] 180*9880d681SAndroid Build Coastguard Worker br i1 undef, label %left, label %right 181*9880d681SAndroid Build Coastguard Worker 182*9880d681SAndroid Build Coastguard Workerleft: 183*9880d681SAndroid Build Coastguard Worker %cond_3 = icmp ult i32 %a, 7 184*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_3) [ "deopt"() ] 185*9880d681SAndroid Build Coastguard Worker br label %left 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard Workerright: 188*9880d681SAndroid Build Coastguard Worker ret void 189*9880d681SAndroid Build Coastguard Worker} 190*9880d681SAndroid Build Coastguard Worker 191*9880d681SAndroid Build Coastguard Worker; In this case the earliest dominating guard is in a loop, and we 192*9880d681SAndroid Build Coastguard Worker; don't want to put extra work in there. This heuristic can use some 193*9880d681SAndroid Build Coastguard Worker; tuning. 194*9880d681SAndroid Build Coastguard Workerdefine void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) { 195*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_8( 196*9880d681SAndroid Build Coastguard Workerentry: 197*9880d681SAndroid Build Coastguard Worker br label %loop 198*9880d681SAndroid Build Coastguard Worker 199*9880d681SAndroid Build Coastguard Workerloop: 200*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 201*9880d681SAndroid Build Coastguard Worker br i1 undef, label %loop, label %leave 202*9880d681SAndroid Build Coastguard Worker 203*9880d681SAndroid Build Coastguard Workerleave: 204*9880d681SAndroid Build Coastguard Worker; CHECK: leave: 205*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_3 = icmp ult i32 %a, 7 206*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %cond_2, %cond_3 207*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 208*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %loop2, label %leave2 209*9880d681SAndroid Build Coastguard Worker 210*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ] 211*9880d681SAndroid Build Coastguard Worker br i1 undef, label %loop2, label %leave2 212*9880d681SAndroid Build Coastguard Worker 213*9880d681SAndroid Build Coastguard Workerloop2: 214*9880d681SAndroid Build Coastguard Worker %cond_3 = icmp ult i32 %a, 7 215*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_3) [ "deopt"() ] 216*9880d681SAndroid Build Coastguard Worker br label %loop2 217*9880d681SAndroid Build Coastguard Worker 218*9880d681SAndroid Build Coastguard Workerleave2: 219*9880d681SAndroid Build Coastguard Worker ret void 220*9880d681SAndroid Build Coastguard Worker} 221*9880d681SAndroid Build Coastguard Worker 222*9880d681SAndroid Build Coastguard Worker; In cases like these where there isn't any "obviously profitable" 223*9880d681SAndroid Build Coastguard Worker; widening sites, we refuse to do anything. 224*9880d681SAndroid Build Coastguard Workerdefine void @f_9(i32 %a, i1 %cond_0, i1 %cond_1) { 225*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_9( 226*9880d681SAndroid Build Coastguard Workerentry: 227*9880d681SAndroid Build Coastguard Worker br label %first_loop 228*9880d681SAndroid Build Coastguard Worker 229*9880d681SAndroid Build Coastguard Workerfirst_loop: 230*9880d681SAndroid Build Coastguard Worker; CHECK: first_loop: 231*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 232*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %first_loop, label %second_loop 233*9880d681SAndroid Build Coastguard Worker 234*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 235*9880d681SAndroid Build Coastguard Worker br i1 undef, label %first_loop, label %second_loop 236*9880d681SAndroid Build Coastguard Worker 237*9880d681SAndroid Build Coastguard Workersecond_loop: 238*9880d681SAndroid Build Coastguard Worker; CHECK: second_loop: 239*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 240*9880d681SAndroid Build Coastguard Worker; CHECK: br label %second_loop 241*9880d681SAndroid Build Coastguard Worker 242*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 243*9880d681SAndroid Build Coastguard Worker br label %second_loop 244*9880d681SAndroid Build Coastguard Worker} 245*9880d681SAndroid Build Coastguard Worker 246*9880d681SAndroid Build Coastguard Worker; Same situation as in @f_9: no "obviously profitable" widening sites, 247*9880d681SAndroid Build Coastguard Worker; so we refuse to do anything. 248*9880d681SAndroid Build Coastguard Workerdefine void @f_10(i32 %a, i1 %cond_0, i1 %cond_1) { 249*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_10( 250*9880d681SAndroid Build Coastguard Workerentry: 251*9880d681SAndroid Build Coastguard Worker br label %loop 252*9880d681SAndroid Build Coastguard Worker 253*9880d681SAndroid Build Coastguard Workerloop: 254*9880d681SAndroid Build Coastguard Worker; CHECK: loop: 255*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 256*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %loop, label %no_loop 257*9880d681SAndroid Build Coastguard Worker 258*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 259*9880d681SAndroid Build Coastguard Worker br i1 undef, label %loop, label %no_loop 260*9880d681SAndroid Build Coastguard Worker 261*9880d681SAndroid Build Coastguard Workerno_loop: 262*9880d681SAndroid Build Coastguard Worker; CHECK: no_loop: 263*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 264*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 265*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 266*9880d681SAndroid Build Coastguard Worker ret void 267*9880d681SAndroid Build Coastguard Worker} 268*9880d681SAndroid Build Coastguard Worker 269*9880d681SAndroid Build Coastguard Worker; With guards in loops, we're okay hoisting out the guard into the 270*9880d681SAndroid Build Coastguard Worker; containing loop. 271*9880d681SAndroid Build Coastguard Workerdefine void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) { 272*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_11( 273*9880d681SAndroid Build Coastguard Workerentry: 274*9880d681SAndroid Build Coastguard Worker br label %inner 275*9880d681SAndroid Build Coastguard Worker 276*9880d681SAndroid Build Coastguard Workerinner: 277*9880d681SAndroid Build Coastguard Worker; CHECK: inner: 278*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %cond_0, %cond_1 279*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 280*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %inner, label %outer 281*9880d681SAndroid Build Coastguard Worker 282*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 283*9880d681SAndroid Build Coastguard Worker br i1 undef, label %inner, label %outer 284*9880d681SAndroid Build Coastguard Worker 285*9880d681SAndroid Build Coastguard Workerouter: 286*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 287*9880d681SAndroid Build Coastguard Worker br label %inner 288*9880d681SAndroid Build Coastguard Worker} 289*9880d681SAndroid Build Coastguard Worker 290*9880d681SAndroid Build Coastguard Worker; Checks that we are adequately guarded against exponential-time 291*9880d681SAndroid Build Coastguard Worker; behavior when hoisting code. 292*9880d681SAndroid Build Coastguard Workerdefine void @f_12(i32 %a0) { 293*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_12 294*9880d681SAndroid Build Coastguard Worker 295*9880d681SAndroid Build Coastguard Worker; Eliding the earlier 29 multiplications for brevity 296*9880d681SAndroid Build Coastguard Worker; CHECK: %a30 = mul i32 %a29, %a29 297*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %cond = trunc i32 %a30 to i1 298*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %wide.chk = and i1 true, %cond 299*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 300*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void 301*9880d681SAndroid Build Coastguard Worker 302*9880d681SAndroid Build Coastguard Workerentry: 303*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] 304*9880d681SAndroid Build Coastguard Worker %a1 = mul i32 %a0, %a0 305*9880d681SAndroid Build Coastguard Worker %a2 = mul i32 %a1, %a1 306*9880d681SAndroid Build Coastguard Worker %a3 = mul i32 %a2, %a2 307*9880d681SAndroid Build Coastguard Worker %a4 = mul i32 %a3, %a3 308*9880d681SAndroid Build Coastguard Worker %a5 = mul i32 %a4, %a4 309*9880d681SAndroid Build Coastguard Worker %a6 = mul i32 %a5, %a5 310*9880d681SAndroid Build Coastguard Worker %a7 = mul i32 %a6, %a6 311*9880d681SAndroid Build Coastguard Worker %a8 = mul i32 %a7, %a7 312*9880d681SAndroid Build Coastguard Worker %a9 = mul i32 %a8, %a8 313*9880d681SAndroid Build Coastguard Worker %a10 = mul i32 %a9, %a9 314*9880d681SAndroid Build Coastguard Worker %a11 = mul i32 %a10, %a10 315*9880d681SAndroid Build Coastguard Worker %a12 = mul i32 %a11, %a11 316*9880d681SAndroid Build Coastguard Worker %a13 = mul i32 %a12, %a12 317*9880d681SAndroid Build Coastguard Worker %a14 = mul i32 %a13, %a13 318*9880d681SAndroid Build Coastguard Worker %a15 = mul i32 %a14, %a14 319*9880d681SAndroid Build Coastguard Worker %a16 = mul i32 %a15, %a15 320*9880d681SAndroid Build Coastguard Worker %a17 = mul i32 %a16, %a16 321*9880d681SAndroid Build Coastguard Worker %a18 = mul i32 %a17, %a17 322*9880d681SAndroid Build Coastguard Worker %a19 = mul i32 %a18, %a18 323*9880d681SAndroid Build Coastguard Worker %a20 = mul i32 %a19, %a19 324*9880d681SAndroid Build Coastguard Worker %a21 = mul i32 %a20, %a20 325*9880d681SAndroid Build Coastguard Worker %a22 = mul i32 %a21, %a21 326*9880d681SAndroid Build Coastguard Worker %a23 = mul i32 %a22, %a22 327*9880d681SAndroid Build Coastguard Worker %a24 = mul i32 %a23, %a23 328*9880d681SAndroid Build Coastguard Worker %a25 = mul i32 %a24, %a24 329*9880d681SAndroid Build Coastguard Worker %a26 = mul i32 %a25, %a25 330*9880d681SAndroid Build Coastguard Worker %a27 = mul i32 %a26, %a26 331*9880d681SAndroid Build Coastguard Worker %a28 = mul i32 %a27, %a27 332*9880d681SAndroid Build Coastguard Worker %a29 = mul i32 %a28, %a28 333*9880d681SAndroid Build Coastguard Worker %a30 = mul i32 %a29, %a29 334*9880d681SAndroid Build Coastguard Worker %cond = trunc i32 %a30 to i1 335*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ] 336*9880d681SAndroid Build Coastguard Worker ret void 337*9880d681SAndroid Build Coastguard Worker} 338*9880d681SAndroid Build Coastguard Worker 339*9880d681SAndroid Build Coastguard Workerdefine void @f_13(i32 %a) { 340*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_13( 341*9880d681SAndroid Build Coastguard Workerentry: 342*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = icmp ult i32 %a, 10 343*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] 344*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %left, label %right 345*9880d681SAndroid Build Coastguard Worker 346*9880d681SAndroid Build Coastguard Worker %cond_0 = icmp ult i32 %a, 14 347*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 348*9880d681SAndroid Build Coastguard Worker br i1 undef, label %left, label %right 349*9880d681SAndroid Build Coastguard Worker 350*9880d681SAndroid Build Coastguard Workerleft: 351*9880d681SAndroid Build Coastguard Worker %cond_1 = icmp slt i32 %a, 10 352*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 353*9880d681SAndroid Build Coastguard Worker ret void 354*9880d681SAndroid Build Coastguard Worker 355*9880d681SAndroid Build Coastguard Workerright: 356*9880d681SAndroid Build Coastguard Worker ret void 357*9880d681SAndroid Build Coastguard Worker} 358*9880d681SAndroid Build Coastguard Worker 359*9880d681SAndroid Build Coastguard Workerdefine void @f_14(i32 %a) { 360*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_14( 361*9880d681SAndroid Build Coastguard Workerentry: 362*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_0 = icmp ult i32 %a, 14 363*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 364*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 undef, label %left, label %right 365*9880d681SAndroid Build Coastguard Worker 366*9880d681SAndroid Build Coastguard Worker %cond_0 = icmp ult i32 %a, 14 367*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] 368*9880d681SAndroid Build Coastguard Worker br i1 undef, label %left, label %right 369*9880d681SAndroid Build Coastguard Worker 370*9880d681SAndroid Build Coastguard Workerleft: 371*9880d681SAndroid Build Coastguard Worker; CHECK: left: 372*9880d681SAndroid Build Coastguard Worker; CHECK: %cond_1 = icmp sgt i32 %a, 10 373*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 374*9880d681SAndroid Build Coastguard Worker 375*9880d681SAndroid Build Coastguard Worker %cond_1 = icmp sgt i32 %a, 10 376*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] 377*9880d681SAndroid Build Coastguard Worker ret void 378*9880d681SAndroid Build Coastguard Worker 379*9880d681SAndroid Build Coastguard Workerright: 380*9880d681SAndroid Build Coastguard Worker ret void 381*9880d681SAndroid Build Coastguard Worker} 382