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