| ; 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 @n_unknown(ptr %dst, i32 %n, i32 %i) { |
| ; CHECK-LABEL: @n_unknown( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SUB:%.*]] = add i32 [[N:%.*]], -1 |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[SUB]] to i64 |
| ; CHECK-NEXT: [[PTR_N_SUB_1:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IDXPROM]] |
| ; CHECK-NEXT: [[CMP_PTR_DST:%.*]] = icmp uge ptr [[PTR_N_SUB_1]], [[DST]] |
| ; CHECK-NEXT: br i1 [[CMP_PTR_DST]], label [[PRE_BB_2:%.*]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i1 false |
| ; CHECK: pre.bb.2: |
| ; CHECK-NEXT: br i1 true, label [[TGT_BB:%.*]], label [[EXIT]] |
| ; CHECK: tgt.bb: |
| ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[I:%.*]], [[N]] |
| ; CHECK-NEXT: ret i1 [[CMP1]] |
| ; |
| entry: |
| %sub = add i32 %n, -1 |
| %idxprom = zext i32 %sub to i64 |
| %ptr.n.sub.1 = getelementptr i32, ptr %dst, i64 %idxprom |
| %cmp.ptr.dst = icmp uge ptr %ptr.n.sub.1, %dst |
| br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit |
| |
| exit: |
| ret i1 false |
| |
| pre.bb.2: |
| %pre.2 = icmp uge i32 %i, 0 |
| br i1 %pre.2, label %tgt.bb, label %exit |
| |
| tgt.bb: |
| %cmp1 = icmp ult i32 %i, %n |
| ret i1 %cmp1 |
| } |
| |
| define i1 @n_known_zero_due_to_nuw(ptr %dst, i32 %n, i32 %i) { |
| ; CHECK-LABEL: @n_known_zero_due_to_nuw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SUB:%.*]] = add i32 [[N:%.*]], -1 |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[SUB]] to i64 |
| ; CHECK-NEXT: [[PTR_N_SUB_1:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IDXPROM]] |
| ; CHECK-NEXT: [[CMP_PTR_DST:%.*]] = icmp uge ptr [[PTR_N_SUB_1]], [[DST]] |
| ; CHECK-NEXT: br i1 [[CMP_PTR_DST]], label [[PRE_BB_2:%.*]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i1 false |
| ; CHECK: pre.bb.2: |
| ; CHECK-NEXT: br i1 true, label [[TGT_BB:%.*]], label [[EXIT]] |
| ; CHECK: tgt.bb: |
| ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[I:%.*]], [[N]] |
| ; CHECK-NEXT: ret i1 [[CMP1]] |
| ; |
| entry: |
| %sub = add i32 %n, -1 |
| %idxprom = zext i32 %sub to i64 |
| %ptr.n.sub.1 = getelementptr i32, ptr %dst, i64 %idxprom |
| %cmp.ptr.dst = icmp uge ptr %ptr.n.sub.1, %dst |
| br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit |
| |
| exit: |
| ret i1 false |
| |
| pre.bb.2: |
| %pre.2 = icmp uge i32 %i, 0 |
| br i1 %pre.2, label %tgt.bb, label %exit |
| |
| tgt.bb: |
| %cmp1 = icmp ult i32 %i, %n |
| ret i1 %cmp1 |
| } |
| |
| define i4 @inc_ptr_N_could_be_negative(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) { |
| ; CHECK-LABEL: @inc_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 ult ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge 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: [[NEXT:%.*]] = add nuw nsw i8 [[STEP:%.*]], 2 |
| ; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i8 [[NEXT]], [[N]] |
| ; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_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 ult ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge 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 ult ptr %src, %lower |
| %cmp.src.end = icmp uge 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 uge i8 %step, 0 |
| %next = add nuw nsw i8 %step, 2 |
| %step.ult.N = icmp ult i8 %next, %N |
| %and.step = and i1 %step.pos, %step.ult.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 ult ptr %src.step, %lower |
| %cmp.step.end = icmp uge 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 @inc_ptr_src_uge_end(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @inc_ptr_src_uge_end( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]] |
| ; CHECK-NEXT: [[CMP_OVERFLOW:%.*]] = icmp ugt 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: [[NEXT:%.*]] = add nuw nsw i16 [[STEP:%.*]], 2 |
| ; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i16 [[NEXT]], [[N]] |
| ; CHECK-NEXT: [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_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 ult ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge 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 ult ptr %src, %lower |
| %cmp.src.end = icmp uge ptr %src.end, %upper |
| %cmp.overflow = icmp ugt 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 uge i16 %step, 0 |
| %next = add nuw nsw i16 %step, 2 |
| %step.ult.N = icmp ult i16 %next, %N |
| %and.step = and i1 %step.pos, %step.ult.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 ult ptr %src.step, %lower |
| %cmp.step.end = icmp uge 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 @inc_ptr_src_uge_end_no_nsw_add(ptr %src, ptr %lower, ptr %upper, i16 %idx, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @inc_ptr_src_uge_end_no_nsw_add( |
| ; CHECK-NEXT: entry.1: |
| ; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]] |
| ; CHECK: entry: |
| ; CHECK-NEXT: [[SRC_IDX:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[IDX]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC_IDX]], [[LOWER:%.*]] |
| ; CHECK-NEXT: br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[NEXT:%.*]] = add i16 [[IDX]], 2 |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[NEXT]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge 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.1: |
| %idx.pos = icmp sge i16 %idx, 0 |
| br i1 %idx.pos, label %entry, label %trap.bb |
| |
| entry: |
| %src.idx = getelementptr inbounds i8, ptr %src, i16 %idx |
| %cmp.src.start = icmp ult ptr %src.idx, %lower |
| br i1 %cmp.src.start, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %next = add i16 %idx, 2 |
| %src.step = getelementptr inbounds i8, ptr %src, i16 %next |
| %cmp.step.start = icmp ult ptr %src.step, %lower |
| %cmp.step.end = icmp uge 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 @inc_ptr_src_uge_end_no_nsw_add_sge_0(ptr %src, ptr %lower, ptr %upper, i16 %idx, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @inc_ptr_src_uge_end_no_nsw_add_sge_0( |
| ; CHECK-NEXT: entry.1: |
| ; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]] |
| ; CHECK: entry: |
| ; CHECK-NEXT: [[SRC_IDX:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[IDX]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC_IDX]], [[LOWER:%.*]] |
| ; CHECK-NEXT: br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]] |
| ; CHECK: trap.bb: |
| ; CHECK-NEXT: ret i4 2 |
| ; CHECK: step.check: |
| ; CHECK-NEXT: [[NEXT:%.*]] = add i16 [[IDX]], 2 |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[NEXT]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge 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.1: |
| %idx.pos = icmp sge i16 %idx, 0 |
| br i1 %idx.pos, label %entry, label %trap.bb |
| |
| entry: |
| %src.idx = getelementptr inbounds i8, ptr %src, i16 %idx |
| %cmp.src.start = icmp ult ptr %src.idx, %lower |
| br i1 %cmp.src.start, label %trap.bb, label %step.check |
| |
| trap.bb: |
| ret i4 2 |
| |
| step.check: |
| %next = add i16 %idx, 2 |
| %src.step = getelementptr inbounds i8, ptr %src, i16 %next |
| %cmp.step.start = icmp ult ptr %src.step, %lower |
| %cmp.step.end = icmp uge 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_step_zext_n_zext(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @ptr_N_step_zext_n_zext( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[N_ADD_1:%.*]] = add nuw nsw i16 [[N:%.*]], 1 |
| ; CHECK-NEXT: [[N_ADD_1_EXT:%.*]] = zext i16 [[N_ADD_1]] to i32 |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i32 [[N_ADD_1_EXT]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge 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_ADD_1:%.*]] = add nuw nsw i16 [[STEP:%.*]], 1 |
| ; CHECK-NEXT: [[STEP_ADD_1_EXT:%.*]] = zext i16 [[STEP_ADD_1]] to i32 |
| ; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i32 [[STEP_ADD_1_EXT]], [[N_ADD_1_EXT]] |
| ; CHECK-NEXT: br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i32 [[STEP_ADD_1_EXT]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], false |
| ; CHECK-NEXT: br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i4 3 |
| ; |
| entry: |
| %N.add.1 = add nuw nsw i16 %N, 1 |
| %N.add.1.ext = zext i16 %N.add.1 to i32 |
| %src.end = getelementptr inbounds i8, ptr %src, i32 %N.add.1.ext |
| %cmp.src.start = icmp ult ptr %src, %lower |
| %cmp.src.end = icmp uge 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.add.1 = add nuw nsw i16 %step, 1 |
| %step.add.1.ext = zext i16 %step.add.1 to i32 |
| %step.ult.N = icmp ult i32 %step.add.1.ext, %N.add.1.ext |
| br i1 %step.ult.N, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i32 %step.add.1.ext |
| %cmp.step.start = icmp ult ptr %src.step, %lower |
| %cmp.step.end = icmp uge 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_step_zext_n_zext_out_of_bounds(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) { |
| ; CHECK-LABEL: @ptr_N_step_zext_n_zext_out_of_bounds( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[N_ADD_2:%.*]] = add nuw nsw i16 [[N:%.*]], 2 |
| ; CHECK-NEXT: [[N_ADD_2_EXT:%.*]] = zext i16 [[N_ADD_2]] to i32 |
| ; CHECK-NEXT: [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i32 [[N_ADD_2_EXT]] |
| ; CHECK-NEXT: [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]] |
| ; CHECK-NEXT: [[CMP_SRC_END:%.*]] = icmp uge 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_ADD_2:%.*]] = add nuw nsw i16 [[STEP:%.*]], 2 |
| ; CHECK-NEXT: [[STEP_ADD_2_EXT:%.*]] = zext i16 [[STEP_ADD_2]] to i32 |
| ; CHECK-NEXT: [[STEP_EXT:%.*]] = zext i16 [[STEP]] to i32 |
| ; CHECK-NEXT: [[STEP_ULT_N:%.*]] = icmp ult i32 [[STEP_EXT]], [[N_ADD_2_EXT]] |
| ; CHECK-NEXT: br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]] |
| ; CHECK: ptr.check: |
| ; CHECK-NEXT: [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i32 [[STEP_ADD_2_EXT]] |
| ; CHECK-NEXT: [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]] |
| ; CHECK-NEXT: [[CMP_STEP_END:%.*]] = icmp uge 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.add.2 = add nuw nsw i16 %N, 2 |
| %N.add.2.ext = zext i16 %N.add.2 to i32 |
| %src.end = getelementptr inbounds i8, ptr %src, i32 %N.add.2.ext |
| %cmp.src.start = icmp ult ptr %src, %lower |
| %cmp.src.end = icmp uge 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.add.2 = add nuw nsw i16 %step, 2 |
| %step.add.2.ext = zext i16 %step.add.2 to i32 |
| %step.ext = zext i16 %step to i32 |
| %step.ult.N = icmp ult i32 %step.ext, %N.add.2.ext |
| br i1 %step.ult.N, label %ptr.check, label %exit |
| |
| ptr.check: |
| %src.step = getelementptr inbounds i8, ptr %src, i32 %step.add.2.ext |
| %cmp.step.start = icmp ult ptr %src.step, %lower |
| %cmp.step.end = icmp uge 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 i1 @gep_count_add_1_sge_known_ult_1(i32 %count, ptr %p) { |
| ; CHECK-LABEL: @gep_count_add_1_sge_known_ult_1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[SGE]]) |
| ; CHECK-NEXT: [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64 |
| ; CHECK-NEXT: [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]] |
| ; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[COUNT]], -1 |
| ; CHECK-NEXT: [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64 |
| ; CHECK-NEXT: [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]] |
| ; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[GEP_SUB]], [[GEP_COUNT]] |
| ; CHECK-NEXT: ret i1 [[C]] |
| ; |
| entry: |
| %sge = icmp sge i32 %count, 1 |
| call void @llvm.assume(i1 %sge) |
| %count.ext = zext i32 %count to i64 |
| %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext |
| %sub = add nsw i32 %count, -1 |
| %sub.ext = zext i32 %sub to i64 |
| %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext |
| %c = icmp ult ptr %gep.sub, %gep.count |
| ;%2 = icmp uge ptr %0, %p |
| ret i1 %c |
| } |
| |
| define i1 @gep_count_add_1_sge_known_uge_1(i32 %count, ptr %p) { |
| ; CHECK-LABEL: @gep_count_add_1_sge_known_uge_1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[SGE]]) |
| ; CHECK-NEXT: [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64 |
| ; CHECK-NEXT: [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]] |
| ; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[COUNT]], -1 |
| ; CHECK-NEXT: [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64 |
| ; CHECK-NEXT: [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]] |
| ; CHECK-NEXT: [[C:%.*]] = icmp uge ptr [[GEP_SUB]], [[P]] |
| ; CHECK-NEXT: ret i1 [[C]] |
| ; |
| entry: |
| %sge = icmp sge i32 %count, 1 |
| call void @llvm.assume(i1 %sge) |
| %count.ext = zext i32 %count to i64 |
| %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext |
| %sub = add nsw i32 %count, -1 |
| %sub.ext = zext i32 %sub to i64 |
| %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext |
| %c = icmp uge ptr %gep.sub, %p |
| ret i1 %c |
| } |
| |
| define i1 @gep_count_add_2_sge_not_known_ult_1(i32 %count, ptr %p) { |
| ; CHECK-LABEL: @gep_count_add_2_sge_not_known_ult_1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[SGE]]) |
| ; CHECK-NEXT: [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64 |
| ; CHECK-NEXT: [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]] |
| ; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[COUNT]], -2 |
| ; CHECK-NEXT: [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64 |
| ; CHECK-NEXT: [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]] |
| ; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[GEP_SUB]], [[GEP_COUNT]] |
| ; CHECK-NEXT: ret i1 [[C]] |
| ; |
| entry: |
| %sge = icmp sge i32 %count, 1 |
| call void @llvm.assume(i1 %sge) |
| %count.ext = zext i32 %count to i64 |
| %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext |
| %sub = add nsw i32 %count, -2 |
| %sub.ext = zext i32 %sub to i64 |
| %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext |
| %c = icmp ult ptr %gep.sub, %gep.count |
| ret i1 %c |
| } |
| |
| define i1 @gep_count_add_2_sge_not_known_uge_1(i32 %count, ptr %p) { |
| ; CHECK-LABEL: @gep_count_add_2_sge_not_known_uge_1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[SGE]]) |
| ; CHECK-NEXT: [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64 |
| ; CHECK-NEXT: [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]] |
| ; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[COUNT]], -2 |
| ; CHECK-NEXT: [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64 |
| ; CHECK-NEXT: [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]] |
| ; CHECK-NEXT: [[C:%.*]] = icmp uge ptr [[GEP_SUB]], [[P]] |
| ; CHECK-NEXT: ret i1 [[C]] |
| ; |
| entry: |
| %sge = icmp sge i32 %count, 1 |
| call void @llvm.assume(i1 %sge) |
| %count.ext = zext i32 %count to i64 |
| %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext |
| %sub = add nsw i32 %count, -2 |
| %sub.ext = zext i32 %sub to i64 |
| %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext |
| %c = icmp uge ptr %gep.sub, %p |
| ret i1 %c |
| } |