1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=guard-widening < %s | FileCheck %s 3 4declare void @llvm.experimental.guard(i1,...) 5 6define void @f_0(i32 %x, ptr %length_buf) { 7; CHECK-LABEL: @f_0( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 10; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0:![0-9]+]], !noundef !1 11; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]] 12; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 13; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] 14; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 15; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 16; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] 17; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]] 18; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 19; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] 20; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]] 21; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 22; CHECK-NEXT: ret void 23; 24entry: 25 %length = load i32, ptr %length_buf, !range !0, !noundef !{} 26 %chk0 = icmp ult i32 %x, %length 27 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 28 29 %x.inc1 = add i32 %x, 1 30 %chk1 = icmp ult i32 %x.inc1, %length 31 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 32 33 %x.inc2 = add i32 %x, 2 34 %chk2 = icmp ult i32 %x.inc2, %length 35 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 36 37 %x.inc3 = add i32 %x, 3 38 %chk3 = icmp ult i32 %x.inc3, %length 39 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 40 ret void 41} 42 43define void @f_1(i32 %x, ptr %length_buf) { 44; CHECK-LABEL: @f_1( 45; CHECK-NEXT: entry: 46; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 47; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1 48; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]] 49; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 50; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] 51; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 52; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_INC1]], 2 53; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] 54; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]] 55; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 56; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] 57; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]] 58; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 59; CHECK-NEXT: ret void 60; 61entry: 62 %length = load i32, ptr %length_buf, !range !0, !noundef !{} 63 %chk0 = icmp ult i32 %x, %length 64 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 65 66 %x.inc1 = add i32 %x, 1 67 %chk1 = icmp ult i32 %x.inc1, %length 68 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 69 70 %x.inc2 = add i32 %x.inc1, 2 71 %chk2 = icmp ult i32 %x.inc2, %length 72 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 73 74 %x.inc3 = add i32 %x.inc2, 3 75 %chk3 = icmp ult i32 %x.inc3, %length 76 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 77 ret void 78} 79 80define void @f_2(i32 %a, ptr %length_buf) { 81; CHECK-LABEL: @f_2( 82; CHECK-NEXT: entry: 83; CHECK-NEXT: [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]] 84; CHECK-NEXT: [[X:%.*]] = and i32 [[A_GW_FR]], -256 85; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] 86; CHECK-NEXT: [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]] 87; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH_GW_FR]] 88; CHECK-NEXT: [[X_INC1:%.*]] = or i32 [[X]], 1 89; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]] 90; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 91; CHECK-NEXT: [[X_INC2:%.*]] = or i32 [[X]], 2 92; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_GW_FR]] 93; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] 94; CHECK-NEXT: [[X_INC3:%.*]] = or i32 [[X]], 3 95; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_GW_FR]] 96; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[CHK3]] 97; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 98; CHECK-NEXT: ret void 99; 100entry: 101 %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00 102 %length = load i32, ptr %length_buf, !range !0 103 %chk0 = icmp ult i32 %x, %length 104 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 105 106 %x.inc1 = or i32 %x, 1 107 %chk1 = icmp ult i32 %x.inc1, %length 108 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 109 110 %x.inc2 = or i32 %x, 2 111 %chk2 = icmp ult i32 %x.inc2, %length 112 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 113 114 %x.inc3 = or i32 %x, 3 115 %chk3 = icmp ult i32 %x.inc3, %length 116 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 117 ret void 118} 119 120define void @f_3(i32 %a, ptr %length_buf) { 121; CHECK-LABEL: @f_3( 122; CHECK-NEXT: entry: 123; CHECK-NEXT: [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]] 124; CHECK-NEXT: [[X:%.*]] = and i32 [[A_GW_FR]], -256 125; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1 126; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH]] 127; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 128; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] 129; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 130; CHECK-NEXT: [[X_INC2:%.*]] = or i32 [[X_INC1]], 2 131; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] 132; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]] 133; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 134; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] 135; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]] 136; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 137; CHECK-NEXT: ret void 138; 139entry: 140 %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00 141 %length = load i32, ptr %length_buf, !range !0, !noundef !{} 142 %chk0 = icmp ult i32 %x, %length 143 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 144 145 %x.inc1 = add i32 %x, 1 146 %chk1 = icmp ult i32 %x.inc1, %length 147 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 148 149 %x.inc2 = or i32 %x.inc1, 2 150 %chk2 = icmp ult i32 %x.inc2, %length 151 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 152 153 %x.inc3 = add i32 %x.inc2, 3 154 %chk3 = icmp ult i32 %x.inc3, %length 155 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 156 ret void 157} 158 159define void @f_4(i32 %x, ptr %length_buf) { 160; CHECK-LABEL: @f_4( 161; CHECK-NEXT: entry: 162; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 163; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1 164; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]] 165; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -1024 166; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] 167; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 168; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 169; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] 170; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK1]] 171; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 172; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] 173; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK1]] 174; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 175; CHECK-NEXT: ret void 176; 177 178; Note: we NOT guarding on "and i1 %chk3, %chk0", that would be incorrect. 179entry: 180 %length = load i32, ptr %length_buf, !range !0, !noundef !{} 181 %chk0 = icmp ult i32 %x, %length 182 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 183 184 %x.inc1 = add i32 %x, -1024 185 %chk1 = icmp ult i32 %x.inc1, %length 186 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 187 188 %x.inc2 = add i32 %x, 2 189 %chk2 = icmp ult i32 %x.inc2, %length 190 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 191 192 %x.inc3 = add i32 %x, 3 193 %chk3 = icmp ult i32 %x.inc3, %length 194 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 195 ret void 196} 197 198define void @f_5(i32 %x, ptr %length_buf) { 199; CHECK-LABEL: @f_5( 200; CHECK-NEXT: entry: 201; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 202; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1 203; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]] 204; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 205; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] 206; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 207; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_INC1]], -200 208; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] 209; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK1]], [[CHK2]] 210; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK1]], [[CHK2]] 211; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 212; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 213; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] 214; CHECK-NEXT: ret void 215; 216entry: 217 %length = load i32, ptr %length_buf, !range !0, !noundef !{} 218 %chk0 = icmp ult i32 %x, %length 219 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 220 221 %x.inc1 = add i32 %x, 1 222 %chk1 = icmp ult i32 %x.inc1, %length 223 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 224 225 %x.inc2 = add i32 %x.inc1, -200 226 %chk2 = icmp ult i32 %x.inc2, %length 227 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 228 229 %x.inc3 = add i32 %x.inc2, 3 230 %chk3 = icmp ult i32 %x.inc3, %length 231 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 232 ret void 233} 234 235 236; Negative test: we can't merge these checks into 237; 238; (%x + -2147483647) u< L && (%x + 3) u< L 239; 240; because if %length == INT_MAX and %x == -3 then 241; 242; (%x + -2147483647) == i32 2147483646 u< L (L is 2147483647) 243; (%x + 3) == 0 u< L 244; 245; But (%x + 2) == -1 is not u< L 246; 247define void @f_6(i32 %x, ptr %length_buf) { 248; CHECK-LABEL: @f_6( 249; CHECK-NEXT: entry: 250; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 251; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1 252; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]] 253; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -2147483647 254; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] 255; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 256; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 257; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] 258; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] 259; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 260; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] 261; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[CHK3]] 262; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 263; CHECK-NEXT: ret void 264; 265entry: 266 %length = load i32, ptr %length_buf, !range !0, !noundef !{} 267 %chk0 = icmp ult i32 %x, %length 268 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 269 270 %x.inc1 = add i32 %x, -2147483647 ;; -2147483647 == (i32 INT_MIN)+1 == -(i32 INT_MAX) 271 %chk1 = icmp ult i32 %x.inc1, %length 272 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 273 274 %x.inc2 = add i32 %x, 2 275 %chk2 = icmp ult i32 %x.inc2, %length 276 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 277 278 %x.inc3 = add i32 %x, 3 279 %chk3 = icmp ult i32 %x.inc3, %length 280 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 281 ret void 282} 283 284 285define void @f_7(i32 %x, ptr %length_buf) { 286; CHECK-LABEL: @f_7( 287; CHECK-NEXT: entry: 288; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 289; CHECK-NEXT: [[LENGTH_A:%.*]] = load volatile i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1 290; CHECK-NEXT: [[LENGTH_B:%.*]] = load volatile i32, ptr [[LENGTH_BUF]], align 4, !range [[RNG0]], !noundef !1 291; CHECK-NEXT: [[CHK0_A:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_A]] 292; CHECK-NEXT: [[CHK0_B:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_B]] 293; CHECK-NEXT: [[CHK0:%.*]] = and i1 [[CHK0_A]], [[CHK0_B]] 294; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 295; CHECK-NEXT: [[CHK1_B:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_B]] 296; CHECK-NEXT: [[CHK1_A:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_A]] 297; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[CHK1_B]], [[CHK1_A]] 298; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[TMP0]] 299; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 300; CHECK-NEXT: [[CHK2_A:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_A]] 301; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[CHK2_A]], [[CHK0_A]] 302; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[CHK0_B]], [[TMP1]] 303; CHECK-NEXT: [[CHK2_B:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_B]] 304; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2_B]], [[TMP2]] 305; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 306; CHECK-NEXT: [[CHK3_A:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_A]] 307; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[CHK3_A]], [[CHK0_A]] 308; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[CHK0_B]], [[TMP3]] 309; CHECK-NEXT: [[CHK3_B:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_B]] 310; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3_B]], [[TMP4]] 311; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] 312; CHECK-NEXT: [[CHK1:%.*]] = and i1 [[CHK1_A]], [[CHK1_B]] 313; CHECK-NEXT: [[CHK2:%.*]] = and i1 [[CHK2_A]], [[CHK2_B]] 314; CHECK-NEXT: [[CHK3:%.*]] = and i1 [[CHK3_A]], [[CHK3_B]] 315; CHECK-NEXT: ret void 316; 317 318 319entry: 320 %length_a = load volatile i32, ptr %length_buf, !range !0, !noundef !{} 321 %length_b = load volatile i32, ptr %length_buf, !range !0, !noundef !{} 322 %chk0.a = icmp ult i32 %x, %length_a 323 %chk0.b = icmp ult i32 %x, %length_b 324 %chk0 = and i1 %chk0.a, %chk0.b 325 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 326 327 %x.inc1 = add i32 %x, 1 328 %chk1.a = icmp ult i32 %x.inc1, %length_a 329 %chk1.b = icmp ult i32 %x.inc1, %length_b 330 %chk1 = and i1 %chk1.a, %chk1.b 331 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 332 333 %x.inc2 = add i32 %x, 2 334 %chk2.a = icmp ult i32 %x.inc2, %length_a 335 %chk2.b = icmp ult i32 %x.inc2, %length_b 336 %chk2 = and i1 %chk2.a, %chk2.b 337 call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ] 338 339 %x.inc3 = add i32 %x, 3 340 %chk3.a = icmp ult i32 %x.inc3, %length_a 341 %chk3.b = icmp ult i32 %x.inc3, %length_b 342 %chk3 = and i1 %chk3.a, %chk3.b 343 call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ] 344 ret void 345} 346 347define void @f_8(i32 %x, ptr %length_buf) { 348; Check that we clean nuw nsw flags 349; CHECK-LABEL: @f_8( 350; CHECK-NEXT: entry: 351; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] 352; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1 353; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]] 354; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 355; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] 356; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] 357; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] 358; CHECK-NEXT: ret void 359; 360entry: 361 %length = load i32, ptr %length_buf, !range !0, !noundef !{} 362 %chk0 = icmp ult i32 %x, %length 363 call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ] 364 365 %x.inc1 = add nuw nsw i32 %x, 1 366 %chk1 = icmp ult i32 %x.inc1, %length 367 call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ] 368 ret void 369} 370 371 372 373!0 = !{i32 0, i32 2147483648} 374