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