| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s |
| |
| declare void @llvm.assume(i1 noundef) #0 |
| |
| define i1 @gep_constant_positive_index(ptr %dst, ptr %lower, ptr %upper) { |
| ; CHECK-LABEL: @gep_constant_positive_index( |
| ; CHECK-NEXT: [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 4 |
| ; CHECK-NEXT: [[PRE_DST_LOWER:%.*]] = icmp sge ptr [[DST]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[PRE_DST_UPPER:%.*]] = icmp slt ptr [[DST_ADD_4]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[AND:%.*]] = and i1 [[PRE_DST_LOWER]], [[PRE_DST_UPPER]] |
| ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[CMP_DST_UPPER:%.*]] = icmp slt ptr [[DST]], [[UPPER]] |
| ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[CMP_DST_UPPER]] |
| ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3 |
| ; CHECK-NEXT: [[CMP_DST_ADD_3_LOWER:%.*]] = icmp sge ptr [[DST_ADD_3]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_DST_ADD_3_UPPER:%.*]] = icmp slt ptr [[DST_ADD_3]], [[UPPER]] |
| ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_DST_ADD_3_LOWER]] |
| ; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], [[CMP_DST_ADD_3_UPPER]] |
| ; CHECK-NEXT: [[CMP_DST_ADD_4_LOWER:%.*]] = icmp sge ptr [[DST_ADD_4]], [[LOWER]] |
| ; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[CMP_DST_ADD_4_LOWER]] |
| ; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true |
| ; CHECK-NEXT: [[DST_ADD_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 5 |
| ; CHECK-NEXT: [[CMP_DST_ADD_5_LOWER:%.*]] = icmp sge ptr [[DST_ADD_5]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_DST_ADD_5_UPPER:%.*]] = icmp slt ptr [[DST_ADD_5]], [[UPPER]] |
| ; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[CMP_DST_ADD_5_LOWER]] |
| ; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[CMP_DST_ADD_5_UPPER]] |
| ; CHECK-NEXT: ret i1 [[RES_7]] |
| ; CHECK: else: |
| ; CHECK-NEXT: ret i1 false |
| ; |
| %dst.add.4 = getelementptr inbounds i8, ptr %dst, i64 4 |
| %pre.dst.lower = icmp sge ptr %dst, %lower |
| %pre.dst.upper = icmp slt ptr %dst.add.4, %upper |
| %and = and i1 %pre.dst.lower, %pre.dst.upper |
| br i1 %and, label %then, label %else |
| |
| then: |
| %cmp.dst.lower = icmp sge ptr %dst, %lower |
| %cmp.dst.upper = icmp slt ptr %dst, %upper |
| %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper |
| %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3 |
| %cmp.dst.add.3.lower = icmp sge ptr %dst.add.3, %lower |
| %cmp.dst.add.3.upper = icmp slt ptr %dst.add.3, %upper |
| %res.2 = xor i1 %res.1, %cmp.dst.add.3.lower |
| %res.3 = xor i1 %res.2, %cmp.dst.add.3.upper |
| %cmp.dst.add.4.lower = icmp sge ptr %dst.add.4, %lower |
| %cmp.dst.add.4.upper = icmp slt ptr %dst.add.4, %upper |
| %res.4 = xor i1 %res.3, %cmp.dst.add.4.lower |
| %res.5 = xor i1 %res.4, %cmp.dst.add.4.upper |
| %dst.add.5 = getelementptr inbounds i8, ptr %dst, i64 5 |
| %cmp.dst.add.5.lower = icmp sge ptr %dst.add.5, %lower |
| %cmp.dst.add.5.upper = icmp slt ptr %dst.add.5, %upper |
| %res.6 = xor i1 %res.5, %cmp.dst.add.5.lower |
| %res.7 = xor i1 %res.6, %cmp.dst.add.5.upper |
| ret i1 %res.7 |
| |
| else: |
| ret i1 false |
| } |
| |
| define i1 @gep_constant_negative_index(ptr %dst, ptr %lower, ptr %upper) { |
| ; CHECK-LABEL: @gep_constant_negative_index( |
| ; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 -4 |
| ; CHECK-NEXT: [[PRE_DST_LOWER:%.*]] = icmp sge ptr [[DST]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[PRE_DST_UPPER:%.*]] = icmp slt ptr [[DST_SUB_4]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[AND:%.*]] = and i1 [[PRE_DST_LOWER]], [[PRE_DST_UPPER]] |
| ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[CMP_DST_UPPER:%.*]] = icmp slt ptr [[DST]], [[UPPER]] |
| ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[CMP_DST_UPPER]] |
| ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -3 |
| ; CHECK-NEXT: [[CMP_DST_SUB_3_LOWER:%.*]] = icmp sge ptr [[DST_SUB_3]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_DST_SUB_3_UPPER:%.*]] = icmp slt ptr [[DST_SUB_3]], [[UPPER]] |
| ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_DST_SUB_3_LOWER]] |
| ; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], [[CMP_DST_SUB_3_UPPER]] |
| ; CHECK-NEXT: [[CMP_DST_SUB_4_LOWER:%.*]] = icmp sge ptr [[DST_SUB_4]], [[LOWER]] |
| ; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[CMP_DST_SUB_4_LOWER]] |
| ; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true |
| ; CHECK-NEXT: [[DST_SUB_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -5 |
| ; CHECK-NEXT: [[CMP_DST_SUB_5_LOWER:%.*]] = icmp sge ptr [[DST_SUB_5]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_DST_SUB_5_UPPER:%.*]] = icmp slt ptr [[DST_SUB_5]], [[UPPER]] |
| ; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[CMP_DST_SUB_5_LOWER]] |
| ; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[CMP_DST_SUB_5_UPPER]] |
| ; CHECK-NEXT: ret i1 [[RES_7]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[ELSE_CMP_DST_LOWER:%.*]] = icmp sge ptr [[DST]], [[LOWER]] |
| ; CHECK-NEXT: [[ELSE_CMP_DST_UPPER:%.*]] = icmp slt ptr [[DST]], [[UPPER]] |
| ; CHECK-NEXT: [[ELSE_RES_1:%.*]] = xor i1 [[ELSE_CMP_DST_LOWER]], [[ELSE_CMP_DST_UPPER]] |
| ; CHECK-NEXT: [[ELSE_DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -3 |
| ; CHECK-NEXT: [[ELSE_CMP_DST_SUB_3_LOWER:%.*]] = icmp sge ptr [[ELSE_DST_SUB_3]], [[LOWER]] |
| ; CHECK-NEXT: [[ELSE_CMP_DST_SUB_3_UPPER:%.*]] = icmp slt ptr [[ELSE_DST_SUB_3]], [[UPPER]] |
| ; CHECK-NEXT: [[ELSE_RES_2:%.*]] = xor i1 [[ELSE_RES_1]], [[ELSE_CMP_DST_SUB_3_LOWER]] |
| ; CHECK-NEXT: [[ELSE_RES_3:%.*]] = xor i1 [[ELSE_RES_2]], [[ELSE_CMP_DST_SUB_3_UPPER]] |
| ; CHECK-NEXT: [[ELSE_CMP_DST_SUB_4_LOWER:%.*]] = icmp sge ptr [[DST_SUB_4]], [[LOWER]] |
| ; CHECK-NEXT: [[ELSE_CMP_DST_SUB_4_UPPER:%.*]] = icmp slt ptr [[DST_SUB_4]], [[UPPER]] |
| ; CHECK-NEXT: [[ELSE_RES_4:%.*]] = xor i1 [[ELSE_RES_3]], [[ELSE_CMP_DST_SUB_4_LOWER]] |
| ; CHECK-NEXT: [[ELSE_RES_5:%.*]] = xor i1 [[ELSE_RES_4]], [[ELSE_CMP_DST_SUB_4_UPPER]] |
| ; CHECK-NEXT: [[ELSE_DST_SUB_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -5 |
| ; CHECK-NEXT: [[ELSE_CMP_DST_SUB_5_LOWER:%.*]] = icmp sge ptr [[ELSE_DST_SUB_5]], [[LOWER]] |
| ; CHECK-NEXT: [[ELSE_CMP_DST_SUB_5_UPPER:%.*]] = icmp slt ptr [[ELSE_DST_SUB_5]], [[UPPER]] |
| ; CHECK-NEXT: [[ELSE_RES_6:%.*]] = xor i1 [[ELSE_RES_5]], [[ELSE_CMP_DST_SUB_5_LOWER]] |
| ; CHECK-NEXT: [[ELSE_RES_7:%.*]] = xor i1 [[ELSE_RES_6]], [[ELSE_CMP_DST_SUB_5_UPPER]] |
| ; CHECK-NEXT: ret i1 [[ELSE_RES_7]] |
| ; |
| %dst.sub.4 = getelementptr inbounds i8, ptr %dst, i64 -4 |
| %pre.dst.lower = icmp sge ptr %dst, %lower |
| %pre.dst.upper = icmp slt ptr %dst.sub.4, %upper |
| %and = and i1 %pre.dst.lower, %pre.dst.upper |
| br i1 %and, label %then, label %else |
| |
| then: |
| %cmp.dst.lower = icmp sge ptr %dst, %lower |
| %cmp.dst.upper = icmp slt ptr %dst, %upper |
| %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper |
| %dst.sub.3 = getelementptr inbounds i8, ptr %dst, i64 -3 |
| %cmp.dst.sub.3.lower = icmp sge ptr %dst.sub.3, %lower |
| %cmp.dst.sub.3.upper = icmp slt ptr %dst.sub.3, %upper |
| %res.2 = xor i1 %res.1, %cmp.dst.sub.3.lower |
| %res.3 = xor i1 %res.2, %cmp.dst.sub.3.upper |
| %cmp.dst.sub.4.lower = icmp sge ptr %dst.sub.4, %lower |
| %cmp.dst.sub.4.upper = icmp slt ptr %dst.sub.4, %upper |
| %res.4 = xor i1 %res.3, %cmp.dst.sub.4.lower |
| %res.5 = xor i1 %res.4, %cmp.dst.sub.4.upper |
| %dst.sub.5 = getelementptr inbounds i8, ptr %dst, i64 -5 |
| %cmp.dst.sub.5.lower = icmp sge ptr %dst.sub.5, %lower |
| %cmp.dst.sub.5.upper = icmp slt ptr %dst.sub.5, %upper |
| %res.6 = xor i1 %res.5, %cmp.dst.sub.5.lower |
| %res.7 = xor i1 %res.6, %cmp.dst.sub.5.upper |
| ret i1 %res.7 |
| |
| else: |
| %else.cmp.dst.lower = icmp sge ptr %dst, %lower |
| %else.cmp.dst.upper = icmp slt ptr %dst, %upper |
| %else.res.1 = xor i1 %else.cmp.dst.lower, %else.cmp.dst.upper |
| %else.dst.sub.3 = getelementptr inbounds i8, ptr %dst, i64 -3 |
| %else.cmp.dst.sub.3.lower = icmp sge ptr %else.dst.sub.3, %lower |
| %else.cmp.dst.sub.3.upper = icmp slt ptr %else.dst.sub.3, %upper |
| %else.res.2 = xor i1 %else.res.1, %else.cmp.dst.sub.3.lower |
| %else.res.3 = xor i1 %else.res.2, %else.cmp.dst.sub.3.upper |
| %else.cmp.dst.sub.4.lower = icmp sge ptr %dst.sub.4, %lower |
| %else.cmp.dst.sub.4.upper = icmp slt ptr %dst.sub.4, %upper |
| %else.res.4 = xor i1 %else.res.3, %else.cmp.dst.sub.4.lower |
| %else.res.5 = xor i1 %else.res.4, %else.cmp.dst.sub.4.upper |
| %else.dst.sub.5 = getelementptr inbounds i8, ptr %dst, i64 -5 |
| %else.cmp.dst.sub.5.lower = icmp sge ptr %else.dst.sub.5, %lower |
| %else.cmp.dst.sub.5.upper = icmp slt ptr %else.dst.sub.5, %upper |
| %else.res.6 = xor i1 %else.res.5, %else.cmp.dst.sub.5.lower |
| %else.res.7 = xor i1 %else.res.6, %else.cmp.dst.sub.5.upper |
| ret i1 %else.res.7 |
| } |
| |
| define i4 @ptr_N_signed_positive_explicit_check_constant_step(ptr %src, ptr %lower, ptr %upper, i16 %N) { |
| ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] |
| ; CHECK: entry.1: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i16 1, [[N]] |
| ; CHECK-NEXT: br i1 [[STEP_SLT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1 |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %N.pos = icmp sge i16 %N, 0 |
| br i1 %N.pos, label %entry.1, label %trap.bb |
| |
| entry.1: |
| %src.end = getelementptr inbounds i8, ptr %src, i16 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| br i1 %or.precond.0, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.slt.N = icmp slt i16 1, %N |
| br i1 %step.slt.N, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i16 1 |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| ; Same as ptr_N_signed_positive_explicit_check_constant_step, but without inbounds. |
| define i4 @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(ptr %src, ptr %lower, ptr %upper, i16 %N) { |
| ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] |
| ; CHECK: entry.1: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i16 [[N]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i16 1, [[N]] |
| ; CHECK-NEXT: br i1 [[STEP_SLT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr i8, ptr [[SRC]], i16 1 |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %N.pos = icmp sge i16 %N, 0 |
| br i1 %N.pos, label %entry.1, label %trap.bb |
| |
| entry.1: |
| %src.end = getelementptr i8, ptr %src, i16 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| br i1 %or.precond.0, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.slt.N = icmp slt i16 1, %N |
| br i1 %step.slt.N, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr i8, ptr %src, i16 1 |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| define i4 @ptr_N_and_step_signed_positive_explicit_check_constant_step(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @ptr_N_and_step_signed_positive_explicit_check_constant_step( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0 |
| ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0 |
| ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[N_POS]], [[STEP_POS]] |
| ; CHECK-NEXT: br i1 [[AND_1]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] |
| ; CHECK: entry.1: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i16 [[STEP]], [[N]] |
| ; CHECK-NEXT: [[AND_2:%.*]] = and i1 true, [[STEP_SLT_N]] |
| ; CHECK-NEXT: br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1 |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %N.pos = icmp sge i16 %N, 0 |
| %step.pos = icmp sge i16 %step, 0 |
| %and.1 = and i1 %N.pos, %step.pos |
| br i1 %and.1, label %entry.1, label %trap.bb |
| |
| entry.1: |
| %src.end = getelementptr inbounds i8, ptr %src, i16 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| br i1 %or.precond.0, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.sge.0 = icmp sge i16 %step, 0 |
| %step.slt.N = icmp slt i16 %step, %N |
| %and.2 = and i1 %step.sge.0, %step.slt.N |
| br i1 %and.2, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i16 1 |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| define i4 @ptr_N_and_step_signed_positive_unsigned_checks_only(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @ptr_N_and_step_signed_positive_unsigned_checks_only( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] |
| ; CHECK-NEXT: [[NO_OVERFLOW:%.*]] = icmp sle ptr [[SRC]], [[SRC_END]] |
| ; CHECK-NEXT: br i1 [[NO_OVERFLOW]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]] |
| ; CHECK: entry.1: |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_SGE_0:%.*]] = icmp sge i16 [[STEP:%.*]], 0 |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i16 [[STEP]], [[N]] |
| ; CHECK-NEXT: [[AND_2:%.*]] = and i1 [[STEP_SGE_0]], [[STEP_SLT_N]] |
| ; CHECK-NEXT: br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1 |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %src.end = getelementptr inbounds i8, ptr %src, i16 %N |
| %no.overflow = icmp sle ptr %src, %src.end |
| br i1 %no.overflow, label %entry.1, label %trap.bb |
| |
| entry.1: |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| br i1 %or.precond.0, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.sge.0 = icmp sge i16 %step, 0 |
| %step.slt.N = icmp slt i16 %step, %N |
| %and.2 = and i1 %step.sge.0, %step.slt.N |
| br i1 %and.2, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i16 1 |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| define i4 @ptr_N_signed_positive(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @ptr_N_signed_positive( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[N_NEG:%.*]] = icmp slt i16 [[N]], 0 |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0 |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i16 [[STEP]], [[N]] |
| ; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_SLT_N]] |
| ; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %src.end = getelementptr inbounds i8, ptr %src, i16 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %N.neg = icmp slt i16 %N, 0 |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| %or.precond.1 = or i1 %or.precond.0, %N.neg |
| br i1 %or.precond.1, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.pos = icmp sge i16 %step, 0 |
| %step.slt.N = icmp slt i16 %step, %N |
| %and.step = and i1 %step.pos, %step.slt.N |
| br i1 %and.step, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i16 %step |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| define i4 @ptr_N_could_be_negative(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) { |
| ; CHECK-LABEL: @ptr_N_could_be_negative( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i8 [[STEP:%.*]], 0 |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i8 [[STEP]], [[N]] |
| ; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_SLT_N]] |
| ; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[STEP]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %src.end = getelementptr inbounds i8, ptr %src, i8 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| br i1 %or.precond.0, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.pos = icmp sge i8 %step, 0 |
| %step.slt.N = icmp slt i8 %step, %N |
| %and.step = and i1 %step.pos, %step.slt.N |
| br i1 %and.step, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i8 %step |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| define i4 @ptr_src_sge_end(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) { |
| ; CHECK-LABEL: @ptr_src_sge_end( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[CMP_OVERFLOW:%.*]] = icmp sgt ptr [[SRC]], [[SRC_END]] |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i8 [[STEP:%.*]], 0 |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i8 [[STEP]], [[N]] |
| ; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_SLT_N]] |
| ; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[STEP]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %src.end = getelementptr inbounds i8, ptr %src, i8 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %cmp.overflow = icmp sgt ptr %src, %src.end |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| %or.precond.1 = or i1 %or.precond.0, %cmp.overflow |
| br i1 %or.precond.1, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.pos = icmp sge i8 %step, 0 |
| %step.slt.N = icmp slt i8 %step, %N |
| %and.step = and i1 %step.pos, %step.slt.N |
| br i1 %and.step, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i8 %step |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| ; N might be negative, meaning %src.end could be < %src! Cannot remove checks! |
| define i4 @ptr_N_unsigned_positive(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @ptr_N_unsigned_positive( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[N_NEG:%.*]] = icmp slt i16 [[N]], 0 |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0 |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i16 [[STEP]], [[N]] |
| ; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_SLT_N]] |
| ; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %src.end = getelementptr inbounds i8, ptr %src, i16 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %N.neg = icmp slt i16 %N, 0 |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| %or.precond.1 = or i1 %or.precond.0, %N.neg |
| br i1 %or.precond.1, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.pos = icmp sge i16 %step, 0 |
| %step.slt.N = icmp slt i16 %step, %N |
| %and.step = and i1 %step.pos, %step.slt.N |
| br i1 %and.step, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i16 %step |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |
| |
| define i4 @ptr_N_signed_positive_assume(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @ptr_N_signed_positive_assume( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[N_NEG:%.*]] = icmp slt i16 [[N]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[N_NEG]]) |
| ; CHECK-NEXT: [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]] |
| ; CHECK-NEXT: br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0 |
| ; CHECK-NEXT: [[STEP_SLT_N:%.*]] = icmp slt i16 [[STEP]], [[N]] |
| ; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 [[STEP_POS]], false |
| ; CHECK-NEXT: br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]] |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %src.end = getelementptr inbounds i8, ptr %src, i16 %N |
| %cmp.src.start = icmp slt ptr %src, %lower |
| %cmp.src.end = icmp sge ptr %src.end, %upper |
| %N.neg = icmp slt i16 %N, 0 |
| call void @llvm.assume(i1 %N.neg) |
| %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end |
| br i1 %or.precond.0, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %step.pos = icmp sge i16 %step, 0 |
| %step.slt.N = icmp slt i16 %step, %N |
| %and.step = and i1 %step.pos, %step.slt.N |
| br i1 %and.step, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i16 %step |
| %cmp.step.start = icmp slt ptr %src.step, %lower |
| %cmp.step.end = icmp sge ptr %src.step, %upper |
| %or.check = or i1 %cmp.step.start, %cmp.step.end |
| br i1 %or.check, label %trap.bb, label %exit |
| |
| exit: |
| ret i4 3 |
| } |