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