1*9880d681SAndroid Build Coastguard Worker; RUN: opt -S -guard-widening < %s | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.experimental.guard(i1,...) 4*9880d681SAndroid Build Coastguard Worker 5*9880d681SAndroid Build Coastguard Workerdefine void @f_0(i32 %x, i32* %length_buf) { 6*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_0( 7*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: @llvm.experimental.guard 8*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk2 = and i1 %chk3, %chk0 9*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ] 10*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 11*9880d681SAndroid Build Coastguard Workerentry: 12*9880d681SAndroid Build Coastguard Worker %length = load i32, i32* %length_buf, !range !0 13*9880d681SAndroid Build Coastguard Worker %chk0 = icmp ult i32 %x, %length 14*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 15*9880d681SAndroid Build Coastguard Worker 16*9880d681SAndroid Build Coastguard Worker %x.inc1 = add i32 %x, 1 17*9880d681SAndroid Build Coastguard Worker %chk1 = icmp ult i32 %x.inc1, %length 18*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 19*9880d681SAndroid Build Coastguard Worker 20*9880d681SAndroid Build Coastguard Worker %x.inc2 = add i32 %x, 2 21*9880d681SAndroid Build Coastguard Worker %chk2 = icmp ult i32 %x.inc2, %length 22*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard Worker %x.inc3 = add i32 %x, 3 25*9880d681SAndroid Build Coastguard Worker %chk3 = icmp ult i32 %x.inc3, %length 26*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 27*9880d681SAndroid Build Coastguard Worker ret void 28*9880d681SAndroid Build Coastguard Worker} 29*9880d681SAndroid Build Coastguard Worker 30*9880d681SAndroid Build Coastguard Workerdefine void @f_1(i32 %x, i32* %length_buf) { 31*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_1( 32*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: llvm.experimental.guard 33*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk2 = and i1 %chk3, %chk0 34*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ] 35*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 36*9880d681SAndroid Build Coastguard Workerentry: 37*9880d681SAndroid Build Coastguard Worker %length = load i32, i32* %length_buf, !range !0 38*9880d681SAndroid Build Coastguard Worker %chk0 = icmp ult i32 %x, %length 39*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 40*9880d681SAndroid Build Coastguard Worker 41*9880d681SAndroid Build Coastguard Worker %x.inc1 = add i32 %x, 1 42*9880d681SAndroid Build Coastguard Worker %chk1 = icmp ult i32 %x.inc1, %length 43*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 44*9880d681SAndroid Build Coastguard Worker 45*9880d681SAndroid Build Coastguard Worker %x.inc2 = add i32 %x.inc1, 2 46*9880d681SAndroid Build Coastguard Worker %chk2 = icmp ult i32 %x.inc2, %length 47*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 48*9880d681SAndroid Build Coastguard Worker 49*9880d681SAndroid Build Coastguard Worker %x.inc3 = add i32 %x.inc2, 3 50*9880d681SAndroid Build Coastguard Worker %chk3 = icmp ult i32 %x.inc3, %length 51*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 52*9880d681SAndroid Build Coastguard Worker ret void 53*9880d681SAndroid Build Coastguard Worker} 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Workerdefine void @f_2(i32 %a, i32* %length_buf) { 56*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_2( 57*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: llvm.experimental.guard 58*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk2 = and i1 %chk3, %chk0 59*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ] 60*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 61*9880d681SAndroid Build Coastguard Workerentry: 62*9880d681SAndroid Build Coastguard Worker %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00 63*9880d681SAndroid Build Coastguard Worker %length = load i32, i32* %length_buf, !range !0 64*9880d681SAndroid Build Coastguard Worker %chk0 = icmp ult i32 %x, %length 65*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 66*9880d681SAndroid Build Coastguard Worker 67*9880d681SAndroid Build Coastguard Worker %x.inc1 = or i32 %x, 1 68*9880d681SAndroid Build Coastguard Worker %chk1 = icmp ult i32 %x.inc1, %length 69*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Worker %x.inc2 = or i32 %x, 2 72*9880d681SAndroid Build Coastguard Worker %chk2 = icmp ult i32 %x.inc2, %length 73*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 74*9880d681SAndroid Build Coastguard Worker 75*9880d681SAndroid Build Coastguard Worker %x.inc3 = or i32 %x, 3 76*9880d681SAndroid Build Coastguard Worker %chk3 = icmp ult i32 %x.inc3, %length 77*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 78*9880d681SAndroid Build Coastguard Worker ret void 79*9880d681SAndroid Build Coastguard Worker} 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Workerdefine void @f_3(i32 %a, i32* %length_buf) { 82*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_3( 83*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: llvm.experimental.guard 84*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk2 = and i1 %chk3, %chk0 85*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ] 86*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 87*9880d681SAndroid Build Coastguard Workerentry: 88*9880d681SAndroid Build Coastguard Worker %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00 89*9880d681SAndroid Build Coastguard Worker %length = load i32, i32* %length_buf, !range !0 90*9880d681SAndroid Build Coastguard Worker %chk0 = icmp ult i32 %x, %length 91*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 92*9880d681SAndroid Build Coastguard Worker 93*9880d681SAndroid Build Coastguard Worker %x.inc1 = add i32 %x, 1 94*9880d681SAndroid Build Coastguard Worker %chk1 = icmp ult i32 %x.inc1, %length 95*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 96*9880d681SAndroid Build Coastguard Worker 97*9880d681SAndroid Build Coastguard Worker %x.inc2 = or i32 %x.inc1, 2 98*9880d681SAndroid Build Coastguard Worker %chk2 = icmp ult i32 %x.inc2, %length 99*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 100*9880d681SAndroid Build Coastguard Worker 101*9880d681SAndroid Build Coastguard Worker %x.inc3 = add i32 %x.inc2, 3 102*9880d681SAndroid Build Coastguard Worker %chk3 = icmp ult i32 %x.inc3, %length 103*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 104*9880d681SAndroid Build Coastguard Worker ret void 105*9880d681SAndroid Build Coastguard Worker} 106*9880d681SAndroid Build Coastguard Worker 107*9880d681SAndroid Build Coastguard Workerdefine void @f_4(i32 %x, i32* %length_buf) { 108*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_4( 109*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: llvm.experimental.guard 110*9880d681SAndroid Build Coastguard Worker 111*9880d681SAndroid Build Coastguard Worker; Note: we NOT guarding on "and i1 %chk3, %chk0", that would be incorrect. 112*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk2 = and i1 %chk3, %chk1 113*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ] 114*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 115*9880d681SAndroid Build Coastguard Workerentry: 116*9880d681SAndroid Build Coastguard Worker %length = load i32, i32* %length_buf, !range !0 117*9880d681SAndroid Build Coastguard Worker %chk0 = icmp ult i32 %x, %length 118*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Worker %x.inc1 = add i32 %x, -1024 121*9880d681SAndroid Build Coastguard Worker %chk1 = icmp ult i32 %x.inc1, %length 122*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 123*9880d681SAndroid Build Coastguard Worker 124*9880d681SAndroid Build Coastguard Worker %x.inc2 = add i32 %x, 2 125*9880d681SAndroid Build Coastguard Worker %chk2 = icmp ult i32 %x.inc2, %length 126*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 127*9880d681SAndroid Build Coastguard Worker 128*9880d681SAndroid Build Coastguard Worker %x.inc3 = add i32 %x, 3 129*9880d681SAndroid Build Coastguard Worker %chk3 = icmp ult i32 %x.inc3, %length 130*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 131*9880d681SAndroid Build Coastguard Worker ret void 132*9880d681SAndroid Build Coastguard Worker} 133*9880d681SAndroid Build Coastguard Worker 134*9880d681SAndroid Build Coastguard Workerdefine void @f_5(i32 %x, i32* %length_buf) { 135*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_5( 136*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: llvm.experimental.guard 137*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk2 = and i1 %chk1, %chk2 138*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ] 139*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 140*9880d681SAndroid Build Coastguard Workerentry: 141*9880d681SAndroid Build Coastguard Worker %length = load i32, i32* %length_buf, !range !0 142*9880d681SAndroid Build Coastguard Worker %chk0 = icmp ult i32 %x, %length 143*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 144*9880d681SAndroid Build Coastguard Worker 145*9880d681SAndroid Build Coastguard Worker %x.inc1 = add i32 %x, 1 146*9880d681SAndroid Build Coastguard Worker %chk1 = icmp ult i32 %x.inc1, %length 147*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 148*9880d681SAndroid Build Coastguard Worker 149*9880d681SAndroid Build Coastguard Worker %x.inc2 = add i32 %x.inc1, -200 150*9880d681SAndroid Build Coastguard Worker %chk2 = icmp ult i32 %x.inc2, %length 151*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Worker %x.inc3 = add i32 %x.inc2, 3 154*9880d681SAndroid Build Coastguard Worker %chk3 = icmp ult i32 %x.inc3, %length 155*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 156*9880d681SAndroid Build Coastguard Worker ret void 157*9880d681SAndroid Build Coastguard Worker} 158*9880d681SAndroid Build Coastguard Worker 159*9880d681SAndroid Build Coastguard Worker 160*9880d681SAndroid Build Coastguard Worker; Negative test: we can't merge these checks into 161*9880d681SAndroid Build Coastguard Worker; 162*9880d681SAndroid Build Coastguard Worker; (%x + -2147483647) u< L && (%x + 3) u< L 163*9880d681SAndroid Build Coastguard Worker; 164*9880d681SAndroid Build Coastguard Worker; because if %length == INT_MAX and %x == -3 then 165*9880d681SAndroid Build Coastguard Worker; 166*9880d681SAndroid Build Coastguard Worker; (%x + -2147483647) == i32 2147483646 u< L (L is 2147483647) 167*9880d681SAndroid Build Coastguard Worker; (%x + 3) == 0 u< L 168*9880d681SAndroid Build Coastguard Worker; 169*9880d681SAndroid Build Coastguard Worker; But (%x + 2) == -1 is not u< L 170*9880d681SAndroid Build Coastguard Worker; 171*9880d681SAndroid Build Coastguard Workerdefine void @f_6(i32 %x, i32* %length_buf) { 172*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_6( 173*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: llvm.experimental.guard 174*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk = and i1 %chk0, %chk1 175*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk1 = and i1 %wide.chk, %chk2 176*9880d681SAndroid Build Coastguard Worker; CHECK: %wide.chk2 = and i1 %wide.chk1, %chk3 177*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ] 178*9880d681SAndroid Build Coastguard Workerentry: 179*9880d681SAndroid Build Coastguard Worker %length = load i32, i32* %length_buf, !range !0 180*9880d681SAndroid Build Coastguard Worker %chk0 = icmp ult i32 %x, %length 181*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 182*9880d681SAndroid Build Coastguard Worker 183*9880d681SAndroid Build Coastguard Worker %x.inc1 = add i32 %x, -2147483647 ;; -2147483647 == (i32 INT_MIN)+1 == -(i32 INT_MAX) 184*9880d681SAndroid Build Coastguard Worker %chk1 = icmp ult i32 %x.inc1, %length 185*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard Worker %x.inc2 = add i32 %x, 2 188*9880d681SAndroid Build Coastguard Worker %chk2 = icmp ult i32 %x.inc2, %length 189*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 190*9880d681SAndroid Build Coastguard Worker 191*9880d681SAndroid Build Coastguard Worker %x.inc3 = add i32 %x, 3 192*9880d681SAndroid Build Coastguard Worker %chk3 = icmp ult i32 %x.inc3, %length 193*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 194*9880d681SAndroid Build Coastguard Worker ret void 195*9880d681SAndroid Build Coastguard Worker} 196*9880d681SAndroid Build Coastguard Worker 197*9880d681SAndroid Build Coastguard Worker 198*9880d681SAndroid Build Coastguard Workerdefine void @f_7(i32 %x, i32* %length_buf) { 199*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_7( 200*9880d681SAndroid Build Coastguard Worker 201*9880d681SAndroid Build Coastguard Worker; CHECK: [[COND_0:%[^ ]+]] = and i1 %chk3.b, %chk0.b 202*9880d681SAndroid Build Coastguard Worker; CHECK: [[COND_1:%[^ ]+]] = and i1 %chk0.a, [[COND_0]] 203*9880d681SAndroid Build Coastguard Worker; CHECK: [[COND_2:%[^ ]+]] = and i1 %chk3.a, [[COND_1]] 204*9880d681SAndroid Build Coastguard Worker; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2]]) [ "deopt"() ] 205*9880d681SAndroid Build Coastguard Worker 206*9880d681SAndroid Build Coastguard Workerentry: 207*9880d681SAndroid Build Coastguard Worker %length_a = load volatile i32, i32* %length_buf, !range !0 208*9880d681SAndroid Build Coastguard Worker %length_b = load volatile i32, i32* %length_buf, !range !0 209*9880d681SAndroid Build Coastguard Worker %chk0.a = icmp ult i32 %x, %length_a 210*9880d681SAndroid Build Coastguard Worker %chk0.b = icmp ult i32 %x, %length_b 211*9880d681SAndroid Build Coastguard Worker %chk0 = and i1 %chk0.a, %chk0.b 212*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 213*9880d681SAndroid Build Coastguard Worker 214*9880d681SAndroid Build Coastguard Worker %x.inc1 = add i32 %x, 1 215*9880d681SAndroid Build Coastguard Worker %chk1.a = icmp ult i32 %x.inc1, %length_a 216*9880d681SAndroid Build Coastguard Worker %chk1.b = icmp ult i32 %x.inc1, %length_b 217*9880d681SAndroid Build Coastguard Worker %chk1 = and i1 %chk1.a, %chk1.b 218*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 219*9880d681SAndroid Build Coastguard Worker 220*9880d681SAndroid Build Coastguard Worker %x.inc2 = add i32 %x, 2 221*9880d681SAndroid Build Coastguard Worker %chk2.a = icmp ult i32 %x.inc2, %length_a 222*9880d681SAndroid Build Coastguard Worker %chk2.b = icmp ult i32 %x.inc2, %length_b 223*9880d681SAndroid Build Coastguard Worker %chk2 = and i1 %chk2.a, %chk2.b 224*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 225*9880d681SAndroid Build Coastguard Worker 226*9880d681SAndroid Build Coastguard Worker %x.inc3 = add i32 %x, 3 227*9880d681SAndroid Build Coastguard Worker %chk3.a = icmp ult i32 %x.inc3, %length_a 228*9880d681SAndroid Build Coastguard Worker %chk3.b = icmp ult i32 %x.inc3, %length_b 229*9880d681SAndroid Build Coastguard Worker %chk3 = and i1 %chk3.a, %chk3.b 230*9880d681SAndroid Build Coastguard Worker call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 231*9880d681SAndroid Build Coastguard Worker ret void 232*9880d681SAndroid Build Coastguard Worker} 233*9880d681SAndroid Build Coastguard Worker 234*9880d681SAndroid Build Coastguard Worker 235*9880d681SAndroid Build Coastguard Worker!0 = !{i32 0, i32 2147483648} 236