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_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[GEP_IV]] 411; CHECK-NEXT: [[CMP_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV]] 412; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_IV_LOWER]], [[CMP_IV_UPPER]] 413; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]] 414; CHECK: for.body.1: 415; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1 416; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[ADD]] 417; CHECK-NEXT: [[CMP_IV_1_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[GEP_IV_1]] 418; CHECK-NEXT: [[CMP_IV_1_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV_1]] 419; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_1_LOWER]], [[CMP_IV_1_UPPER]] 420; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] 421; CHECK: for.latch: 422; CHECK-NEXT: store i8 0, ptr [[GEP_IV]], align 4 423; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 424; CHECK-NEXT: br label [[FOR_HEADER]] 425; CHECK: for.end: 426; CHECK-NEXT: ret void 427; 428entry: 429 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 430 br i1 %cmp.ptr.lower, label %trap, label %pre 431 432pre: 433 %add.ptr = getelementptr inbounds i8, ptr %ptr, i16 %n 434 %cmp.ptr.n.upper = icmp ult ptr %add.ptr, %upper 435 br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap 436 437for.cond.preheader: 438 br label %for.header 439 440trap: 441 ret void 442 443for.header: 444 %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ] 445 %exitcond = icmp ne i16 %iv, %n 446 br i1 %exitcond, label %for.body, label %for.end 447 448for.body: 449 %gep.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 450 %cmp.iv.lower = icmp ugt ptr %lower, %gep.iv 451 %cmp.iv.upper = icmp ule ptr %upper, %gep.iv 452 %or = or i1 %cmp.iv.lower, %cmp.iv.upper 453 br i1 %or, label %trap, label %for.body.1 454 455for.body.1: 456 %add = add nuw nsw i16 %iv, 1 457 %gep.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %add 458 %cmp.iv.1.lower = icmp ugt ptr %lower, %gep.iv.1 459 %cmp.iv.1.upper = icmp ule ptr %upper, %gep.iv.1 460 %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper 461 br i1 %or.1, label %trap, label %for.latch 462 463for.latch: 464 store i8 0, ptr %gep.iv, align 4 465 %iv.next = add nuw nsw i16 %iv, 1 466 br label %for.header 467 468for.end: 469 ret void 470} 471 472; Should be able to remove the checks in the loop, because %n is signed positive. 473define void @ne_check_in_loop_no_zext_n_positive_check(ptr %ptr, ptr %lower, ptr %upper, i16 %n) { 474; CHECK-LABEL: @ne_check_in_loop_no_zext_n_positive_check( 475; CHECK-NEXT: entry: 476; CHECK-NEXT: [[N_SIGNED_POSITIVE:%.*]] = icmp slt i16 [[N:%.*]], 0 477; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 478; CHECK-NEXT: [[OR_T:%.*]] = or i1 [[N_SIGNED_POSITIVE]], [[CMP_PTR_LOWER]] 479; CHECK-NEXT: br i1 [[OR_T]], label [[TRAP:%.*]], label [[PRE:%.*]] 480; CHECK: pre: 481; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[N]] 482; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[ADD_PTR]], [[UPPER:%.*]] 483; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]] 484; CHECK: for.cond.preheader: 485; CHECK-NEXT: br label [[FOR_HEADER:%.*]] 486; CHECK: trap: 487; CHECK-NEXT: ret void 488; CHECK: for.header: 489; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ] 490; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[N]] 491; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 492; CHECK: for.body: 493; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 494; CHECK-NEXT: [[CMP_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[GEP_IV]] 495; CHECK-NEXT: [[CMP_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV]] 496; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_IV_LOWER]], [[CMP_IV_UPPER]] 497; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]] 498; CHECK: for.body.1: 499; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1 500; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[ADD]] 501; CHECK-NEXT: [[CMP_IV_1_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[GEP_IV_1]] 502; CHECK-NEXT: [[CMP_IV_1_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV_1]] 503; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_1_LOWER]], [[CMP_IV_1_UPPER]] 504; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] 505; CHECK: for.latch: 506; CHECK-NEXT: store i8 0, ptr [[GEP_IV]], align 4 507; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 508; CHECK-NEXT: br label [[FOR_HEADER]] 509; CHECK: for.end: 510; CHECK-NEXT: ret void 511; 512entry: 513 %n.signed.positive = icmp slt i16 %n, 0 514 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 515 %or.t = or i1 %n.signed.positive, %cmp.ptr.lower 516 br i1 %or.t, label %trap, label %pre 517 518pre: 519 %add.ptr = getelementptr inbounds i8, ptr %ptr, i16 %n 520 %cmp.ptr.n.upper = icmp ult ptr %add.ptr, %upper 521 br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap 522 523for.cond.preheader: 524 br label %for.header 525 526trap: 527 ret void 528 529for.header: 530 %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ] 531 %exitcond = icmp ne i16 %iv, %n 532 br i1 %exitcond, label %for.body, label %for.end 533 534for.body: 535 %gep.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 536 %cmp.iv.lower = icmp ugt ptr %lower, %gep.iv 537 %cmp.iv.upper = icmp ule ptr %upper, %gep.iv 538 %or = or i1 %cmp.iv.lower, %cmp.iv.upper 539 br i1 %or, label %trap, label %for.body.1 540 541for.body.1: 542 %add = add nuw nsw i16 %iv, 1 543 %gep.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %add 544 %cmp.iv.1.lower = icmp ugt ptr %lower, %gep.iv.1 545 %cmp.iv.1.upper = icmp ule ptr %upper, %gep.iv.1 546 %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper 547 br i1 %or.1, label %trap, label %for.latch 548 549for.latch: 550 store i8 0, ptr %gep.iv, align 4 551 %iv.next = add nuw nsw i16 %iv, 1 552 br label %for.header 553 554for.end: 555 ret void 556} 557 558; Make sure icmp ne of the induction variable in the loop body can be handled 559; and is treated as ule. 560define void @ne_check_in_loop_with_zext(ptr %ptr, ptr %lower, ptr %upper, i8 %n) { 561; CHECK-LABEL: @ne_check_in_loop_with_zext( 562; CHECK-NEXT: entry: 563; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 564; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE:%.*]] 565; CHECK: pre: 566; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[N:%.*]] to i16 567; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IDX_EXT]] 568; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[ADD_PTR]], [[UPPER:%.*]] 569; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]] 570; CHECK: for.cond.preheader: 571; CHECK-NEXT: br label [[FOR_HEADER:%.*]] 572; CHECK: trap: 573; CHECK-NEXT: ret void 574; CHECK: for.header: 575; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ] 576; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[IDX_EXT]] 577; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 578; CHECK: for.body: 579; CHECK-NEXT: [[GEP_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 580; CHECK-NEXT: [[CMP_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[GEP_IV]] 581; CHECK-NEXT: [[CMP_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV]] 582; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_IV_LOWER]], [[CMP_IV_UPPER]] 583; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]] 584; CHECK: for.body.1: 585; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1 586; CHECK-NEXT: [[GEP_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[ADD]] 587; CHECK-NEXT: [[CMP_IV_1_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[GEP_IV_1]] 588; CHECK-NEXT: [[CMP_IV_1_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[GEP_IV_1]] 589; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[CMP_IV_1_LOWER]], [[CMP_IV_1_UPPER]] 590; CHECK-NEXT: br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]] 591; CHECK: for.latch: 592; CHECK-NEXT: store i8 0, ptr [[GEP_IV]], align 4 593; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 594; CHECK-NEXT: br label [[FOR_HEADER]] 595; CHECK: for.end: 596; CHECK-NEXT: ret void 597; 598entry: 599 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 600 br i1 %cmp.ptr.lower, label %trap, label %pre 601 602pre: 603 %idx.ext = zext i8 %n to i16 604 %add.ptr = getelementptr inbounds i8, ptr %ptr, i16 %idx.ext 605 %cmp.ptr.n.upper = icmp ult ptr %add.ptr, %upper 606 br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap 607 608for.cond.preheader: 609 br label %for.header 610 611trap: 612 ret void 613 614for.header: 615 %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ] 616 %exitcond = icmp ne i16 %iv, %idx.ext 617 br i1 %exitcond, label %for.body, label %for.end 618 619for.body: 620 %gep.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 621 %cmp.iv.lower = icmp ugt ptr %lower, %gep.iv 622 %cmp.iv.upper = icmp ule ptr %upper, %gep.iv 623 %or = or i1 %cmp.iv.lower, %cmp.iv.upper 624 br i1 %or, label %trap, label %for.body.1 625 626for.body.1: 627 %add = add nuw nsw i16 %iv, 1 628 %gep.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %add 629 %cmp.iv.1.lower = icmp ugt ptr %lower, %gep.iv.1 630 %cmp.iv.1.upper = icmp ule ptr %upper, %gep.iv.1 631 %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper 632 br i1 %or.1, label %trap, label %for.latch 633 634for.latch: 635 store i8 0, ptr %gep.iv, align 4 636 %iv.next = add nuw nsw i16 %iv, 1 637 br label %for.header 638 639for.end: 640 ret void 641} 642 643define void @test_ptr_need_one_upper_check(ptr readonly %src, ptr %dst, i32 %n) { 644; CHECK-LABEL: @test_ptr_need_one_upper_check( 645; CHECK-NEXT: entry: 646; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 647; CHECK: loop.header: 648; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[LOOP_LATCH_2:%.*]] ] 649; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[N:%.*]] 650; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_CHECK_1:%.*]], label [[EXIT:%.*]] 651; CHECK: loop.check.1: 652; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 653; CHECK-NEXT: [[SRC_UPPER:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i64 [[TMP0]] 654; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[I_0]], 2 655; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[ADD]] to i64 656; CHECK-NEXT: [[SRC_IDX:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[IDXPROM]] 657; CHECK-NEXT: [[CMP_SRC_IDX_UPPER:%.*]] = icmp ult ptr [[SRC_IDX]], [[SRC_UPPER]] 658; CHECK-NEXT: call void @use(i1 [[CMP_SRC_IDX_UPPER]]) 659; CHECK-NEXT: br i1 [[CMP_SRC_IDX_UPPER]], label [[LOOP_LATCH:%.*]], label [[EXIT]] 660; CHECK: loop.latch: 661; CHECK-NEXT: [[DST_UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[TMP0]] 662; CHECK-NEXT: [[DST_IDX:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IDXPROM]] 663; CHECK-NEXT: call void @use(i1 true) 664; CHECK-NEXT: br i1 true, label [[LOOP_LATCH_2]], label [[EXIT]] 665; CHECK: loop.latch.2: 666; CHECK-NEXT: br label [[LOOP_HEADER]] 667; CHECK: exit: 668; CHECK-NEXT: ret void 669; 670entry: 671 br label %loop.header 672 673loop.header: 674 %i.0 = phi i32 [ 0, %entry ], [ %add, %loop.latch.2 ] 675 %cmp = icmp ult i32 %i.0, %n 676 br i1 %cmp, label %loop.check.1, label %exit 677 678loop.check.1: 679 %0 = zext i32 %n to i64 680 %src.upper = getelementptr inbounds i32, ptr %src, i64 %0 681 %add = add nuw nsw i32 %i.0, 2 682 %idxprom = zext i32 %add to i64 683 %src.idx = getelementptr inbounds i32, ptr %src, i64 %idxprom 684 %cmp.src.idx.upper = icmp ult ptr %src.idx, %src.upper 685 call void @use(i1 %cmp.src.idx.upper) 686 br i1 %cmp.src.idx.upper, label %loop.latch, label %exit 687 688loop.latch: 689 %dst.upper = getelementptr inbounds i32, ptr %dst, i64 %0 690 %dst.idx = getelementptr inbounds i32, ptr %dst, i64 %idxprom 691 %cmp.dst.idx.upper = icmp ult ptr %dst.idx, %dst.upper 692 call void @use(i1 %cmp.dst.idx.upper) 693 br i1 %cmp.dst.idx.upper, label %loop.latch.2, label %exit 694 695loop.latch.2: 696 br label %loop.header 697 698exit: 699 ret void 700} 701 702; Same as test_ptr_need_one_upper_check, but without inbounds GEP. 703define void @test_ptr_need_one_upper_check_no_inbounds(ptr readonly %src, ptr %dst, i32 %n) { 704; CHECK-LABEL: @test_ptr_need_one_upper_check_no_inbounds( 705; CHECK-NEXT: entry: 706; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 707; CHECK: loop.header: 708; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[LOOP_LATCH_2:%.*]] ] 709; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[N:%.*]] 710; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_CHECK_1:%.*]], label [[EXIT:%.*]] 711; CHECK: loop.check.1: 712; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 713; CHECK-NEXT: [[SRC_UPPER:%.*]] = getelementptr i32, ptr [[SRC:%.*]], i64 [[TMP0]] 714; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[I_0]], 2 715; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[ADD]] to i64 716; CHECK-NEXT: [[SRC_IDX:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[IDXPROM]] 717; CHECK-NEXT: [[CMP_SRC_IDX_UPPER:%.*]] = icmp ult ptr [[SRC_IDX]], [[SRC_UPPER]] 718; CHECK-NEXT: call void @use(i1 [[CMP_SRC_IDX_UPPER]]) 719; CHECK-NEXT: br i1 [[CMP_SRC_IDX_UPPER]], label [[LOOP_LATCH:%.*]], label [[EXIT]] 720; CHECK: loop.latch: 721; CHECK-NEXT: [[DST_UPPER:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[TMP0]] 722; CHECK-NEXT: [[DST_IDX:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IDXPROM]] 723; CHECK-NEXT: [[CMP_DST_IDX_UPPER:%.*]] = icmp ult ptr [[DST_IDX]], [[DST_UPPER]] 724; CHECK-NEXT: call void @use(i1 [[CMP_DST_IDX_UPPER]]) 725; CHECK-NEXT: br i1 [[CMP_DST_IDX_UPPER]], label [[LOOP_LATCH_2]], label [[EXIT]] 726; CHECK: loop.latch.2: 727; CHECK-NEXT: br label [[LOOP_HEADER]] 728; CHECK: exit: 729; CHECK-NEXT: ret void 730; 731entry: 732 br label %loop.header 733 734loop.header: 735 %i.0 = phi i32 [ 0, %entry ], [ %add, %loop.latch.2 ] 736 %cmp = icmp ult i32 %i.0, %n 737 br i1 %cmp, label %loop.check.1, label %exit 738 739loop.check.1: 740 %0 = zext i32 %n to i64 741 %src.upper = getelementptr i32, ptr %src, i64 %0 742 %add = add nuw nsw i32 %i.0, 2 743 %idxprom = zext i32 %add to i64 744 %src.idx = getelementptr inbounds i32, ptr %src, i64 %idxprom 745 %cmp.src.idx.upper = icmp ult ptr %src.idx, %src.upper 746 call void @use(i1 %cmp.src.idx.upper) 747 br i1 %cmp.src.idx.upper, label %loop.latch, label %exit 748 749loop.latch: 750 %dst.upper = getelementptr i32, ptr %dst, i64 %0 751 %dst.idx = getelementptr inbounds i32, ptr %dst, i64 %idxprom 752 %cmp.dst.idx.upper = icmp ult ptr %dst.idx, %dst.upper 753 call void @use(i1 %cmp.dst.idx.upper) 754 br i1 %cmp.dst.idx.upper, label %loop.latch.2, label %exit 755 756loop.latch.2: 757 br label %loop.header 758 759exit: 760 ret void 761} 762 763; Test case that exposed a crash in the earlier NewVariables handling code. 764define void @test_only_some_new_variables_may_be_0(ptr %A, ptr %start) { 765; CHECK-LABEL: @test_only_some_new_variables_may_be_0( 766; CHECK-NEXT: entry: 767; CHECK-NEXT: [[A_10:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 10 768; CHECK-NEXT: br label [[HEADER:%.*]] 769; CHECK: header: 770; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 771; CHECK-NEXT: [[A_IV:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]] 772; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[A_IV]], [[A_10]] 773; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[A_IV]], [[START:%.*]] 774; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]] 775; CHECK-NEXT: br i1 [[AND]], label [[LATCH]], label [[EXIT:%.*]] 776; CHECK: latch: 777; CHECK-NEXT: call void @clobber() 778; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], -1 779; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i64 [[IV]], 0 780; CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[HEADER]], label [[EXIT]] 781; CHECK: exit: 782; CHECK-NEXT: ret void 783; 784entry: 785 %A.10 = getelementptr inbounds i32, ptr %A, i64 10 786 br label %header 787 788header: 789 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] 790 %A.iv = getelementptr i32, ptr %A, i64 %iv 791 %c.1 = icmp ult ptr %A.iv, %A.10 792 %c.2 = icmp uge ptr %A.iv, %start 793 %and = and i1 %c.1, %c.2 794 br i1 %and, label %latch, label %exit 795 796latch: 797 call void @clobber() 798 %iv.next = add nsw i64 %iv, -1 799 %cmp.not.i = icmp eq i64 %iv, 0 800 br i1 %cmp.not.i, label %header, label %exit 801 802exit: 803 ret void 804} 805 806declare void @clobber() 807