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