1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4define i32 @test.ult(ptr readonly %src, ptr readnone %min, ptr readnone %max) { 5; CHECK-LABEL: @test.ult( 6; CHECK-NEXT: check.0.min: 7; CHECK-NEXT: [[C_MIN_0:%.*]] = icmp ult ptr [[SRC:%.*]], [[MIN:%.*]] 8; CHECK-NEXT: br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]] 9; CHECK: trap: 10; CHECK-NEXT: ret i32 10 11; CHECK: check.0.max: 12; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult ptr [[SRC]], [[MAX:%.*]] 13; CHECK-NEXT: br i1 [[C_MAX_0]], label [[CHECK_3_MIN:%.*]], label [[TRAP]] 14; CHECK: check.3.min: 15; CHECK-NEXT: [[L0:%.*]] = load i32, ptr [[SRC]], align 4 16; CHECK-NEXT: [[ADD_PTR_I36:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3 17; CHECK-NEXT: br i1 false, label [[TRAP]], label [[CHECK_3_MAX:%.*]] 18; CHECK: check.3.max: 19; CHECK-NEXT: [[C_3_MAX:%.*]] = icmp ult ptr [[ADD_PTR_I36]], [[MAX]] 20; CHECK-NEXT: br i1 [[C_3_MAX]], label [[CHECK_1_MIN:%.*]], label [[TRAP]] 21; CHECK: check.1.min: 22; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[ADD_PTR_I36]], align 4 23; CHECK-NEXT: [[ADD_PTR_I29:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 24; CHECK-NEXT: br i1 false, label [[TRAP]], label [[CHECK_1_MAX:%.*]] 25; CHECK: check.1.max: 26; CHECK-NEXT: br i1 true, label [[CHECK_2_MIN:%.*]], label [[TRAP]] 27; CHECK: check.2.min: 28; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[ADD_PTR_I29]], align 4 29; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2 30; CHECK-NEXT: br i1 false, label [[TRAP]], label [[CHECK_2_MAX:%.*]] 31; CHECK: check.2.max: 32; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[TRAP]] 33; CHECK: exit: 34; CHECK-NEXT: [[L3:%.*]] = load i32, ptr [[ADD_PTR_I]], align 4 35; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[L1]], [[L0]] 36; CHECK-NEXT: [[ADD8:%.*]] = add nsw i32 [[ADD]], [[L2]] 37; CHECK-NEXT: [[ADD9:%.*]] = add nsw i32 [[ADD8]], [[L3]] 38; CHECK-NEXT: ret i32 [[ADD9]] 39; 40check.0.min: 41 %c.min.0 = icmp ult ptr %src, %min 42 br i1 %c.min.0, label %trap, label %check.0.max 43 44trap: 45 ret i32 10 46 47check.0.max: 48 %c.max.0 = icmp ult ptr %src, %max 49 br i1 %c.max.0, label %check.3.min, label %trap 50 51check.3.min: 52 %l0 = load i32, ptr %src, align 4 53 %add.ptr.i36 = getelementptr inbounds i32, ptr %src, i64 3 54 %c.3.min = icmp ult ptr %add.ptr.i36, %min 55 br i1 %c.3.min, label %trap, label %check.3.max 56 57check.3.max: 58 %c.3.max = icmp ult ptr %add.ptr.i36, %max 59 br i1 %c.3.max, label %check.1.min, label %trap 60 61check.1.min: 62 %l1 = load i32, ptr %add.ptr.i36, align 4 63 %add.ptr.i29 = getelementptr inbounds i32, ptr %src, i64 1 64 %c.1.min = icmp ult ptr %add.ptr.i29, %min 65 br i1 %c.1.min, label %trap, label %check.1.max 66 67check.1.max: 68 %c.1.max = icmp ult ptr %add.ptr.i29, %max 69 br i1 %c.1.max, label %check.2.min, label %trap 70 71check.2.min: 72 %l2 = load i32, ptr %add.ptr.i29, align 4 73 %add.ptr.i = getelementptr inbounds i32, ptr %src, i64 2 74 %c.2.min = icmp ult ptr %add.ptr.i, %min 75 br i1 %c.2.min, label %trap, label %check.2.max 76 77check.2.max: 78 %c.2.max = icmp ult ptr %add.ptr.i, %max 79 br i1 %c.2.max, label %exit, label %trap 80 81exit: 82 %l3 = load i32, ptr %add.ptr.i, align 4 83 %add = add nsw i32 %l1, %l0 84 %add8 = add nsw i32 %add, %l2 85 %add9 = add nsw i32 %add8, %l3 86 ret i32 %add9 87} 88 89; Same as test.ult, but without inbounds. 90define i32 @test.ult_no_inbounds(ptr readonly %src, ptr readnone %min, ptr readnone %max) { 91; CHECK-LABEL: @test.ult_no_inbounds( 92; CHECK-NEXT: check.0.min: 93; CHECK-NEXT: [[C_MIN_0:%.*]] = icmp ult ptr [[SRC:%.*]], [[MIN:%.*]] 94; CHECK-NEXT: br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]] 95; CHECK: trap: 96; CHECK-NEXT: ret i32 10 97; CHECK: check.0.max: 98; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult ptr [[SRC]], [[MAX:%.*]] 99; CHECK-NEXT: br i1 [[C_MAX_0]], label [[CHECK_3_MIN:%.*]], label [[TRAP]] 100; CHECK: check.3.min: 101; CHECK-NEXT: [[L0:%.*]] = load i32, ptr [[SRC]], align 4 102; CHECK-NEXT: [[ADD_PTR_I36:%.*]] = getelementptr i32, ptr [[SRC]], i64 3 103; CHECK-NEXT: [[C_3_MIN:%.*]] = icmp ult ptr [[ADD_PTR_I36]], [[MIN]] 104; CHECK-NEXT: br i1 [[C_3_MIN]], label [[TRAP]], label [[CHECK_3_MAX:%.*]] 105; CHECK: check.3.max: 106; CHECK-NEXT: [[C_3_MAX:%.*]] = icmp ult ptr [[ADD_PTR_I36]], [[MAX]] 107; CHECK-NEXT: br i1 [[C_3_MAX]], label [[CHECK_1_MIN:%.*]], label [[TRAP]] 108; CHECK: check.1.min: 109; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[ADD_PTR_I36]], align 4 110; CHECK-NEXT: [[ADD_PTR_I29:%.*]] = getelementptr i32, ptr [[SRC]], i64 1 111; CHECK-NEXT: [[C_1_MIN:%.*]] = icmp ult ptr [[ADD_PTR_I29]], [[MIN]] 112; CHECK-NEXT: br i1 [[C_1_MIN]], label [[TRAP]], label [[CHECK_1_MAX:%.*]] 113; CHECK: check.1.max: 114; CHECK-NEXT: [[C_1_MAX:%.*]] = icmp ult ptr [[ADD_PTR_I29]], [[MAX]] 115; CHECK-NEXT: br i1 [[C_1_MAX]], label [[CHECK_2_MIN:%.*]], label [[TRAP]] 116; CHECK: check.2.min: 117; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[ADD_PTR_I29]], align 4 118; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i32, ptr [[SRC]], i64 2 119; CHECK-NEXT: [[C_2_MIN:%.*]] = icmp ult ptr [[ADD_PTR_I]], [[MIN]] 120; CHECK-NEXT: br i1 [[C_2_MIN]], label [[TRAP]], label [[CHECK_2_MAX:%.*]] 121; CHECK: check.2.max: 122; CHECK-NEXT: [[C_2_MAX:%.*]] = icmp ult ptr [[ADD_PTR_I]], [[MAX]] 123; CHECK-NEXT: br i1 [[C_2_MAX]], label [[EXIT:%.*]], label [[TRAP]] 124; CHECK: exit: 125; CHECK-NEXT: [[L3:%.*]] = load i32, ptr [[ADD_PTR_I]], align 4 126; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[L1]], [[L0]] 127; CHECK-NEXT: [[ADD8:%.*]] = add nsw i32 [[ADD]], [[L2]] 128; CHECK-NEXT: [[ADD9:%.*]] = add nsw i32 [[ADD8]], [[L3]] 129; CHECK-NEXT: ret i32 [[ADD9]] 130; 131check.0.min: 132 %c.min.0 = icmp ult ptr %src, %min 133 br i1 %c.min.0, label %trap, label %check.0.max 134 135trap: 136 ret i32 10 137 138check.0.max: 139 %c.max.0 = icmp ult ptr %src, %max 140 br i1 %c.max.0, label %check.3.min, label %trap 141 142check.3.min: 143 %l0 = load i32, ptr %src, align 4 144 %add.ptr.i36 = getelementptr i32, ptr %src, i64 3 145 %c.3.min = icmp ult ptr %add.ptr.i36, %min 146 br i1 %c.3.min, label %trap, label %check.3.max 147 148check.3.max: 149 %c.3.max = icmp ult ptr %add.ptr.i36, %max 150 br i1 %c.3.max, label %check.1.min, label %trap 151 152check.1.min: 153 %l1 = load i32, ptr %add.ptr.i36, align 4 154 %add.ptr.i29 = getelementptr i32, ptr %src, i64 1 155 %c.1.min = icmp ult ptr %add.ptr.i29, %min 156 br i1 %c.1.min, label %trap, label %check.1.max 157 158check.1.max: 159 %c.1.max = icmp ult ptr %add.ptr.i29, %max 160 br i1 %c.1.max, label %check.2.min, label %trap 161 162check.2.min: 163 %l2 = load i32, ptr %add.ptr.i29, align 4 164 %add.ptr.i = getelementptr i32, ptr %src, i64 2 165 %c.2.min = icmp ult ptr %add.ptr.i, %min 166 br i1 %c.2.min, label %trap, label %check.2.max 167 168check.2.max: 169 %c.2.max = icmp ult ptr %add.ptr.i, %max 170 br i1 %c.2.max, label %exit, label %trap 171 172exit: 173 %l3 = load i32, ptr %add.ptr.i, align 4 174 %add = add nsw i32 %l1, %l0 175 %add8 = add nsw i32 %add, %l2 176 %add9 = add nsw i32 %add8, %l3 177 ret i32 %add9 178} 179 180define void @test.not.uge.ult(ptr %start, ptr %low, ptr %high) { 181; CHECK-LABEL: @test.not.uge.ult( 182; CHECK-NEXT: entry: 183; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3 184; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[ADD_PTR_I]], [[HIGH:%.*]] 185; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 186; CHECK: if.then: 187; CHECK-NEXT: ret void 188; CHECK: if.end: 189; CHECK-NEXT: call void @use(i1 true) 190; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1 191; CHECK-NEXT: call void @use(i1 true) 192; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2 193; CHECK-NEXT: call void @use(i1 true) 194; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3 195; CHECK-NEXT: call void @use(i1 true) 196; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4 197; CHECK-NEXT: [[C_4:%.*]] = icmp ult ptr [[START_4]], [[HIGH]] 198; CHECK-NEXT: call void @use(i1 [[C_4]]) 199; CHECK-NEXT: ret void 200; 201entry: 202 %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3 203 %c.1 = icmp uge ptr %add.ptr.i, %high 204 br i1 %c.1, label %if.then, label %if.end 205 206if.then: 207 ret void 208 209if.end: 210 %t.0 = icmp ult ptr %start, %high 211 call void @use(i1 %t.0) 212 %start.1 = getelementptr inbounds i8, ptr %start, i64 1 213 %t.1 = icmp ult ptr %start.1, %high 214 call void @use(i1 %t.1) 215 %start.2 = getelementptr inbounds i8, ptr %start, i64 2 216 %t.2 = icmp ult ptr %start.2, %high 217 call void @use(i1 %t.2) 218 %start.3 = getelementptr inbounds i8, ptr %start, i64 3 219 %t.3 = icmp ult ptr %start.3, %high 220 call void @use(i1 %t.3) 221 %start.4 = getelementptr inbounds i8, ptr %start, i64 4 222 %c.4 = icmp ult ptr %start.4, %high 223 call void @use(i1 %c.4) 224 ret void 225} 226 227; Same as test.not.uge.ult, but without inbounds GEPs. 228define void @test.not.uge.ult_no_inbounds(ptr %start, ptr %low, ptr %high) { 229; CHECK-LABEL: @test.not.uge.ult_no_inbounds( 230; CHECK-NEXT: entry: 231; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i8, ptr [[START:%.*]], i64 3 232; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[ADD_PTR_I]], [[HIGH:%.*]] 233; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 234; CHECK: if.then: 235; CHECK-NEXT: ret void 236; CHECK: if.end: 237; CHECK-NEXT: [[T_0:%.*]] = icmp ult ptr [[START]], [[HIGH]] 238; CHECK-NEXT: call void @use(i1 [[T_0]]) 239; CHECK-NEXT: [[START_1:%.*]] = getelementptr i8, ptr [[START]], i64 1 240; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[START_1]], [[HIGH]] 241; CHECK-NEXT: call void @use(i1 [[T_1]]) 242; CHECK-NEXT: [[START_2:%.*]] = getelementptr i8, ptr [[START]], i64 2 243; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[START_2]], [[HIGH]] 244; CHECK-NEXT: call void @use(i1 [[T_2]]) 245; CHECK-NEXT: [[START_3:%.*]] = getelementptr i8, ptr [[START]], i64 3 246; CHECK-NEXT: [[T_3:%.*]] = icmp ult ptr [[START_3]], [[HIGH]] 247; CHECK-NEXT: call void @use(i1 [[T_3]]) 248; CHECK-NEXT: [[START_4:%.*]] = getelementptr i8, ptr [[START]], i64 4 249; CHECK-NEXT: [[C_4:%.*]] = icmp ult ptr [[START_4]], [[HIGH]] 250; CHECK-NEXT: call void @use(i1 [[C_4]]) 251; CHECK-NEXT: ret void 252; 253entry: 254 %add.ptr.i = getelementptr i8, ptr %start, i64 3 255 %c.1 = icmp uge ptr %add.ptr.i, %high 256 br i1 %c.1, label %if.then, label %if.end 257 258if.then: 259 ret void 260 261if.end: 262 %t.0 = icmp ult ptr %start, %high 263 call void @use(i1 %t.0) 264 %start.1 = getelementptr i8, ptr %start, i64 1 265 %t.1 = icmp ult ptr %start.1, %high 266 call void @use(i1 %t.1) 267 %start.2 = getelementptr i8, ptr %start, i64 2 268 %t.2 = icmp ult ptr %start.2, %high 269 call void @use(i1 %t.2) 270 %start.3 = getelementptr i8, ptr %start, i64 3 271 %t.3 = icmp ult ptr %start.3, %high 272 call void @use(i1 %t.3) 273 %start.4 = getelementptr i8, ptr %start, i64 4 274 %c.4 = icmp ult ptr %start.4, %high 275 call void @use(i1 %c.4) 276 ret void 277} 278 279define void @test.not.uge.ule(ptr %start, ptr %low, ptr %high) { 280; CHECK-LABEL: @test.not.uge.ule( 281; CHECK-NEXT: entry: 282; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3 283; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[ADD_PTR_I]], [[HIGH:%.*]] 284; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 285; CHECK: if.then: 286; CHECK-NEXT: ret void 287; CHECK: if.end: 288; CHECK-NEXT: call void @use(i1 true) 289; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1 290; CHECK-NEXT: call void @use(i1 true) 291; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2 292; CHECK-NEXT: call void @use(i1 true) 293; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3 294; CHECK-NEXT: call void @use(i1 true) 295; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4 296; CHECK-NEXT: call void @use(i1 true) 297; CHECK-NEXT: [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5 298; CHECK-NEXT: [[C_5:%.*]] = icmp ule ptr [[START_5]], [[HIGH]] 299; CHECK-NEXT: call void @use(i1 [[C_5]]) 300; CHECK-NEXT: ret void 301; 302entry: 303 %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3 304 %c.1 = icmp uge ptr %add.ptr.i, %high 305 br i1 %c.1, label %if.then, label %if.end 306 307if.then: 308 ret void 309 310if.end: 311 %t.0 = icmp ule ptr %start, %high 312 call void @use(i1 %t.0) 313 %start.1 = getelementptr inbounds i8, ptr %start, i64 1 314 %t.1 = icmp ule ptr %start.1, %high 315 call void @use(i1 %t.1) 316 %start.2 = getelementptr inbounds i8, ptr %start, i64 2 317 %t.2 = icmp ule ptr %start.2, %high 318 call void @use(i1 %t.2) 319 %start.3 = getelementptr inbounds i8, ptr %start, i64 3 320 %t.3 = icmp ule ptr %start.3, %high 321 call void @use(i1 %t.3) 322 %start.4 = getelementptr inbounds i8, ptr %start, i64 4 323 %t.4 = icmp ule ptr %start.4, %high 324 call void @use(i1 %t.4) 325 %start.5 = getelementptr inbounds i8, ptr %start, i64 5 326 %c.5 = icmp ule ptr %start.5, %high 327 call void @use(i1 %c.5) 328 ret void 329} 330 331define void @test.not.uge.ugt(ptr %start, ptr %low, ptr %high) { 332; CHECK-LABEL: @test.not.uge.ugt( 333; CHECK-NEXT: entry: 334; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3 335; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[ADD_PTR_I]], [[HIGH:%.*]] 336; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 337; CHECK: if.then: 338; CHECK-NEXT: ret void 339; CHECK: if.end: 340; CHECK-NEXT: call void @use(i1 false) 341; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1 342; CHECK-NEXT: call void @use(i1 false) 343; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2 344; CHECK-NEXT: call void @use(i1 false) 345; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3 346; CHECK-NEXT: call void @use(i1 false) 347; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4 348; CHECK-NEXT: call void @use(i1 false) 349; CHECK-NEXT: [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5 350; CHECK-NEXT: [[C_5:%.*]] = icmp ugt ptr [[START_5]], [[HIGH]] 351; CHECK-NEXT: call void @use(i1 [[C_5]]) 352; CHECK-NEXT: ret void 353; 354entry: 355 %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3 356 %c.1 = icmp uge ptr %add.ptr.i, %high 357 br i1 %c.1, label %if.then, label %if.end 358 359if.then: 360 ret void 361 362if.end: 363 %f.0 = icmp ugt ptr %start, %high 364 call void @use(i1 %f.0) 365 %start.1 = getelementptr inbounds i8, ptr %start, i64 1 366 %f.1 = icmp ugt ptr %start.1, %high 367 call void @use(i1 %f.1) 368 %start.2 = getelementptr inbounds i8, ptr %start, i64 2 369 %f.2 = icmp ugt ptr %start.2, %high 370 call void @use(i1 %f.2) 371 %start.3 = getelementptr inbounds i8, ptr %start, i64 3 372 %f.3 = icmp ugt ptr %start.3, %high 373 call void @use(i1 %f.3) 374 %start.4 = getelementptr inbounds i8, ptr %start, i64 4 375 %f.4 = icmp ugt ptr %start.4, %high 376 call void @use(i1 %f.4) 377 %start.5 = getelementptr inbounds i8, ptr %start, i64 5 378 %c.5 = icmp ugt ptr %start.5, %high 379 call void @use(i1 %c.5) 380 ret void 381} 382 383define void @test.not.uge.uge(ptr %start, ptr %low, ptr %high) { 384; CHECK-LABEL: @test.not.uge.uge( 385; CHECK-NEXT: entry: 386; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3 387; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[ADD_PTR_I]], [[HIGH:%.*]] 388; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 389; CHECK: if.then: 390; CHECK-NEXT: ret void 391; CHECK: if.end: 392; CHECK-NEXT: call void @use(i1 false) 393; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1 394; CHECK-NEXT: call void @use(i1 false) 395; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2 396; CHECK-NEXT: call void @use(i1 false) 397; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3 398; CHECK-NEXT: call void @use(i1 false) 399; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4 400; CHECK-NEXT: [[C_4:%.*]] = icmp uge ptr [[START_4]], [[HIGH]] 401; CHECK-NEXT: call void @use(i1 [[C_4]]) 402; CHECK-NEXT: [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5 403; CHECK-NEXT: [[C_5:%.*]] = icmp uge ptr [[START_5]], [[HIGH]] 404; CHECK-NEXT: call void @use(i1 [[C_5]]) 405; CHECK-NEXT: ret void 406; 407entry: 408 %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3 409 %c.1 = icmp uge ptr %add.ptr.i, %high 410 br i1 %c.1, label %if.then, label %if.end 411 412if.then: 413 ret void 414 415if.end: 416 %f.0 = icmp ugt ptr %start, %high 417 call void @use(i1 %f.0) 418 %start.1 = getelementptr inbounds i8, ptr %start, i64 1 419 %f.1 = icmp uge ptr %start.1, %high 420 call void @use(i1 %f.1) 421 %start.2 = getelementptr inbounds i8, ptr %start, i64 2 422 %f.2 = icmp uge ptr %start.2, %high 423 call void @use(i1 %f.2) 424 %start.3 = getelementptr inbounds i8, ptr %start, i64 3 425 %f.3 = icmp uge ptr %start.3, %high 426 call void @use(i1 %f.3) 427 %start.4 = getelementptr inbounds i8, ptr %start, i64 4 428 %c.4 = icmp uge ptr %start.4, %high 429 call void @use(i1 %c.4) 430 %start.5 = getelementptr inbounds i8, ptr %start, i64 5 431 %c.5 = icmp uge ptr %start.5, %high 432 call void @use(i1 %c.5) 433 ret void 434} 435 436define void @test.not.uge.uge.nonconst(ptr %start, ptr %low, ptr %high, i8 %off) { 437; CHECK-LABEL: @test.not.uge.uge.nonconst( 438; CHECK-NEXT: entry: 439; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i8 [[OFF:%.*]] 440; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[ADD_PTR_I]], [[HIGH:%.*]] 441; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 442; CHECK: if.then: 443; CHECK-NEXT: [[START_OFF_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i8 [[OFF]] 444; CHECK-NEXT: [[T_0:%.*]] = icmp uge ptr [[START_OFF_2]], [[HIGH]] 445; CHECK-NEXT: call void @use(i1 [[T_0]]) 446; CHECK-NEXT: ret void 447; CHECK: if.end: 448; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1 449; CHECK-NEXT: [[C_0:%.*]] = icmp uge ptr [[START_1]], [[HIGH]] 450; CHECK-NEXT: call void @use(i1 [[C_0]]) 451; CHECK-NEXT: [[START_OFF:%.*]] = getelementptr inbounds i8, ptr [[START]], i8 [[OFF]] 452; CHECK-NEXT: [[F_0:%.*]] = icmp uge ptr [[START_OFF]], [[HIGH]] 453; CHECK-NEXT: call void @use(i1 [[F_0]]) 454; CHECK-NEXT: ret void 455; 456entry: 457 %add.ptr.i = getelementptr inbounds i8, ptr %start, i8 %off 458 %c.1 = icmp uge ptr %add.ptr.i, %high 459 br i1 %c.1, label %if.then, label %if.end 460 461if.then: 462 %start.off.2 = getelementptr inbounds i8, ptr %start, i8 %off 463 %t.0 = icmp uge ptr %start.off.2, %high 464 call void @use(i1 %t.0) 465 ret void 466 467if.end: 468 %start.1 = getelementptr inbounds i8, ptr %start, i64 1 469 %c.0 = icmp uge ptr %start.1, %high 470 call void @use(i1 %c.0) 471 %start.off = getelementptr inbounds i8, ptr %start, i8 %off 472 %f.0 = icmp uge ptr %start.off, %high 473 call void @use(i1 %f.0) 474 ret void 475} 476 477; Test which requires decomposing GEP %ptr, SHL(). 478define void @test.ult.gep.shl(ptr readonly %src, ptr readnone %max, i8 %idx) { 479; CHECK-LABEL: @test.ult.gep.shl( 480; CHECK-NEXT: check.0.min: 481; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i32 10 482; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt ptr [[ADD_10]], [[MAX:%.*]] 483; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]] 484; CHECK: trap: 485; CHECK-NEXT: ret void 486; CHECK: check.idx: 487; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IDX:%.*]], 5 488; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]] 489; CHECK: check.max: 490; CHECK-NEXT: [[IDX_SHL_1:%.*]] = shl nuw nsw i8 [[IDX]], 1 491; CHECK-NEXT: [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_1]] 492; CHECK-NEXT: call void @use(i1 true) 493; CHECK-NEXT: [[IDX_SHL_2:%.*]] = shl nuw i8 [[IDX]], 2 494; CHECK-NEXT: [[ADD_PTR_SHL_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_2]] 495; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult ptr [[ADD_PTR_SHL_2]], [[MAX]] 496; CHECK-NEXT: call void @use(i1 [[C_MAX_1]]) 497; CHECK-NEXT: [[IDX_SHL_NOT_NUW:%.*]] = shl i8 [[IDX]], 1 498; CHECK-NEXT: [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_NOT_NUW]] 499; CHECK-NEXT: [[C_MAX_2:%.*]] = icmp ult ptr [[ADD_PTR_SHL_NOT_NUW]], [[MAX]] 500; CHECK-NEXT: call void @use(i1 [[C_MAX_2]]) 501; CHECK-NEXT: [[IDX_SHL_3:%.*]] = shl nuw i8 [[IDX]], 3 502; CHECK-NEXT: [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_3]] 503; CHECK-NEXT: [[C_MAX_3:%.*]] = icmp ult ptr [[ADD_PTR_SHL_3]], [[MAX]] 504; CHECK-NEXT: call void @use(i1 [[C_MAX_3]]) 505; CHECK-NEXT: ret void 506; 507check.0.min: 508 %add.10 = getelementptr inbounds i32, ptr %src, i32 10 509 %c.add.10.max = icmp ugt ptr %add.10, %max 510 br i1 %c.add.10.max, label %trap, label %check.idx 511 512trap: 513 ret void 514 515check.idx: 516 %cmp = icmp ult i8 %idx, 5 517 br i1 %cmp, label %check.max, label %trap 518 519check.max: 520 %idx.shl.1 = shl nsw nuw i8 %idx, 1 521 %add.ptr.shl.1 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.1 522 %c.max.0 = icmp ult ptr %add.ptr.shl.1, %max 523 call void @use(i1 %c.max.0) 524 %idx.shl.2 = shl nuw i8 %idx, 2 525 %add.ptr.shl.2 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.2 526 %c.max.1 = icmp ult ptr %add.ptr.shl.2, %max 527 call void @use(i1 %c.max.1) 528 %idx.shl.not.nuw = shl i8 %idx, 1 529 %add.ptr.shl.not.nuw = getelementptr inbounds i32, ptr %src, i8 %idx.shl.not.nuw 530 %c.max.2 = icmp ult ptr %add.ptr.shl.not.nuw, %max 531 call void @use(i1 %c.max.2) 532 %idx.shl.3 = shl nuw i8 %idx, 3 533 %add.ptr.shl.3 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.3 534 %c.max.3 = icmp ult ptr %add.ptr.shl.3, %max 535 call void @use(i1 %c.max.3) 536 ret void 537} 538 539; Test which requires decomposing GEP %ptr, ZEXT(SHL()). 540define void @test.ult.gep.shl.zext(ptr readonly %src, ptr readnone %max, i32 %idx, i32 %j) { 541; CHECK-LABEL: @test.ult.gep.shl.zext( 542; CHECK-NEXT: check.0.min: 543; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i32 10 544; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt ptr [[ADD_10]], [[MAX:%.*]] 545; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]] 546; CHECK: trap: 547; CHECK-NEXT: ret void 548; CHECK: check.idx: 549; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 5 550; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]] 551; CHECK: check.max: 552; CHECK-NEXT: [[IDX_SHL:%.*]] = shl nuw i32 [[IDX]], 1 553; CHECK-NEXT: [[EXT_1:%.*]] = zext i32 [[IDX_SHL]] to i64 554; CHECK-NEXT: [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_1]] 555; CHECK-NEXT: call void @use(i1 true) 556; CHECK-NEXT: [[IDX_SHL_NOT_NUW:%.*]] = shl i32 [[IDX]], 1 557; CHECK-NEXT: [[EXT_2:%.*]] = zext i32 [[IDX_SHL_NOT_NUW]] to i64 558; CHECK-NEXT: [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_2]] 559; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult ptr [[ADD_PTR_SHL_NOT_NUW]], [[MAX]] 560; CHECK-NEXT: call void @use(i1 [[C_MAX_1]]) 561; CHECK-NEXT: [[IDX_SHL_3:%.*]] = shl nuw i32 [[IDX]], 2 562; CHECK-NEXT: [[EXT_3:%.*]] = zext i32 [[IDX_SHL_3]] to i64 563; CHECK-NEXT: [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_3]] 564; CHECK-NEXT: [[C_MAX_2:%.*]] = icmp ult ptr [[ADD_PTR_SHL_3]], [[MAX]] 565; CHECK-NEXT: call void @use(i1 [[C_MAX_2]]) 566; CHECK-NEXT: ret void 567; 568check.0.min: 569 %add.10 = getelementptr inbounds i32, ptr %src, i32 10 570 %c.add.10.max = icmp ugt ptr %add.10, %max 571 br i1 %c.add.10.max, label %trap, label %check.idx 572 573trap: 574 ret void 575 576check.idx: 577 %cmp = icmp ult i32 %idx, 5 578 br i1 %cmp, label %check.max, label %trap 579 580check.max: 581 %idx.shl = shl nuw i32 %idx, 1 582 %ext.1 = zext i32 %idx.shl to i64 583 %add.ptr.shl = getelementptr inbounds i32, ptr %src, i64 %ext.1 584 %c.max.0 = icmp ult ptr %add.ptr.shl, %max 585 call void @use(i1 %c.max.0) 586 %idx.shl.not.nuw = shl i32 %idx, 1 587 %ext.2 = zext i32 %idx.shl.not.nuw to i64 588 %add.ptr.shl.not.nuw = getelementptr inbounds i32, ptr %src, i64 %ext.2 589 %c.max.1 = icmp ult ptr %add.ptr.shl.not.nuw, %max 590 call void @use(i1 %c.max.1) 591 %idx.shl.3 = shl nuw i32 %idx, 2 592 %ext.3 = zext i32 %idx.shl.3 to i64 593 %add.ptr.shl.3 = getelementptr inbounds i32, ptr %src, i64 %ext.3 594 %c.max.2 = icmp ult ptr %add.ptr.shl.3, %max 595 call void @use(i1 %c.max.2) 596 ret void 597} 598 599; Make sure non-constant shift amounts are handled correctly. 600define i1 @test.ult.gep.shl.nonconst.zext(i16 %B, ptr readonly %src, ptr readnone %max, i16 %idx, i16 %j) { 601; CHECK-LABEL: @test.ult.gep.shl.nonconst.zext( 602; CHECK-NEXT: check.0.min: 603; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i16, ptr [[SRC:%.*]], i16 10 604; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt ptr [[ADD_10]], [[MAX:%.*]] 605; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[EXIT_1:%.*]], label [[CHECK_IDX:%.*]] 606; CHECK: exit.1: 607; CHECK-NEXT: ret i1 true 608; CHECK: check.idx: 609; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[IDX:%.*]], 5 610; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP:%.*]] 611; CHECK: check.max: 612; CHECK-NEXT: [[IDX_SHL:%.*]] = shl nuw i16 [[IDX]], [[B:%.*]] 613; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[IDX_SHL]] to i64 614; CHECK-NEXT: [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i16, ptr [[SRC]], i64 [[EXT]] 615; CHECK-NEXT: [[C_MAX:%.*]] = icmp ult ptr [[ADD_PTR_SHL]], [[MAX]] 616; CHECK-NEXT: ret i1 [[C_MAX]] 617; CHECK: trap: 618; CHECK-NEXT: [[IDX_SHL_1:%.*]] = shl nuw i16 [[IDX]], [[B]] 619; CHECK-NEXT: [[EXT_1:%.*]] = zext i16 [[IDX_SHL_1]] to i64 620; CHECK-NEXT: [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i16, ptr [[SRC]], i64 [[EXT_1]] 621; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult ptr [[ADD_PTR_SHL_1]], [[MAX]] 622; CHECK-NEXT: ret i1 [[C_MAX_1]] 623; 624check.0.min: 625 %add.10 = getelementptr inbounds i16, ptr %src, i16 10 626 %c.add.10.max = icmp ugt ptr %add.10, %max 627 br i1 %c.add.10.max, label %exit.1, label %check.idx 628 629exit.1: 630 ret i1 true 631 632check.idx: 633 %cmp = icmp ult i16 %idx, 5 634 br i1 %cmp, label %check.max, label %trap 635 636check.max: 637 %idx.shl = shl nuw i16 %idx, %B 638 %ext = zext i16 %idx.shl to i64 639 %add.ptr.shl = getelementptr inbounds i16, ptr %src, i64 %ext 640 %c.max = icmp ult ptr %add.ptr.shl, %max 641 ret i1 %c.max 642 643trap: 644 %idx.shl.1 = shl nuw i16 %idx, %B 645 %ext.1 = zext i16 %idx.shl.1 to i64 646 %add.ptr.shl.1 = getelementptr inbounds i16, ptr %src, i64 %ext.1 647 %c.max.1 = icmp ult ptr %add.ptr.shl.1, %max 648 ret i1 %c.max.1 649} 650 651declare void @use(i1) 652