1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare void @use(i1) 5 6define void @test1(ptr %src, ptr noundef %lower, ptr noundef %upper, i8 %N) { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] 10; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 11; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 12; CHECK-NEXT: [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 13; CHECK-NEXT: br i1 [[OR_0]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]] 14; CHECK: trap.bb: 15; CHECK-NEXT: ret void 16; CHECK: loop.header: 17; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] 18; CHECK-NEXT: [[EC:%.*]] = icmp uge i8 [[IV]], [[N]] 19; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]] 20; CHECK: loop.body: 21; CHECK-NEXT: [[SRC_IV:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[IV]] 22; CHECK-NEXT: [[CMP_IV_END:%.*]] = icmp uge ptr [[SRC_IV]], [[UPPER]] 23; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_END]] 24; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]] 25; CHECK: loop.body.1: 26; CHECK-NEXT: [[PTR_SRC_IV:%.*]] = bitcast ptr [[SRC_IV]] to ptr 27; CHECK-NEXT: store i32 0, ptr [[PTR_SRC_IV]], align 4 28; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[IV]], 1 29; CHECK-NEXT: [[SRC_IV_1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[ADD_1]] 30; CHECK-NEXT: [[CMP_IV_1_END:%.*]] = icmp uge ptr [[SRC_IV_1]], [[UPPER]] 31; CHECK-NEXT: [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]] 32; CHECK-NEXT: br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]] 33; CHECK: loop.body.2: 34; CHECK-NEXT: [[PTR_SRC_IV_1:%.*]] = bitcast ptr [[SRC_IV_1]] to ptr 35; CHECK-NEXT: store i32 0, ptr [[PTR_SRC_IV_1]], align 4 36; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2 37; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[ADD_2]] 38; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge ptr [[SRC_IV_2]], [[UPPER]] 39; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] 40; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] 41; CHECK: loop.latch: 42; CHECK-NEXT: [[PTR_SRC_IV_2:%.*]] = bitcast ptr [[SRC_IV_2]] to ptr 43; CHECK-NEXT: store i32 0, ptr [[PTR_SRC_IV_2]], align 4 44; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1 45; CHECK-NEXT: br label [[LOOP_HEADER]] 46; CHECK: exit: 47; CHECK-NEXT: ret void 48; 49entry: 50 %src.end = getelementptr inbounds i8, ptr %src, i8 %N 51 %cmp.src.start = icmp ult ptr %src, %lower 52 %cmp.src.end = icmp uge ptr %src.end, %upper 53 %or.0 = or i1 %cmp.src.start, %cmp.src.end 54 br i1 %or.0, label %trap.bb, label %loop.header 55 56trap.bb: 57 ret void 58 59loop.header: 60 %iv = phi i8 [ %iv.next, %loop.latch ], [ 0, %entry ] 61 %ec = icmp uge i8 %iv, %N 62 br i1 %ec, label %exit, label %loop.body 63 64loop.body: 65 %src.iv = getelementptr inbounds i8, ptr %src, i8 %iv 66 %cmp.iv.start = icmp ult ptr %src.iv, %lower 67 %cmp.iv.end = icmp uge ptr %src.iv, %upper 68 %or.1 = or i1 %cmp.iv.start, %cmp.iv.end 69 br i1 %or.1, label %trap.bb, label %loop.body.1 70 71loop.body.1: 72 %ptr.src.iv = bitcast ptr %src.iv to ptr 73 store i32 0, ptr %ptr.src.iv, align 4 74 %add.1 = add nuw nsw i8 %iv, 1 75 %src.iv.1 = getelementptr inbounds i8, ptr %src, i8 %add.1 76 %cmp.iv.1.start = icmp ult ptr %src.iv.1, %lower 77 %cmp.iv.1.end = icmp uge ptr %src.iv.1, %upper 78 %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end 79 br i1 %or.2, label %trap.bb, label %loop.body.2 80 81loop.body.2: 82 %ptr.src.iv.1 = bitcast ptr %src.iv.1 to ptr 83 store i32 0, ptr %ptr.src.iv.1, align 4 84 %add.2 = add nuw nsw i8 %iv, 2 85 %src.iv.2 = getelementptr inbounds i8, ptr %src, i8 %add.2 86 %cmp.iv.2.start = icmp ult ptr %src.iv.2, %lower 87 %cmp.iv.2.end = icmp uge ptr %src.iv.2, %upper 88 %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end 89 br i1 %or.3, label %trap.bb, label %loop.latch 90 91loop.latch: 92 %ptr.src.iv.2 = bitcast ptr %src.iv.2 to ptr 93 store i32 0, ptr %ptr.src.iv.2, align 4 94 %iv.next = add nuw nsw i8 %iv, 1 95 br label %loop.header 96 97exit: 98 ret void 99} 100 101define void @test2(ptr %src, ptr %lower, ptr %upper, i8 %N) { 102; CHECK-LABEL: @test2( 103; CHECK-NEXT: entry: 104; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] 105; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 106; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 107; CHECK-NEXT: [[CMP_OVERFLOW:%.*]] = icmp ugt ptr [[SRC]], [[SRC_END]] 108; CHECK-NEXT: [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 109; CHECK-NEXT: [[OR_11:%.*]] = or i1 [[OR_0]], [[CMP_OVERFLOW]] 110; CHECK-NEXT: br i1 [[OR_11]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]] 111; CHECK: trap.bb: 112; CHECK-NEXT: ret void 113; CHECK: loop.header: 114; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ] 115; CHECK-NEXT: [[NEXT:%.*]] = add nuw nsw i8 [[IV]], 2 116; CHECK-NEXT: [[EC:%.*]] = icmp uge i8 [[NEXT]], [[N]] 117; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]] 118; CHECK: loop.body: 119; CHECK-NEXT: [[SRC_IV:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[IV]] 120; CHECK-NEXT: [[CMP_IV_END:%.*]] = icmp uge ptr [[SRC_IV]], [[UPPER]] 121; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_END]] 122; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]] 123; CHECK: loop.body.1: 124; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[IV]], 1 125; CHECK-NEXT: [[SRC_IV_1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[ADD_1]] 126; CHECK-NEXT: [[CMP_IV_1_END:%.*]] = icmp uge ptr [[SRC_IV_1]], [[UPPER]] 127; CHECK-NEXT: [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]] 128; CHECK-NEXT: br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]] 129; CHECK: loop.body.2: 130; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2 131; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[ADD_2]] 132; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge ptr [[SRC_IV_2]], [[UPPER]] 133; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] 134; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] 135; CHECK: loop.latch: 136; CHECK-NEXT: [[PTR:%.*]] = bitcast ptr [[SRC_IV]] to ptr 137; CHECK-NEXT: store i32 0, ptr [[PTR]], align 4 138; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1 139; CHECK-NEXT: br label [[LOOP_HEADER]] 140; CHECK: exit: 141; CHECK-NEXT: ret void 142; 143entry: 144 %src.end = getelementptr inbounds i8, ptr %src, i8 %N 145 %cmp.src.start = icmp ult ptr %src, %lower 146 %cmp.src.end = icmp uge ptr %src.end, %upper 147 %cmp.overflow = icmp ugt ptr %src, %src.end 148 %or.0 = or i1 %cmp.src.start, %cmp.src.end 149 %or.11 = or i1 %or.0, %cmp.overflow 150 br i1 %or.11, label %trap.bb, label %loop.header 151 152trap.bb: 153 ret void 154 155loop.header: 156 %iv = phi i8 [ %iv.next, %loop.latch ], [ 1, %entry ] 157 %next = add nuw nsw i8 %iv, 2 158 %ec = icmp uge i8 %next, %N 159 br i1 %ec, label %exit, label %loop.body 160 161loop.body: 162 %src.iv = getelementptr inbounds i8, ptr %src, i8 %iv 163 %cmp.iv.start = icmp ult ptr %src.iv, %lower 164 %cmp.iv.end = icmp uge ptr %src.iv, %upper 165 %or.1 = or i1 %cmp.iv.start, %cmp.iv.end 166 br i1 %or.1, label %trap.bb, label %loop.body.1 167 168loop.body.1: 169 %add.1 = add nuw nsw i8 %iv, 1 170 %src.iv.1 = getelementptr inbounds i8, ptr %src, i8 %add.1 171 %cmp.iv.1.start = icmp ult ptr %src.iv.1, %lower 172 %cmp.iv.1.end = icmp uge ptr %src.iv.1, %upper 173 %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end 174 br i1 %or.2, label %trap.bb, label %loop.body.2 175 176loop.body.2: 177 %add.2 = add nuw nsw i8 %iv, 2 178 %src.iv.2 = getelementptr inbounds i8, ptr %src, i8 %add.2 179 %cmp.iv.2.start = icmp ult ptr %src.iv.2, %lower 180 %cmp.iv.2.end = icmp uge ptr %src.iv.2, %upper 181 %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end 182 br i1 %or.3, label %trap.bb, label %loop.latch 183 184loop.latch: 185 %ptr = bitcast ptr %src.iv to ptr 186 store i32 0, ptr %ptr, align 4 187 %iv.next = add nuw nsw i8 %iv, 1 188 br label %loop.header 189 190exit: 191 ret void 192} 193 194define void @test2_with_ne(ptr %src, ptr %lower, ptr %upper, i8 %N) { 195; CHECK-LABEL: @test2_with_ne( 196; CHECK-NEXT: entry: 197; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] 198; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 199; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 200; CHECK-NEXT: [[CMP_OVERFLOW:%.*]] = icmp ugt ptr [[SRC]], [[SRC_END]] 201; CHECK-NEXT: [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 202; CHECK-NEXT: [[OR_11:%.*]] = or i1 [[OR_0]], [[CMP_OVERFLOW]] 203; CHECK-NEXT: br i1 [[OR_11]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]] 204; CHECK: trap.bb: 205; CHECK-NEXT: ret void 206; CHECK: loop.header: 207; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ] 208; CHECK-NEXT: [[NEXT:%.*]] = add nuw nsw i8 [[IV]], 1 209; CHECK-NEXT: [[EC:%.*]] = icmp eq i8 [[NEXT]], [[N]] 210; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]] 211; CHECK: loop.body: 212; CHECK-NEXT: [[SRC_IV:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[IV]] 213; CHECK-NEXT: [[CMP_IV_START:%.*]] = icmp ult ptr [[SRC_IV]], [[LOWER]] 214; CHECK-NEXT: [[CMP_IV_END:%.*]] = icmp uge ptr [[SRC_IV]], [[UPPER]] 215; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_END]] 216; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]] 217; CHECK: loop.body.1: 218; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[IV]], 1 219; CHECK-NEXT: [[SRC_IV_1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[ADD_1]] 220; CHECK-NEXT: [[CMP_IV_1_END:%.*]] = icmp uge ptr [[SRC_IV_1]], [[UPPER]] 221; CHECK-NEXT: [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]] 222; CHECK-NEXT: br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]] 223; CHECK: loop.body.2: 224; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2 225; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[ADD_2]] 226; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge ptr [[SRC_IV_2]], [[UPPER]] 227; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] 228; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] 229; CHECK: loop.latch: 230; CHECK-NEXT: [[PTR:%.*]] = bitcast ptr [[SRC_IV]] to ptr 231; CHECK-NEXT: store i32 0, ptr [[PTR]], align 4 232; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1 233; CHECK-NEXT: br label [[LOOP_HEADER]] 234; CHECK: exit: 235; CHECK-NEXT: ret void 236; 237entry: 238 %src.end = getelementptr inbounds i8, ptr %src, i8 %N 239 %cmp.src.start = icmp ult ptr %src, %lower 240 %cmp.src.end = icmp uge ptr %src.end, %upper 241 %cmp.overflow = icmp ugt ptr %src, %src.end 242 %or.0 = or i1 %cmp.src.start, %cmp.src.end 243 %or.11 = or i1 %or.0, %cmp.overflow 244 br i1 %or.11, label %trap.bb, label %loop.header 245 246trap.bb: 247 ret void 248 249loop.header: 250 %iv = phi i8 [ %iv.next, %loop.latch ], [ 1, %entry ] 251 %next = add nuw nsw i8 %iv, 1 252 %ec = icmp eq i8 %next, %N 253 br i1 %ec, label %exit, label %loop.body 254 255loop.body: 256 %src.iv = getelementptr inbounds i8, ptr %src, i8 %iv 257 %cmp.iv.start = icmp ult ptr %src.iv, %lower 258 %cmp.iv.end = icmp uge ptr %src.iv, %upper 259 %or.1 = or i1 %cmp.iv.start, %cmp.iv.end 260 br i1 %or.1, label %trap.bb, label %loop.body.1 261 262loop.body.1: 263 %add.1 = add nuw nsw i8 %iv, 1 264 %src.iv.1 = getelementptr inbounds i8, ptr %src, i8 %add.1 265 %cmp.iv.1.start = icmp ult ptr %src.iv.1, %lower 266 %cmp.iv.1.end = icmp uge ptr %src.iv.1, %upper 267 %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end 268 br i1 %or.2, label %trap.bb, label %loop.body.2 269 270loop.body.2: 271 %add.2 = add nuw nsw i8 %iv, 2 272 %src.iv.2 = getelementptr inbounds i8, ptr %src, i8 %add.2 273 %cmp.iv.2.start = icmp ult ptr %src.iv.2, %lower 274 %cmp.iv.2.end = icmp uge ptr %src.iv.2, %upper 275 %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end 276 br i1 %or.3, label %trap.bb, label %loop.latch 277 278loop.latch: 279 %ptr = bitcast ptr %src.iv to ptr 280 store i32 0, ptr %ptr, align 4 281 %iv.next = add nuw nsw i8 %iv, 1 282 br label %loop.header 283 284exit: 285 ret void 286} 287 288define void @test3(ptr %src, ptr %lower, ptr %upper, i8 %N) { 289; CHECK-LABEL: @test3( 290; CHECK-NEXT: entry: 291; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] 292; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 293; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 294; CHECK-NEXT: [[CMP_OVERFLOW:%.*]] = icmp ugt ptr [[SRC]], [[SRC_END]] 295; CHECK-NEXT: [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 296; CHECK-NEXT: [[OR_11:%.*]] = or i1 [[OR_0]], [[CMP_OVERFLOW]] 297; CHECK-NEXT: br i1 [[OR_11]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]] 298; CHECK: trap.bb: 299; CHECK-NEXT: ret void 300; CHECK: loop.header: 301; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ] 302; CHECK-NEXT: [[NEXT:%.*]] = or i8 [[IV]], 1 303; CHECK-NEXT: [[EC:%.*]] = icmp ult i8 [[NEXT]], [[N]] 304; CHECK-NEXT: br i1 [[EC]], label [[LOOP_BODY:%.*]], label [[EXIT:%.*]] 305; CHECK: loop.body: 306; CHECK-NEXT: [[SRC_IV:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[IV]] 307; CHECK-NEXT: [[CMP_IV_START:%.*]] = icmp ult ptr [[SRC_IV]], [[LOWER]] 308; CHECK-NEXT: [[CMP_IV_END:%.*]] = icmp uge ptr [[SRC_IV]], [[UPPER]] 309; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_END]] 310; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]] 311; CHECK: loop.body.1: 312; CHECK-NEXT: [[SRC_IV_1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[NEXT]] 313; CHECK-NEXT: [[CMP_IV_1_END:%.*]] = icmp uge ptr [[SRC_IV_1]], [[UPPER]] 314; CHECK-NEXT: [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]] 315; CHECK-NEXT: br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]] 316; CHECK: loop.body.2: 317; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2 318; CHECK-NEXT: [[SRC_IV_2:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[ADD_2]] 319; CHECK-NEXT: [[CMP_IV_2_END:%.*]] = icmp uge ptr [[SRC_IV_2]], [[UPPER]] 320; CHECK-NEXT: [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]] 321; CHECK-NEXT: br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]] 322; CHECK: loop.latch: 323; CHECK-NEXT: [[PTR:%.*]] = bitcast ptr [[SRC_IV]] to ptr 324; CHECK-NEXT: store i32 0, ptr [[PTR]], align 4 325; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1 326; CHECK-NEXT: br label [[LOOP_HEADER]] 327; CHECK: exit: 328; CHECK-NEXT: ret void 329; 330entry: 331 %src.end = getelementptr inbounds i8, ptr %src, i8 %N 332 %cmp.src.start = icmp ult ptr %src, %lower 333 %cmp.src.end = icmp uge ptr %src.end, %upper 334 %cmp.overflow = icmp ugt ptr %src, %src.end 335 %or.0 = or i1 %cmp.src.start, %cmp.src.end 336 %or.11 = or i1 %or.0, %cmp.overflow 337 br i1 %or.11, label %trap.bb, label %loop.header 338 339trap.bb: 340 ret void 341 342loop.header: 343 %iv = phi i8 [ %iv.next, %loop.latch ], [ 1, %entry ] 344 %next = or i8 %iv, 1 345 %ec = icmp ult i8 %next, %N 346 br i1 %ec, label %loop.body, label %exit 347 348loop.body: 349 %src.iv = getelementptr inbounds i8, ptr %src, i8 %iv 350 %cmp.iv.start = icmp ult ptr %src.iv, %lower 351 %cmp.iv.end = icmp uge ptr %src.iv, %upper 352 %or.1 = or i1 %cmp.iv.start, %cmp.iv.end 353 br i1 %or.1, label %trap.bb, label %loop.body.1 354 355loop.body.1: 356 %src.iv.1 = getelementptr inbounds i8, ptr %src, i8 %next 357 %cmp.iv.1.start = icmp ult ptr %src.iv.1, %lower 358 %cmp.iv.1.end = icmp uge ptr %src.iv.1, %upper 359 %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end 360 br i1 %or.2, label %trap.bb, label %loop.body.2 361 362loop.body.2: 363 %add.2 = add nuw nsw i8 %iv, 2 364 %src.iv.2 = getelementptr inbounds i8, ptr %src, i8 %add.2 365 %cmp.iv.2.start = icmp ult ptr %src.iv.2, %lower 366 %cmp.iv.2.end = icmp uge ptr %src.iv.2, %upper 367 %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end 368 br i1 %or.3, label %trap.bb, label %loop.latch 369 370loop.latch: 371 %ptr = bitcast ptr %src.iv to ptr 372 store i32 0, ptr %ptr, align 4 373 %iv.next = add nuw nsw i8 %iv, 1 374 br label %loop.header 375 376exit: 377 ret void 378} 379 380; Cannot remove checks, because %n may be negative. 381define void @ne_check_in_loop_no_zext_n_may_be_negative(ptr %ptr, ptr %lower, ptr %upper, i16 %n) { 382; CHECK-LABEL: @ne_check_in_loop_no_zext_n_may_be_negative( 383; CHECK-NEXT: entry: 384; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 385; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE:%.*]] 386; CHECK: pre: 387; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[N:%.*]] 388; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[ADD_PTR]], [[UPPER:%.*]] 389; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]] 390; CHECK: for.cond.preheader: 391; CHECK-NEXT: br label [[FOR_HEADER:%.*]] 392; CHECK: trap: 393; CHECK-NEXT: ret void 394; CHECK: for.header: 395; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ] 396; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[N]] 397; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 398; CHECK: for.body: 399; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 400; CHECK-NEXT: [[CMP_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV]] 401; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[CMP_IV_UPPER]] 402; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]] 403; CHECK: for.body.1: 404; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1 405; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[ADD]] 406; CHECK-NEXT: [[CMP_IV_1_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV_1]] 407; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_IV_1_UPPER]] 408; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] 409; CHECK: for.latch: 410; CHECK-NEXT: store i8 0, ptr [[GEP_IV]], align 4 411; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 412; CHECK-NEXT: br label [[FOR_HEADER]] 413; CHECK: for.end: 414; CHECK-NEXT: ret void 415; 416entry: 417 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 418 br i1 %cmp.ptr.lower, label %trap, label %pre 419 420pre: 421 %add.ptr = getelementptr inbounds i8, ptr %ptr, i16 %n 422 %cmp.ptr.n.upper = icmp ult ptr %add.ptr, %upper 423 br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap 424 425for.cond.preheader: 426 br label %for.header 427 428trap: 429 ret void 430 431for.header: 432 %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ] 433 %exitcond = icmp ne i16 %iv, %n 434 br i1 %exitcond, label %for.body, label %for.end 435 436for.body: 437 %gep.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 438 %cmp.iv.lower = icmp ugt ptr %lower, %gep.iv 439 %cmp.iv.upper = icmp ule ptr %upper, %gep.iv 440 %or = or i1 %cmp.iv.lower, %cmp.iv.upper 441 br i1 %or, label %trap, label %for.body.1 442 443for.body.1: 444 %add = add nuw nsw i16 %iv, 1 445 %gep.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %add 446 %cmp.iv.1.lower = icmp ugt ptr %lower, %gep.iv.1 447 %cmp.iv.1.upper = icmp ule ptr %upper, %gep.iv.1 448 %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper 449 br i1 %or.1, label %trap, label %for.latch 450 451for.latch: 452 store i8 0, ptr %gep.iv, align 4 453 %iv.next = add nuw nsw i16 %iv, 1 454 br label %for.header 455 456for.end: 457 ret void 458} 459 460; Should be able to remove the checks in the loop, because %n is signed positive. 461define void @ne_check_in_loop_no_zext_n_positive_check(ptr %ptr, ptr %lower, ptr %upper, i16 %n) { 462; CHECK-LABEL: @ne_check_in_loop_no_zext_n_positive_check( 463; CHECK-NEXT: entry: 464; CHECK-NEXT: [[N_SIGNED_POSITIVE:%.*]] = icmp slt i16 [[N:%.*]], 0 465; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 466; CHECK-NEXT: [[OR_T:%.*]] = or i1 [[N_SIGNED_POSITIVE]], [[CMP_PTR_LOWER]] 467; CHECK-NEXT: br i1 [[OR_T]], label [[TRAP:%.*]], label [[PRE:%.*]] 468; CHECK: pre: 469; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[N]] 470; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[ADD_PTR]], [[UPPER:%.*]] 471; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]] 472; CHECK: for.cond.preheader: 473; CHECK-NEXT: br label [[FOR_HEADER:%.*]] 474; CHECK: trap: 475; CHECK-NEXT: ret void 476; CHECK: for.header: 477; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ] 478; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[N]] 479; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 480; CHECK: for.body: 481; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 482; CHECK-NEXT: [[OR:%.*]] = or i1 false, false 483; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]] 484; CHECK: for.body.1: 485; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1 486; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[ADD]] 487; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, false 488; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] 489; CHECK: for.latch: 490; CHECK-NEXT: store i8 0, ptr [[GEP_IV]], align 4 491; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 492; CHECK-NEXT: br label [[FOR_HEADER]] 493; CHECK: for.end: 494; CHECK-NEXT: ret void 495; 496entry: 497 %n.signed.positive = icmp slt i16 %n, 0 498 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 499 %or.t = or i1 %n.signed.positive, %cmp.ptr.lower 500 br i1 %or.t, label %trap, label %pre 501 502pre: 503 %add.ptr = getelementptr inbounds i8, ptr %ptr, i16 %n 504 %cmp.ptr.n.upper = icmp ult ptr %add.ptr, %upper 505 br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap 506 507for.cond.preheader: 508 br label %for.header 509 510trap: 511 ret void 512 513for.header: 514 %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ] 515 %exitcond = icmp ne i16 %iv, %n 516 br i1 %exitcond, label %for.body, label %for.end 517 518for.body: 519 %gep.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 520 %cmp.iv.lower = icmp ugt ptr %lower, %gep.iv 521 %cmp.iv.upper = icmp ule ptr %upper, %gep.iv 522 %or = or i1 %cmp.iv.lower, %cmp.iv.upper 523 br i1 %or, label %trap, label %for.body.1 524 525for.body.1: 526 %add = add nuw nsw i16 %iv, 1 527 %gep.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %add 528 %cmp.iv.1.lower = icmp ugt ptr %lower, %gep.iv.1 529 %cmp.iv.1.upper = icmp ule ptr %upper, %gep.iv.1 530 %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper 531 br i1 %or.1, label %trap, label %for.latch 532 533for.latch: 534 store i8 0, ptr %gep.iv, align 4 535 %iv.next = add nuw nsw i16 %iv, 1 536 br label %for.header 537 538for.end: 539 ret void 540} 541 542; Make sure icmp ne of the induction variable in the loop body can be handled 543; and is treated as ule. 544define void @ne_check_in_loop_with_zext(ptr %ptr, ptr %lower, ptr %upper, i8 %n) { 545; CHECK-LABEL: @ne_check_in_loop_with_zext( 546; CHECK-NEXT: entry: 547; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 548; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE:%.*]] 549; CHECK: pre: 550; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[N:%.*]] to i16 551; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IDX_EXT]] 552; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[ADD_PTR]], [[UPPER:%.*]] 553; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]] 554; CHECK: for.cond.preheader: 555; CHECK-NEXT: br label [[FOR_HEADER:%.*]] 556; CHECK: trap: 557; CHECK-NEXT: ret void 558; CHECK: for.header: 559; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ] 560; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[IDX_EXT]] 561; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 562; CHECK: for.body: 563; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 564; CHECK-NEXT: [[OR:%.*]] = or i1 false, false 565; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]] 566; CHECK: for.body.1: 567; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1 568; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[ADD]] 569; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, false 570; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] 571; CHECK: for.latch: 572; CHECK-NEXT: store i8 0, ptr [[GEP_IV]], align 4 573; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 574; CHECK-NEXT: br label [[FOR_HEADER]] 575; CHECK: for.end: 576; CHECK-NEXT: ret void 577; 578entry: 579 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 580 br i1 %cmp.ptr.lower, label %trap, label %pre 581 582pre: 583 %idx.ext = zext i8 %n to i16 584 %add.ptr = getelementptr inbounds i8, ptr %ptr, i16 %idx.ext 585 %cmp.ptr.n.upper = icmp ult ptr %add.ptr, %upper 586 br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap 587 588for.cond.preheader: 589 br label %for.header 590 591trap: 592 ret void 593 594for.header: 595 %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ] 596 %exitcond = icmp ne i16 %iv, %idx.ext 597 br i1 %exitcond, label %for.body, label %for.end 598 599for.body: 600 %gep.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 601 %cmp.iv.lower = icmp ugt ptr %lower, %gep.iv 602 %cmp.iv.upper = icmp ule ptr %upper, %gep.iv 603 %or = or i1 %cmp.iv.lower, %cmp.iv.upper 604 br i1 %or, label %trap, label %for.body.1 605 606for.body.1: 607 %add = add nuw nsw i16 %iv, 1 608 %gep.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %add 609 %cmp.iv.1.lower = icmp ugt ptr %lower, %gep.iv.1 610 %cmp.iv.1.upper = icmp ule ptr %upper, %gep.iv.1 611 %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper 612 br i1 %or.1, label %trap, label %for.latch 613 614for.latch: 615 store i8 0, ptr %gep.iv, align 4 616 %iv.next = add nuw nsw i16 %iv, 1 617 br label %for.header 618 619for.end: 620 ret void 621} 622 623define void @test_ptr_need_one_upper_check(ptr readonly %src, ptr %dst, i32 %n) { 624; CHECK-LABEL: @test_ptr_need_one_upper_check( 625; CHECK-NEXT: entry: 626; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 627; CHECK: loop.header: 628; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[LOOP_LATCH_2:%.*]] ] 629; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[N:%.*]] 630; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_CHECK_1:%.*]], label [[EXIT:%.*]] 631; CHECK: loop.check.1: 632; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 633; CHECK-NEXT: [[SRC_UPPER:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i64 [[TMP0]] 634; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[I_0]], 2 635; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[ADD]] to i64 636; CHECK-NEXT: [[SRC_IDX:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[IDXPROM]] 637; CHECK-NEXT: [[CMP_SRC_IDX_UPPER:%.*]] = icmp ult ptr [[SRC_IDX]], [[SRC_UPPER]] 638; CHECK-NEXT: call void @use(i1 [[CMP_SRC_IDX_UPPER]]) 639; CHECK-NEXT: br i1 [[CMP_SRC_IDX_UPPER]], label [[LOOP_LATCH:%.*]], label [[EXIT]] 640; CHECK: loop.latch: 641; CHECK-NEXT: [[DST_UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[TMP0]] 642; CHECK-NEXT: [[DST_IDX:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IDXPROM]] 643; CHECK-NEXT: call void @use(i1 true) 644; CHECK-NEXT: br i1 true, label [[LOOP_LATCH_2]], label [[EXIT]] 645; CHECK: loop.latch.2: 646; CHECK-NEXT: br label [[LOOP_HEADER]] 647; CHECK: exit: 648; CHECK-NEXT: ret void 649; 650entry: 651 br label %loop.header 652 653loop.header: 654 %i.0 = phi i32 [ 0, %entry ], [ %add, %loop.latch.2 ] 655 %cmp = icmp ult i32 %i.0, %n 656 br i1 %cmp, label %loop.check.1, label %exit 657 658loop.check.1: 659 %0 = zext i32 %n to i64 660 %src.upper = getelementptr inbounds i32, ptr %src, i64 %0 661 %add = add nuw nsw i32 %i.0, 2 662 %idxprom = zext i32 %add to i64 663 %src.idx = getelementptr inbounds i32, ptr %src, i64 %idxprom 664 %cmp.src.idx.upper = icmp ult ptr %src.idx, %src.upper 665 call void @use(i1 %cmp.src.idx.upper) 666 br i1 %cmp.src.idx.upper, label %loop.latch, label %exit 667 668loop.latch: 669 %dst.upper = getelementptr inbounds i32, ptr %dst, i64 %0 670 %dst.idx = getelementptr inbounds i32, ptr %dst, i64 %idxprom 671 %cmp.dst.idx.upper = icmp ult ptr %dst.idx, %dst.upper 672 call void @use(i1 %cmp.dst.idx.upper) 673 br i1 %cmp.dst.idx.upper, label %loop.latch.2, label %exit 674 675loop.latch.2: 676 br label %loop.header 677 678exit: 679 ret void 680} 681 682; Same as test_ptr_need_one_upper_check, but without inbounds GEP. 683define void @test_ptr_need_one_upper_check_no_inbounds(ptr readonly %src, ptr %dst, i32 %n) { 684; CHECK-LABEL: @test_ptr_need_one_upper_check_no_inbounds( 685; CHECK-NEXT: entry: 686; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 687; CHECK: loop.header: 688; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[LOOP_LATCH_2:%.*]] ] 689; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[N:%.*]] 690; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_CHECK_1:%.*]], label [[EXIT:%.*]] 691; CHECK: loop.check.1: 692; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 693; CHECK-NEXT: [[SRC_UPPER:%.*]] = getelementptr i32, ptr [[SRC:%.*]], i64 [[TMP0]] 694; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[I_0]], 2 695; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[ADD]] to i64 696; CHECK-NEXT: [[SRC_IDX:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[IDXPROM]] 697; CHECK-NEXT: [[CMP_SRC_IDX_UPPER:%.*]] = icmp ult ptr [[SRC_IDX]], [[SRC_UPPER]] 698; CHECK-NEXT: call void @use(i1 [[CMP_SRC_IDX_UPPER]]) 699; CHECK-NEXT: br i1 [[CMP_SRC_IDX_UPPER]], label [[LOOP_LATCH:%.*]], label [[EXIT]] 700; CHECK: loop.latch: 701; CHECK-NEXT: [[DST_UPPER:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[TMP0]] 702; CHECK-NEXT: [[DST_IDX:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IDXPROM]] 703; CHECK-NEXT: [[CMP_DST_IDX_UPPER:%.*]] = icmp ult ptr [[DST_IDX]], [[DST_UPPER]] 704; CHECK-NEXT: call void @use(i1 [[CMP_DST_IDX_UPPER]]) 705; CHECK-NEXT: br i1 [[CMP_DST_IDX_UPPER]], label [[LOOP_LATCH_2]], label [[EXIT]] 706; CHECK: loop.latch.2: 707; CHECK-NEXT: br label [[LOOP_HEADER]] 708; CHECK: exit: 709; CHECK-NEXT: ret void 710; 711entry: 712 br label %loop.header 713 714loop.header: 715 %i.0 = phi i32 [ 0, %entry ], [ %add, %loop.latch.2 ] 716 %cmp = icmp ult i32 %i.0, %n 717 br i1 %cmp, label %loop.check.1, label %exit 718 719loop.check.1: 720 %0 = zext i32 %n to i64 721 %src.upper = getelementptr i32, ptr %src, i64 %0 722 %add = add nuw nsw i32 %i.0, 2 723 %idxprom = zext i32 %add to i64 724 %src.idx = getelementptr inbounds i32, ptr %src, i64 %idxprom 725 %cmp.src.idx.upper = icmp ult ptr %src.idx, %src.upper 726 call void @use(i1 %cmp.src.idx.upper) 727 br i1 %cmp.src.idx.upper, label %loop.latch, label %exit 728 729loop.latch: 730 %dst.upper = getelementptr i32, ptr %dst, i64 %0 731 %dst.idx = getelementptr inbounds i32, ptr %dst, i64 %idxprom 732 %cmp.dst.idx.upper = icmp ult ptr %dst.idx, %dst.upper 733 call void @use(i1 %cmp.dst.idx.upper) 734 br i1 %cmp.dst.idx.upper, label %loop.latch.2, label %exit 735 736loop.latch.2: 737 br label %loop.header 738 739exit: 740 ret void 741} 742 743; Test case that exposed a crash in the earlier NewVariables handling code. 744define void @test_only_some_new_variables_may_be_0(ptr %A, ptr %start) { 745; CHECK-LABEL: @test_only_some_new_variables_may_be_0( 746; CHECK-NEXT: entry: 747; CHECK-NEXT: [[A_10:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 10 748; CHECK-NEXT: br label [[HEADER:%.*]] 749; CHECK: header: 750; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 751; CHECK-NEXT: [[A_IV:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]] 752; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[A_IV]], [[A_10]] 753; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[A_IV]], [[START:%.*]] 754; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]] 755; CHECK-NEXT: br i1 [[AND]], label [[LATCH]], label [[EXIT:%.*]] 756; CHECK: latch: 757; CHECK-NEXT: call void @clobber() 758; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], -1 759; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i64 [[IV]], 0 760; CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[HEADER]], label [[EXIT]] 761; CHECK: exit: 762; CHECK-NEXT: ret void 763; 764entry: 765 %A.10 = getelementptr inbounds i32, ptr %A, i64 10 766 br label %header 767 768header: 769 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] 770 %A.iv = getelementptr i32, ptr %A, i64 %iv 771 %c.1 = icmp ult ptr %A.iv, %A.10 772 %c.2 = icmp uge ptr %A.iv, %start 773 %and = and i1 %c.1, %c.2 774 br i1 %and, label %latch, label %exit 775 776latch: 777 call void @clobber() 778 %iv.next = add nsw i64 %iv, -1 779 %cmp.not.i = icmp eq i64 %iv, 0 780 br i1 %cmp.not.i, label %header, label %exit 781 782exit: 783 ret void 784} 785 786declare void @clobber() 787