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 @llvm.assume(i1 noundef) #0 5 6define i1 @gep_constant_positive_index(ptr %dst, ptr %lower, ptr %upper) { 7; CHECK-LABEL: @gep_constant_positive_index( 8; CHECK-NEXT: [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 4 9; CHECK-NEXT: [[PRE_DST_LOWER:%.*]] = icmp uge ptr [[DST]], [[LOWER:%.*]] 10; CHECK-NEXT: [[PRE_DST_UPPER:%.*]] = icmp ult ptr [[DST_ADD_4]], [[UPPER:%.*]] 11; CHECK-NEXT: [[AND:%.*]] = and i1 [[PRE_DST_LOWER]], [[PRE_DST_UPPER]] 12; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]] 13; CHECK: then: 14; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 15; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3 16; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true 17; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], true 18; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true 19; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true 20; CHECK-NEXT: [[DST_ADD_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 5 21; CHECK-NEXT: [[CMP_DST_ADD_5_UPPER:%.*]] = icmp ult ptr [[DST_ADD_5]], [[UPPER]] 22; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], true 23; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[CMP_DST_ADD_5_UPPER]] 24; CHECK-NEXT: ret i1 [[RES_7]] 25; CHECK: else: 26; CHECK-NEXT: ret i1 false 27; 28 %dst.add.4 = getelementptr inbounds i8, ptr %dst, i64 4 29 %pre.dst.lower = icmp uge ptr %dst, %lower 30 %pre.dst.upper = icmp ult ptr %dst.add.4, %upper 31 %and = and i1 %pre.dst.lower, %pre.dst.upper 32 br i1 %and, label %then, label %else 33 34then: 35 %cmp.dst.lower = icmp uge ptr %dst, %lower 36 %cmp.dst.upper = icmp ult ptr %dst, %upper 37 %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper 38 %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3 39 %cmp.dst.add.3.lower = icmp uge ptr %dst.add.3, %lower 40 %cmp.dst.add.3.upper = icmp ult ptr %dst.add.3, %upper 41 %res.2 = xor i1 %res.1, %cmp.dst.add.3.lower 42 %res.3 = xor i1 %res.2, %cmp.dst.add.3.upper 43 %cmp.dst.add.4.lower = icmp uge ptr %dst.add.4, %lower 44 %cmp.dst.add.4.upper = icmp ult ptr %dst.add.4, %upper 45 %res.4 = xor i1 %res.3, %cmp.dst.add.4.lower 46 %res.5 = xor i1 %res.4, %cmp.dst.add.4.upper 47 %dst.add.5 = getelementptr inbounds i8, ptr %dst, i64 5 48 %cmp.dst.add.5.lower = icmp uge ptr %dst.add.5, %lower 49 %cmp.dst.add.5.upper = icmp ult ptr %dst.add.5, %upper 50 %res.6 = xor i1 %res.5, %cmp.dst.add.5.lower 51 %res.7 = xor i1 %res.6, %cmp.dst.add.5.upper 52 ret i1 %res.7 53 54else: 55 ret i1 false 56} 57 58define i1 @gep_constant_negative_index(ptr %dst, ptr %lower, ptr %upper) { 59; CHECK-LABEL: @gep_constant_negative_index( 60; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 -4 61; CHECK-NEXT: [[PRE_DST_LOWER:%.*]] = icmp uge ptr [[DST]], [[LOWER:%.*]] 62; CHECK-NEXT: [[PRE_DST_UPPER:%.*]] = icmp ult ptr [[DST_SUB_4]], [[UPPER:%.*]] 63; CHECK-NEXT: [[AND:%.*]] = and i1 [[PRE_DST_LOWER]], [[PRE_DST_UPPER]] 64; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]] 65; CHECK: then: 66; CHECK-NEXT: [[CMP_DST_UPPER:%.*]] = icmp ult ptr [[DST]], [[UPPER]] 67; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[CMP_DST_UPPER]] 68; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -3 69; CHECK-NEXT: [[CMP_DST_SUB_3_LOWER:%.*]] = icmp uge ptr [[DST_SUB_3]], [[LOWER]] 70; CHECK-NEXT: [[CMP_DST_SUB_3_UPPER:%.*]] = icmp ult ptr [[DST_SUB_3]], [[UPPER]] 71; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_DST_SUB_3_LOWER]] 72; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], [[CMP_DST_SUB_3_UPPER]] 73; CHECK-NEXT: [[CMP_DST_SUB_4_LOWER:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]] 74; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[CMP_DST_SUB_4_LOWER]] 75; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true 76; CHECK-NEXT: [[DST_SUB_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -5 77; CHECK-NEXT: [[CMP_DST_SUB_5_LOWER:%.*]] = icmp uge ptr [[DST_SUB_5]], [[LOWER]] 78; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[CMP_DST_SUB_5_LOWER]] 79; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], true 80; CHECK-NEXT: ret i1 [[RES_7]] 81; CHECK: else: 82; CHECK-NEXT: [[ELSE_CMP_DST_LOWER:%.*]] = icmp uge ptr [[DST]], [[LOWER]] 83; CHECK-NEXT: [[ELSE_CMP_DST_UPPER:%.*]] = icmp ult ptr [[DST]], [[UPPER]] 84; CHECK-NEXT: [[ELSE_RES_1:%.*]] = xor i1 [[ELSE_CMP_DST_LOWER]], [[ELSE_CMP_DST_UPPER]] 85; CHECK-NEXT: [[ELSE_DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -3 86; CHECK-NEXT: [[ELSE_CMP_DST_SUB_3_LOWER:%.*]] = icmp uge ptr [[ELSE_DST_SUB_3]], [[LOWER]] 87; CHECK-NEXT: [[ELSE_CMP_DST_SUB_3_UPPER:%.*]] = icmp ult ptr [[ELSE_DST_SUB_3]], [[UPPER]] 88; CHECK-NEXT: [[ELSE_RES_2:%.*]] = xor i1 [[ELSE_RES_1]], [[ELSE_CMP_DST_SUB_3_LOWER]] 89; CHECK-NEXT: [[ELSE_RES_3:%.*]] = xor i1 [[ELSE_RES_2]], [[ELSE_CMP_DST_SUB_3_UPPER]] 90; CHECK-NEXT: [[ELSE_CMP_DST_SUB_4_LOWER:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]] 91; CHECK-NEXT: [[ELSE_CMP_DST_SUB_4_UPPER:%.*]] = icmp ult ptr [[DST_SUB_4]], [[UPPER]] 92; CHECK-NEXT: [[ELSE_RES_4:%.*]] = xor i1 [[ELSE_RES_3]], [[ELSE_CMP_DST_SUB_4_LOWER]] 93; CHECK-NEXT: [[ELSE_RES_5:%.*]] = xor i1 [[ELSE_RES_4]], [[ELSE_CMP_DST_SUB_4_UPPER]] 94; CHECK-NEXT: [[ELSE_DST_SUB_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -5 95; CHECK-NEXT: [[ELSE_CMP_DST_SUB_5_LOWER:%.*]] = icmp uge ptr [[ELSE_DST_SUB_5]], [[LOWER]] 96; CHECK-NEXT: [[ELSE_CMP_DST_SUB_5_UPPER:%.*]] = icmp ult ptr [[ELSE_DST_SUB_5]], [[UPPER]] 97; CHECK-NEXT: [[ELSE_RES_6:%.*]] = xor i1 [[ELSE_RES_5]], [[ELSE_CMP_DST_SUB_5_LOWER]] 98; CHECK-NEXT: [[ELSE_RES_7:%.*]] = xor i1 [[ELSE_RES_6]], [[ELSE_CMP_DST_SUB_5_UPPER]] 99; CHECK-NEXT: ret i1 [[ELSE_RES_7]] 100; 101 %dst.sub.4 = getelementptr inbounds i8, ptr %dst, i64 -4 102 %pre.dst.lower = icmp uge ptr %dst, %lower 103 %pre.dst.upper = icmp ult ptr %dst.sub.4, %upper 104 %and = and i1 %pre.dst.lower, %pre.dst.upper 105 br i1 %and, label %then, label %else 106 107then: 108 %cmp.dst.lower = icmp uge ptr %dst, %lower 109 %cmp.dst.upper = icmp ult ptr %dst, %upper 110 %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper 111 %dst.sub.3 = getelementptr inbounds i8, ptr %dst, i64 -3 112 %cmp.dst.sub.3.lower = icmp uge ptr %dst.sub.3, %lower 113 %cmp.dst.sub.3.upper = icmp ult ptr %dst.sub.3, %upper 114 %res.2 = xor i1 %res.1, %cmp.dst.sub.3.lower 115 %res.3 = xor i1 %res.2, %cmp.dst.sub.3.upper 116 %cmp.dst.sub.4.lower = icmp uge ptr %dst.sub.4, %lower 117 %cmp.dst.sub.4.upper = icmp ult ptr %dst.sub.4, %upper 118 %res.4 = xor i1 %res.3, %cmp.dst.sub.4.lower 119 %res.5 = xor i1 %res.4, %cmp.dst.sub.4.upper 120 %dst.sub.5 = getelementptr inbounds i8, ptr %dst, i64 -5 121 %cmp.dst.sub.5.lower = icmp uge ptr %dst.sub.5, %lower 122 %cmp.dst.sub.5.upper = icmp ult ptr %dst.sub.5, %upper 123 %res.6 = xor i1 %res.5, %cmp.dst.sub.5.lower 124 %res.7 = xor i1 %res.6, %cmp.dst.sub.5.upper 125 ret i1 %res.7 126 127else: 128 %else.cmp.dst.lower = icmp uge ptr %dst, %lower 129 %else.cmp.dst.upper = icmp ult ptr %dst, %upper 130 %else.res.1 = xor i1 %else.cmp.dst.lower, %else.cmp.dst.upper 131 %else.dst.sub.3 = getelementptr inbounds i8, ptr %dst, i64 -3 132 %else.cmp.dst.sub.3.lower = icmp uge ptr %else.dst.sub.3, %lower 133 %else.cmp.dst.sub.3.upper = icmp ult ptr %else.dst.sub.3, %upper 134 %else.res.2 = xor i1 %else.res.1, %else.cmp.dst.sub.3.lower 135 %else.res.3 = xor i1 %else.res.2, %else.cmp.dst.sub.3.upper 136 %else.cmp.dst.sub.4.lower = icmp uge ptr %dst.sub.4, %lower 137 %else.cmp.dst.sub.4.upper = icmp ult ptr %dst.sub.4, %upper 138 %else.res.4 = xor i1 %else.res.3, %else.cmp.dst.sub.4.lower 139 %else.res.5 = xor i1 %else.res.4, %else.cmp.dst.sub.4.upper 140 %else.dst.sub.5 = getelementptr inbounds i8, ptr %dst, i64 -5 141 %else.cmp.dst.sub.5.lower = icmp uge ptr %else.dst.sub.5, %lower 142 %else.cmp.dst.sub.5.upper = icmp ult ptr %else.dst.sub.5, %upper 143 %else.res.6 = xor i1 %else.res.5, %else.cmp.dst.sub.5.lower 144 %else.res.7 = xor i1 %else.res.6, %else.cmp.dst.sub.5.upper 145 ret i1 %else.res.7 146} 147 148define i4 @ptr_N_signed_positive_explicit_check_constant_step(ptr %src, ptr %lower, ptr %upper, i16 %N) { 149; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step( 150; CHECK-NEXT: entry: 151; CHECK-NEXT: [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0 152; CHECK-NEXT: br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] 153; CHECK: entry.1: 154; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N]] 155; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 156; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 157; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 158; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] 159; CHECK: trap.bb: 160; CHECK-NEXT: ret i4 2 161; CHECK: step.check: 162; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]] 163; CHECK-NEXT: br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 164; CHECK: ptr.check: 165; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1 166; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false 167; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 168; CHECK: exit: 169; CHECK-NEXT: ret i4 3 170; 171entry: 172 %N.pos = icmp sge i16 %N, 0 173 br i1 %N.pos, label %entry.1, label %trap.bb 174 175entry.1: 176 %src.end = getelementptr inbounds i8, ptr %src, i16 %N 177 %cmp.src.start = icmp ult ptr %src, %lower 178 %cmp.src.end = icmp uge ptr %src.end, %upper 179 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 180 br i1 %or.precond.0, label %trap.bb, label %step.check 181 182trap.bb: 183 ret i4 2 184 185step.check: 186 %step.ult.N = icmp ult i16 1, %N 187 br i1 %step.ult.N, label %ptr.check, label %exit 188 189ptr.check: 190 %src.step = getelementptr inbounds i8, ptr %src, i16 1 191 %cmp.step.start = icmp ult ptr %src.step, %lower 192 %cmp.step.end = icmp uge ptr %src.step, %upper 193 %or.check = or i1 %cmp.step.start, %cmp.step.end 194 br i1 %or.check, label %trap.bb, label %exit 195 196exit: 197 ret i4 3 198} 199 200; Same as ptr_N_signed_positive_explicit_check_constant_step, but without inbounds. 201define i4 @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(ptr %src, ptr %lower, ptr %upper, i16 %N) { 202; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds( 203; CHECK-NEXT: entry: 204; CHECK-NEXT: [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0 205; CHECK-NEXT: br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] 206; CHECK: entry.1: 207; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i16 [[N]] 208; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 209; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 210; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 211; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] 212; CHECK: trap.bb: 213; CHECK-NEXT: ret i4 2 214; CHECK: step.check: 215; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]] 216; CHECK-NEXT: br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 217; CHECK: ptr.check: 218; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr i8, ptr [[SRC]], i16 1 219; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] 220; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]] 221; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] 222; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 223; CHECK: exit: 224; CHECK-NEXT: ret i4 3 225; 226entry: 227 %N.pos = icmp sge i16 %N, 0 228 br i1 %N.pos, label %entry.1, label %trap.bb 229 230entry.1: 231 %src.end = getelementptr i8, ptr %src, i16 %N 232 %cmp.src.start = icmp ult ptr %src, %lower 233 %cmp.src.end = icmp uge ptr %src.end, %upper 234 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 235 br i1 %or.precond.0, label %trap.bb, label %step.check 236 237trap.bb: 238 ret i4 2 239 240step.check: 241 %step.ult.N = icmp ult i16 1, %N 242 br i1 %step.ult.N, label %ptr.check, label %exit 243 244ptr.check: 245 %src.step = getelementptr i8, ptr %src, i16 1 246 %cmp.step.start = icmp ult ptr %src.step, %lower 247 %cmp.step.end = icmp uge ptr %src.step, %upper 248 %or.check = or i1 %cmp.step.start, %cmp.step.end 249 br i1 %or.check, label %trap.bb, label %exit 250 251exit: 252 ret i4 3 253} 254 255define i4 @ptr_N_and_step_signed_positive_explicit_check_constant_step(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { 256; CHECK-LABEL: @ptr_N_and_step_signed_positive_explicit_check_constant_step( 257; CHECK-NEXT: entry: 258; CHECK-NEXT: [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0 259; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0 260; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[N_POS]], [[STEP_POS]] 261; CHECK-NEXT: br i1 [[AND_1]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] 262; CHECK: entry.1: 263; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N]] 264; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 265; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 266; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 267; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] 268; CHECK: trap.bb: 269; CHECK-NEXT: ret i4 2 270; CHECK: step.check: 271; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]] 272; CHECK-NEXT: [[AND_2:%.*]] = and i1 true, [[STEP_ULT_N]] 273; CHECK-NEXT: br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 274; CHECK: ptr.check: 275; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1 276; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false 277; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 278; CHECK: exit: 279; CHECK-NEXT: ret i4 3 280; 281entry: 282 %N.pos = icmp sge i16 %N, 0 283 %step.pos = icmp sge i16 %step, 0 284 %and.1 = and i1 %N.pos, %step.pos 285 br i1 %and.1, label %entry.1, label %trap.bb 286 287entry.1: 288 %src.end = getelementptr inbounds i8, ptr %src, i16 %N 289 %cmp.src.start = icmp ult ptr %src, %lower 290 %cmp.src.end = icmp uge ptr %src.end, %upper 291 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 292 br i1 %or.precond.0, label %trap.bb, label %step.check 293 294trap.bb: 295 ret i4 2 296 297step.check: 298 %step.uge.0 = icmp uge i16 %step, 0 299 %step.ult.N = icmp ult i16 %step, %N 300 %and.2 = and i1 %step.uge.0, %step.ult.N 301 br i1 %and.2, label %ptr.check, label %exit 302 303ptr.check: 304 %src.step = getelementptr inbounds i8, ptr %src, i16 1 305 %cmp.step.start = icmp ult ptr %src.step, %lower 306 %cmp.step.end = icmp uge ptr %src.step, %upper 307 %or.check = or i1 %cmp.step.start, %cmp.step.end 308 br i1 %or.check, label %trap.bb, label %exit 309 310exit: 311 ret i4 3 312} 313 314define i4 @ptr_N_and_step_signed_positive_unsigned_checks_only(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { 315; CHECK-LABEL: @ptr_N_and_step_signed_positive_unsigned_checks_only( 316; CHECK-NEXT: entry: 317; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] 318; CHECK-NEXT: [[NO_OVERFLOW:%.*]] = icmp ule ptr [[SRC]], [[SRC_END]] 319; CHECK-NEXT: br i1 [[NO_OVERFLOW]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] 320; CHECK: entry.1: 321; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 322; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 323; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 324; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] 325; CHECK: trap.bb: 326; CHECK-NEXT: ret i4 2 327; CHECK: step.check: 328; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]] 329; CHECK-NEXT: [[AND_2:%.*]] = and i1 true, [[STEP_ULT_N]] 330; CHECK-NEXT: br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 331; CHECK: ptr.check: 332; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1 333; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]] 334; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, [[CMP_STEP_END]] 335; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 336; CHECK: exit: 337; CHECK-NEXT: ret i4 3 338; 339entry: 340 %src.end = getelementptr inbounds i8, ptr %src, i16 %N 341 %no.overflow = icmp ule ptr %src, %src.end 342 br i1 %no.overflow, label %entry.1, label %trap.bb 343 344entry.1: 345 %cmp.src.start = icmp ult ptr %src, %lower 346 %cmp.src.end = icmp uge ptr %src.end, %upper 347 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 348 br i1 %or.precond.0, label %trap.bb, label %step.check 349 350trap.bb: 351 ret i4 2 352 353step.check: 354 %step.uge.0 = icmp uge i16 %step, 0 355 %step.ult.N = icmp ult i16 %step, %N 356 %and.2 = and i1 %step.uge.0, %step.ult.N 357 br i1 %and.2, label %ptr.check, label %exit 358 359ptr.check: 360 %src.step = getelementptr inbounds i8, ptr %src, i16 1 361 %cmp.step.start = icmp ult ptr %src.step, %lower 362 %cmp.step.end = icmp uge ptr %src.step, %upper 363 %or.check = or i1 %cmp.step.start, %cmp.step.end 364 br i1 %or.check, label %trap.bb, label %exit 365 366exit: 367 ret i4 3 368} 369 370define i4 @ptr_N_signed_positive(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { 371; CHECK-LABEL: @ptr_N_signed_positive( 372; CHECK-NEXT: entry: 373; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] 374; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 375; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 376; CHECK-NEXT: [[N_NEG:%.*]] = icmp slt i16 [[N]], 0 377; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 378; CHECK-NEXT: [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]] 379; CHECK-NEXT: br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] 380; CHECK: trap.bb: 381; CHECK-NEXT: ret i4 2 382; CHECK: step.check: 383; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]] 384; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]] 385; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 386; CHECK: ptr.check: 387; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]] 388; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 false, false 389; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 390; CHECK: exit: 391; CHECK-NEXT: ret i4 3 392; 393entry: 394 %src.end = getelementptr inbounds i8, ptr %src, i16 %N 395 %cmp.src.start = icmp ult ptr %src, %lower 396 %cmp.src.end = icmp uge ptr %src.end, %upper 397 %N.neg = icmp slt i16 %N, 0 398 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 399 %or.precond.1 = or i1 %or.precond.0, %N.neg 400 br i1 %or.precond.1, label %trap.bb, label %step.check 401 402trap.bb: 403 ret i4 2 404 405step.check: 406 %step.pos = icmp uge i16 %step, 0 407 %step.ult.N = icmp ult i16 %step, %N 408 %and.step = and i1 %step.pos, %step.ult.N 409 br i1 %and.step, label %ptr.check, label %exit 410 411ptr.check: 412 %src.step = getelementptr inbounds i8, ptr %src, i16 %step 413 %cmp.step.start = icmp ult ptr %src.step, %lower 414 %cmp.step.end = icmp uge ptr %src.step, %upper 415 %or.check = or i1 %cmp.step.start, %cmp.step.end 416 br i1 %or.check, label %trap.bb, label %exit 417 418exit: 419 ret i4 3 420} 421 422define i4 @ptr_N_could_be_negative(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) { 423; CHECK-LABEL: @ptr_N_could_be_negative( 424; CHECK-NEXT: entry: 425; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] 426; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 427; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 428; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 429; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] 430; CHECK: trap.bb: 431; CHECK-NEXT: ret i4 2 432; CHECK: step.check: 433; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i8 [[STEP:%.*]], [[N]] 434; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]] 435; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 436; CHECK: ptr.check: 437; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[STEP]] 438; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] 439; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]] 440; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] 441; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 442; CHECK: exit: 443; CHECK-NEXT: ret i4 3 444; 445entry: 446 %src.end = getelementptr inbounds i8, ptr %src, i8 %N 447 %cmp.src.start = icmp ult ptr %src, %lower 448 %cmp.src.end = icmp uge ptr %src.end, %upper 449 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 450 br i1 %or.precond.0, label %trap.bb, label %step.check 451 452trap.bb: 453 ret i4 2 454 455step.check: 456 %step.pos = icmp uge i8 %step, 0 457 %step.ult.N = icmp ult i8 %step, %N 458 %and.step = and i1 %step.pos, %step.ult.N 459 br i1 %and.step, label %ptr.check, label %exit 460 461ptr.check: 462 %src.step = getelementptr inbounds i8, ptr %src, i8 %step 463 %cmp.step.start = icmp ult ptr %src.step, %lower 464 %cmp.step.end = icmp uge ptr %src.step, %upper 465 %or.check = or i1 %cmp.step.start, %cmp.step.end 466 br i1 %or.check, label %trap.bb, label %exit 467 468exit: 469 ret i4 3 470} 471 472define i4 @ptr_src_uge_end(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) { 473; CHECK-LABEL: @ptr_src_uge_end( 474; CHECK-NEXT: entry: 475; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] 476; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 477; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 478; CHECK-NEXT: [[CMP_OVERFLOW:%.*]] = icmp ugt ptr [[SRC]], [[SRC_END]] 479; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 480; CHECK-NEXT: [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]] 481; CHECK-NEXT: br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] 482; CHECK: trap.bb: 483; CHECK-NEXT: ret i4 2 484; CHECK: step.check: 485; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i8 [[STEP:%.*]], [[N]] 486; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]] 487; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 488; CHECK: ptr.check: 489; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[STEP]] 490; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] 491; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]] 492; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] 493; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 494; CHECK: exit: 495; CHECK-NEXT: ret i4 3 496; 497entry: 498 %src.end = getelementptr inbounds i8, ptr %src, i8 %N 499 %cmp.src.start = icmp ult ptr %src, %lower 500 %cmp.src.end = icmp uge ptr %src.end, %upper 501 %cmp.overflow = icmp ugt ptr %src, %src.end 502 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 503 %or.precond.1 = or i1 %or.precond.0, %cmp.overflow 504 br i1 %or.precond.1, label %trap.bb, label %step.check 505 506trap.bb: 507 ret i4 2 508 509step.check: 510 %step.pos = icmp uge i8 %step, 0 511 %step.ult.N = icmp ult i8 %step, %N 512 %and.step = and i1 %step.pos, %step.ult.N 513 br i1 %and.step, label %ptr.check, label %exit 514 515ptr.check: 516 %src.step = getelementptr inbounds i8, ptr %src, i8 %step 517 %cmp.step.start = icmp ult ptr %src.step, %lower 518 %cmp.step.end = icmp uge ptr %src.step, %upper 519 %or.check = or i1 %cmp.step.start, %cmp.step.end 520 br i1 %or.check, label %trap.bb, label %exit 521 522exit: 523 ret i4 3 524} 525 526; N might be negative, meaning %src.end could be < %src! Cannot remove checks! 527define i4 @ptr_N_unsigned_positive(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { 528; CHECK-LABEL: @ptr_N_unsigned_positive( 529; CHECK-NEXT: entry: 530; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] 531; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 532; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 533; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 534; CHECK-NEXT: [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], false 535; CHECK-NEXT: br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] 536; CHECK: trap.bb: 537; CHECK-NEXT: ret i4 2 538; CHECK: step.check: 539; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]] 540; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]] 541; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 542; CHECK: ptr.check: 543; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]] 544; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] 545; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]] 546; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] 547; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 548; CHECK: exit: 549; CHECK-NEXT: ret i4 3 550; 551entry: 552 %src.end = getelementptr inbounds i8, ptr %src, i16 %N 553 %cmp.src.start = icmp ult ptr %src, %lower 554 %cmp.src.end = icmp uge ptr %src.end, %upper 555 %N.neg = icmp ult i16 %N, 0 556 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 557 %or.precond.1 = or i1 %or.precond.0, %N.neg 558 br i1 %or.precond.1, label %trap.bb, label %step.check 559 560trap.bb: 561 ret i4 2 562 563step.check: 564 %step.pos = icmp uge i16 %step, 0 565 %step.ult.N = icmp ult i16 %step, %N 566 %and.step = and i1 %step.pos, %step.ult.N 567 br i1 %and.step, label %ptr.check, label %exit 568 569ptr.check: 570 %src.step = getelementptr inbounds i8, ptr %src, i16 %step 571 %cmp.step.start = icmp ult ptr %src.step, %lower 572 %cmp.step.end = icmp uge ptr %src.step, %upper 573 %or.check = or i1 %cmp.step.start, %cmp.step.end 574 br i1 %or.check, label %trap.bb, label %exit 575 576exit: 577 ret i4 3 578} 579 580define i4 @ptr_N_signed_positive_assume(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { 581; CHECK-LABEL: @ptr_N_signed_positive_assume( 582; CHECK-NEXT: entry: 583; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] 584; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] 585; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] 586; CHECK-NEXT: [[N_NEG:%.*]] = icmp slt i16 [[N]], 0 587; CHECK-NEXT: call void @llvm.assume(i1 [[N_NEG]]) 588; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] 589; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] 590; CHECK: trap.bb: 591; CHECK-NEXT: ret i4 2 592; CHECK: step.check: 593; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]] 594; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]] 595; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] 596; CHECK: ptr.check: 597; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]] 598; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] 599; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]] 600; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] 601; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] 602; CHECK: exit: 603; CHECK-NEXT: ret i4 3 604; 605entry: 606 %src.end = getelementptr inbounds i8, ptr %src, i16 %N 607 %cmp.src.start = icmp ult ptr %src, %lower 608 %cmp.src.end = icmp uge ptr %src.end, %upper 609 %N.neg = icmp slt i16 %N, 0 610 call void @llvm.assume(i1 %N.neg) 611 %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end 612 br i1 %or.precond.0, label %trap.bb, label %step.check 613 614trap.bb: 615 ret i4 2 616 617step.check: 618 %step.pos = icmp uge i16 %step, 0 619 %step.ult.N = icmp ult i16 %step, %N 620 %and.step = and i1 %step.pos, %step.ult.N 621 br i1 %and.step, label %ptr.check, label %exit 622 623ptr.check: 624 %src.step = getelementptr inbounds i8, ptr %src, i16 %step 625 %cmp.step.start = icmp ult ptr %src.step, %lower 626 %cmp.step.end = icmp uge ptr %src.step, %upper 627 %or.check = or i1 %cmp.step.start, %cmp.step.end 628 br i1 %or.check, label %trap.bb, label %exit 629 630exit: 631 ret i4 3 632} 633 634define i1 @test_nusw(ptr %p, i32 %x, i32 %y) { 635; CHECK-LABEL: @test_nusw( 636; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64 637; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64 638; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]] 639; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) 640; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]] 641; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]] 642; CHECK-NEXT: ret i1 true 643; 644 %x.ext = zext i32 %x to i64 645 %y.ext = zext i32 %y to i64 646 %cmp1 = icmp ugt i64 %x.ext, %y.ext 647 call void @llvm.assume(i1 %cmp1) 648 %gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext 649 %gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext 650 %cmp2 = icmp ugt ptr %gep.x, %gep.y 651 ret i1 %cmp2 652} 653 654define i1 @test_nusw_nested(ptr %p, i32 %x, i32 %y) { 655; CHECK-LABEL: @test_nusw_nested( 656; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64 657; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64 658; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]] 659; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) 660; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]] 661; CHECK-NEXT: [[GEP_X1:%.*]] = getelementptr nusw i8, ptr [[GEP_X]], i64 1 662; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]] 663; CHECK-NEXT: ret i1 true 664; 665 %x.ext = zext i32 %x to i64 666 %y.ext = zext i32 %y to i64 667 %cmp1 = icmp ugt i64 %x.ext, %y.ext 668 call void @llvm.assume(i1 %cmp1) 669 %gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext 670 %gep.x1 = getelementptr nusw i8, ptr %gep.x, i64 1 671 %gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext 672 %cmp2 = icmp ugt ptr %gep.x1, %gep.y 673 ret i1 %cmp2 674} 675 676define i1 @test_missing_nusw(ptr %p, i32 %x, i32 %y) { 677; CHECK-LABEL: @test_missing_nusw( 678; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64 679; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64 680; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]] 681; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) 682; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]] 683; CHECK-NEXT: [[GEP_X1:%.*]] = getelementptr i8, ptr [[GEP_X]], i64 1 684; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]] 685; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt ptr [[GEP_X1]], [[GEP_Y]] 686; CHECK-NEXT: ret i1 [[CMP2]] 687; 688 %x.ext = zext i32 %x to i64 689 %y.ext = zext i32 %y to i64 690 %cmp1 = icmp ugt i64 %x.ext, %y.ext 691 call void @llvm.assume(i1 %cmp1) 692 %gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext 693 %gep.x1 = getelementptr i8, ptr %gep.x, i64 1 694 %gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext 695 %cmp2 = icmp ugt ptr %gep.x1, %gep.y 696 ret i1 %cmp2 697} 698 699define i1 @test_nuw(ptr %p, i64 %x, i64 %y) { 700; CHECK-LABEL: @test_nuw( 701; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 702; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) 703; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[X]] 704; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]] 705; CHECK-NEXT: ret i1 true 706; 707 %cmp1 = icmp ugt i64 %x, %y 708 call void @llvm.assume(i1 %cmp1) 709 %gep.x = getelementptr nuw i8, ptr %p, i64 %x 710 %gep.y = getelementptr nuw i8, ptr %p, i64 %y 711 %cmp2 = icmp ugt ptr %gep.x, %gep.y 712 ret i1 %cmp2 713} 714 715define i1 @test_nuw_nested(ptr %p, i64 %x, i64 %y) { 716; CHECK-LABEL: @test_nuw_nested( 717; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 718; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) 719; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[X]] 720; CHECK-NEXT: [[GEP_X1:%.*]] = getelementptr nuw i8, ptr [[GEP_X]], i64 1 721; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]] 722; CHECK-NEXT: ret i1 true 723; 724 %cmp1 = icmp ugt i64 %x, %y 725 call void @llvm.assume(i1 %cmp1) 726 %gep.x = getelementptr nuw i8, ptr %p, i64 %x 727 %gep.x1 = getelementptr nuw i8, ptr %gep.x, i64 1 728 %gep.y = getelementptr nuw i8, ptr %p, i64 %y 729 %cmp2 = icmp ugt ptr %gep.x1, %gep.y 730 ret i1 %cmp2 731} 732 733define i1 @test_nuw_nested_missing_nuw(ptr %p, i64 %x, i64 %y) { 734; CHECK-LABEL: @test_nuw_nested_missing_nuw( 735; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 736; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) 737; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[X]] 738; CHECK-NEXT: [[GEP_X1:%.*]] = getelementptr nuw i8, ptr [[GEP_X]], i64 1 739; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]] 740; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt ptr [[GEP_X1]], [[GEP_Y]] 741; CHECK-NEXT: ret i1 [[CMP2]] 742; 743 %cmp1 = icmp ugt i64 %x, %y 744 call void @llvm.assume(i1 %cmp1) 745 %gep.x = getelementptr i8, ptr %p, i64 %x 746 %gep.x1 = getelementptr nuw i8, ptr %gep.x, i64 1 747 %gep.y = getelementptr nuw i8, ptr %p, i64 %y 748 %cmp2 = icmp ugt ptr %gep.x1, %gep.y 749 ret i1 %cmp2 750} 751 752define i1 @test_nuw_incorrect_precondition(ptr %p, i64 %x, i64 %y) { 753; CHECK-LABEL: @test_nuw_incorrect_precondition( 754; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i64 [[X:%.*]], [[Y:%.*]] 755; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) 756; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[X]] 757; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]] 758; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt ptr [[GEP_X]], [[GEP_Y]] 759; CHECK-NEXT: ret i1 [[CMP2]] 760; 761 %cmp1 = icmp uge i64 %x, %y 762 call void @llvm.assume(i1 %cmp1) 763 %gep.x = getelementptr nuw i8, ptr %p, i64 %x 764 %gep.y = getelementptr nuw i8, ptr %p, i64 %y 765 %cmp2 = icmp ugt ptr %gep.x, %gep.y 766 ret i1 %cmp2 767} 768