; 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) define i1 @gep_sub_1_sge_inbounds(ptr %dst, ptr %lower) { ; CHECK-LABEL: @gep_sub_1_sge_inbounds( ; CHECK-NEXT: [[PRE:%.*]] = icmp sge ptr [[DST:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3 ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp sge ptr [[DST_SUB_1]], [[LOWER]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp sge ptr [[DST_SUB_3]], [[LOWER]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]] ; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -4 ; CHECK-NEXT: [[CMP_SUB_4:%.*]] = icmp sge ptr [[DST_SUB_4]], [[LOWER]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]] ; CHECK-NEXT: ret i1 [[RES_2]] ; %pre = icmp sge ptr %dst, %lower call void @llvm.assume(i1 %pre) %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3 %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.3, i64 -1 %cmp.sub.1 = icmp sge ptr %dst.sub.1, %lower %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3 %cmp.sub.3 = icmp sge ptr %dst.sub.3, %lower %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3 %dst.sub.4 = getelementptr inbounds i8, ptr %dst.add.3, i64 -4 %cmp.sub.4 = icmp sge ptr %dst.sub.4, %lower %res.2 = xor i1 %res.1, %cmp.sub.4 ret i1 %res.2 } define i1 @gep_sub_1_sge_only_inner_inbounds(ptr %dst, ptr %lower) { ; CHECK-LABEL: @gep_sub_1_sge_only_inner_inbounds( ; CHECK-NEXT: [[PRE:%.*]] = icmp sge ptr [[DST:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3 ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp sge ptr [[DST_SUB_1]], [[LOWER]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp sge ptr [[DST_SUB_3]], [[LOWER]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]] ; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -4 ; CHECK-NEXT: [[CMP_SUB_4:%.*]] = icmp sge ptr [[DST_SUB_4]], [[LOWER]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]] ; CHECK-NEXT: ret i1 [[RES_2]] ; %pre = icmp sge ptr %dst, %lower call void @llvm.assume(i1 %pre) %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3 %dst.sub.1 = getelementptr i8, ptr %dst.add.3, i64 -1 %cmp.sub.1 = icmp sge ptr %dst.sub.1, %lower %dst.sub.3 = getelementptr i8, ptr %dst.add.3, i64 -3 %cmp.sub.3 = icmp sge ptr %dst.sub.3, %lower %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3 %dst.sub.4 = getelementptr i8, ptr %dst.add.3, i64 -4 %cmp.sub.4 = icmp sge ptr %dst.sub.4, %lower %res.2 = xor i1 %res.1, %cmp.sub.4 ret i1 %res.2 } define i1 @gep_sub_1_sge_only_outer_inbounds(ptr %dst, ptr %lower) { ; CHECK-LABEL: @gep_sub_1_sge_only_outer_inbounds( ; CHECK-NEXT: [[PRE:%.*]] = icmp sge ptr [[DST:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr i8, ptr [[DST]], i64 3 ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp sge ptr [[DST_SUB_1]], [[LOWER]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp sge ptr [[DST_SUB_3]], [[LOWER]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]] ; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -4 ; CHECK-NEXT: [[CMP_SUB_4:%.*]] = icmp sge ptr [[DST_SUB_4]], [[LOWER]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]] ; CHECK-NEXT: ret i1 [[RES_2]] ; %pre = icmp sge ptr %dst, %lower call void @llvm.assume(i1 %pre) %dst.add.3 = getelementptr i8, ptr %dst, i64 3 %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.3, i64 -1 %cmp.sub.1 = icmp sge ptr %dst.sub.1, %lower %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3 %cmp.sub.3 = icmp sge ptr %dst.sub.3, %lower %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3 %dst.sub.4 = getelementptr inbounds i8, ptr %dst.add.3, i64 -4 %cmp.sub.4 = icmp sge ptr %dst.sub.4, %lower %res.2 = xor i1 %res.1, %cmp.sub.4 ret i1 %res.2 } define i1 @gep_sub_1_sge_no_inbounds(ptr %dst, ptr %lower) { ; CHECK-LABEL: @gep_sub_1_sge_no_inbounds( ; CHECK-NEXT: [[PRE:%.*]] = icmp sge ptr [[DST:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr i8, ptr [[DST]], i64 3 ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp sge ptr [[DST_SUB_1]], [[LOWER]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp sge ptr [[DST_SUB_3]], [[LOWER]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]] ; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -4 ; CHECK-NEXT: [[CMP_SUB_4:%.*]] = icmp sge ptr [[DST_SUB_4]], [[LOWER]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]] ; CHECK-NEXT: ret i1 [[RES_2]] ; %pre = icmp sge ptr %dst, %lower call void @llvm.assume(i1 %pre) %dst.add.3 = getelementptr i8, ptr %dst, i64 3 %dst.sub.1 = getelementptr i8, ptr %dst.add.3, i64 -1 %cmp.sub.1 = icmp sge ptr %dst.sub.1, %lower %dst.sub.3 = getelementptr i8, ptr %dst.add.3, i64 -3 %cmp.sub.3 = icmp sge ptr %dst.sub.3, %lower %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3 %dst.sub.4 = getelementptr i8, ptr %dst.add.3, i64 -4 %cmp.sub.4 = icmp sge ptr %dst.sub.4, %lower %res.2 = xor i1 %res.1, %cmp.sub.4 ret i1 %res.2 } define i1 @gep_sub_1_slt(ptr %dst, ptr %upper) { ; CHECK-LABEL: @gep_sub_1_slt( ; CHECK-NEXT: [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 4 ; CHECK-NEXT: [[PRE:%.*]] = icmp slt ptr [[DST_ADD_4]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3 ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp slt ptr [[DST_SUB_3]], [[UPPER]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]] ; CHECK-NEXT: ret i1 [[RES_1]] ; %dst.add.4 = getelementptr inbounds i8, ptr %dst, i64 4 %pre = icmp slt ptr %dst.add.4, %upper call void @llvm.assume(i1 %pre) %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3 %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.3, i64 -1 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3 %cmp.sub.3 = icmp slt ptr %dst.sub.3, %upper %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3 ret i1 %res.1 } define i1 @gep_sub_slt_var_idx(ptr %dst, ptr %upper, i8 %idx) { ; CHECK-LABEL: @gep_sub_slt_var_idx( ; CHECK-NEXT: [[NOT_ZERO:%.*]] = icmp ne i8 [[IDX:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT_ZERO]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[PRE:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER]] ; CHECK-NEXT: [[DST_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -2 ; CHECK-NEXT: [[CMP_SUB_2:%.*]] = icmp slt ptr [[DST_SUB_2]], [[UPPER]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_2]] ; CHECK-NEXT: [[DST_SUB_1_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_SUB_1]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1_SUB_1]], [[UPPER]] ; CHECK-NEXT: [[CMP_SUB_1_SUB_1_EQ:%.*]] = icmp eq ptr [[DST_SUB_1_SUB_1]], [[DST_SUB_2]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_1_SUB_1]] ; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], [[CMP_SUB_1_SUB_1_EQ]] ; CHECK-NEXT: ret i1 [[RES_3]] ; %not.zero = icmp ne i8 %idx, 0 call void @llvm.assume(i1 %not.zero) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext %pre = icmp slt ptr %dst.add.idx, %upper call void @llvm.assume(i1 %pre) %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -1 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper %dst.sub.2 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -2 %cmp.sub.2 = icmp slt ptr %dst.sub.2, %upper %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2 %dst.sub.1.sub.1 = getelementptr inbounds i8, ptr %dst.sub.1, i64 -1 %cmp.sub.1.sub.1 = icmp slt ptr %dst.sub.1.sub.1, %upper %cmp.sub.1.sub.1.eq = icmp eq ptr %dst.sub.1.sub.1, %dst.sub.2 %res.2 = xor i1 %res.1, %cmp.sub.1.sub.1 %res.3 = xor i1 %res.2, %cmp.sub.1.sub.1.eq ret i1 %res.3 } define i1 @gep_sub_slt_var_idx_sgt_1(ptr %dst, ptr %upper, i8 %idx) { ; CHECK-LABEL: @gep_sub_slt_var_idx_sgt_1( ; CHECK-NEXT: [[SGT_1:%.*]] = icmp sgt i8 [[IDX:%.*]], 1 ; CHECK-NEXT: call void @llvm.assume(i1 [[SGT_1]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[PRE:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER]] ; CHECK-NEXT: [[DST_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -2 ; CHECK-NEXT: [[CMP_SUB_2:%.*]] = icmp slt ptr [[DST_SUB_2]], [[UPPER]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_2]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp slt ptr [[DST_SUB_3]], [[UPPER]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]] ; CHECK-NEXT: ret i1 [[RES_2]] ; %sgt.1 = icmp sgt i8 %idx, 1 call void @llvm.assume(i1 %sgt.1) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext %pre = icmp slt ptr %dst.add.idx, %upper call void @llvm.assume(i1 %pre) %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -1 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper %dst.sub.2 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -2 %cmp.sub.2 = icmp slt ptr %dst.sub.2, %upper %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2 %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -3 %cmp.sub.3 = icmp slt ptr %dst.sub.3, %upper %res.2 = xor i1 %res.1, %cmp.sub.3 ret i1 %res.2 } define i1 @gep_sub_1_slt_var_idx_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) { ; CHECK-LABEL: @gep_sub_1_slt_var_idx_inbounds( ; CHECK-NEXT: [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT_ZERO]]) ; CHECK-NEXT: [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16 ; CHECK-NEXT: [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]] ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]]) ; CHECK-NEXT: [[CMP_IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_SLT_LEN]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[CMP_IDX:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER]] ; CHECK-NEXT: ret i1 [[CMP_IDX]] ; %not.zero = icmp ne i8 %len, 0 call void @llvm.assume(i1 %not.zero) %len.ext = zext i8 %len to i16 %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -1 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper call void @llvm.assume(i1 %cmp.sub.1) %cmp.idx.slt.len = icmp slt i8 %idx, %len call void @llvm.assume(i1 %cmp.idx.slt.len) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext %cmp.idx = icmp slt ptr %dst.add.idx, %upper ret i1 %cmp.idx } define i1 @gep_sub_1_slt_var_idx_only_inner_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) { ; CHECK-LABEL: @gep_sub_1_slt_var_idx_only_inner_inbounds( ; CHECK-NEXT: [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT_ZERO]]) ; CHECK-NEXT: [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16 ; CHECK-NEXT: [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]] ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_LEN]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]]) ; CHECK-NEXT: [[CMP_IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_SLT_LEN]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[CMP_IDX:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER]] ; CHECK-NEXT: ret i1 [[CMP_IDX]] ; %not.zero = icmp ne i8 %len, 0 call void @llvm.assume(i1 %not.zero) %len.ext = zext i8 %len to i16 %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext %dst.sub.1 = getelementptr i8, ptr %dst.add.len, i64 -1 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper call void @llvm.assume(i1 %cmp.sub.1) %cmp.idx.slt.len = icmp slt i8 %idx, %len call void @llvm.assume(i1 %cmp.idx.slt.len) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext %cmp.idx = icmp slt ptr %dst.add.idx, %upper ret i1 %cmp.idx } define i1 @gep_sub_1_slt_var_idx_no_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) { ; CHECK-LABEL: @gep_sub_1_slt_var_idx_no_inbounds( ; CHECK-NEXT: [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT_ZERO]]) ; CHECK-NEXT: [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16 ; CHECK-NEXT: [[DST_ADD_LEN:%.*]] = getelementptr i8, ptr [[DST:%.*]], i16 [[LEN_EXT]] ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_LEN]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]]) ; CHECK-NEXT: [[CMP_IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_SLT_LEN]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr i8, ptr [[DST]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[CMP_IDX:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER]] ; CHECK-NEXT: ret i1 [[CMP_IDX]] ; %not.zero = icmp ne i8 %len, 0 call void @llvm.assume(i1 %not.zero) %len.ext = zext i8 %len to i16 %dst.add.len = getelementptr i8, ptr %dst, i16 %len.ext %dst.sub.1 = getelementptr i8, ptr %dst.add.len, i64 -1 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper call void @llvm.assume(i1 %cmp.sub.1) %cmp.idx.slt.len = icmp slt i8 %idx, %len call void @llvm.assume(i1 %cmp.idx.slt.len) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr i8, ptr %dst, i16 %idx.ext %cmp.idx = icmp slt ptr %dst.add.idx, %upper ret i1 %cmp.idx } define i1 @gep_sub_2_slt_var_idx(ptr %dst, ptr %upper, i8 %len, i8 %idx) { ; CHECK-LABEL: @gep_sub_2_slt_var_idx( ; CHECK-NEXT: [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[NOT_ZERO]]) ; CHECK-NEXT: [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16 ; CHECK-NEXT: [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]] ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -2 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]]) ; CHECK-NEXT: [[CMP_IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_SLT_LEN]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[CMP_IDX:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER]] ; CHECK-NEXT: ret i1 [[CMP_IDX]] ; %not.zero = icmp ne i8 %len, 0 call void @llvm.assume(i1 %not.zero) %len.ext = zext i8 %len to i16 %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -2 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper call void @llvm.assume(i1 %cmp.sub.1) %cmp.idx.slt.len = icmp slt i8 %idx, %len call void @llvm.assume(i1 %cmp.idx.slt.len) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext %cmp.idx = icmp slt ptr %dst.add.idx, %upper ret i1 %cmp.idx } define i1 @gep_sub_2_slt_var_idx_inbounds_len_sge_2(ptr %dst, ptr %upper, i8 %len, i8 %idx) { ; CHECK-LABEL: @gep_sub_2_slt_var_idx_inbounds_len_sge_2( ; CHECK-NEXT: [[SGE_2:%.*]] = icmp sge i8 [[LEN:%.*]], 2 ; CHECK-NEXT: call void @llvm.assume(i1 [[SGE_2]]) ; CHECK-NEXT: [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16 ; CHECK-NEXT: [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]] ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]]) ; CHECK-NEXT: [[CMP_IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_SLT_LEN]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[CMP_IDX:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER]] ; CHECK-NEXT: ret i1 [[CMP_IDX]] ; %sge.2 = icmp sge i8 %len, 2 call void @llvm.assume(i1 %sge.2) %len.ext = zext i8 %len to i16 %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -1 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper call void @llvm.assume(i1 %cmp.sub.1) %cmp.idx.slt.len = icmp slt i8 %idx, %len call void @llvm.assume(i1 %cmp.idx.slt.len) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext %cmp.idx = icmp slt ptr %dst.add.idx, %upper ret i1 %cmp.idx } define i1 @gep_sub_slt_var_idx_len_sgt_1(ptr %dst, ptr %upper, i8 %len, i8 %idx) { ; CHECK-LABEL: @gep_sub_slt_var_idx_len_sgt_1( ; CHECK-NEXT: [[SGT_1:%.*]] = icmp sgt i8 [[LEN:%.*]], 1 ; CHECK-NEXT: call void @llvm.assume(i1 [[SGT_1]]) ; CHECK-NEXT: [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16 ; CHECK-NEXT: [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]] ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -2 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp slt ptr [[DST_SUB_1]], [[UPPER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]]) ; CHECK-NEXT: [[CMP_IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN]] ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_SLT_LEN]]) ; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16 ; CHECK-NEXT: [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]] ; CHECK-NEXT: [[CMP_IDX:%.*]] = icmp slt ptr [[DST_ADD_IDX]], [[UPPER]] ; CHECK-NEXT: ret i1 [[CMP_IDX]] ; %sgt.1 = icmp sgt i8 %len, 1 call void @llvm.assume(i1 %sgt.1) %len.ext = zext i8 %len to i16 %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -2 %cmp.sub.1 = icmp slt ptr %dst.sub.1, %upper call void @llvm.assume(i1 %cmp.sub.1) %cmp.idx.slt.len = icmp slt i8 %idx, %len call void @llvm.assume(i1 %cmp.idx.slt.len) %idx.ext = zext i8 %idx to i16 %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext %cmp.idx = icmp slt ptr %dst.add.idx, %upper ret i1 %cmp.idx } define i1 @gep_sub_1_slt_var_idx_lower_bound(ptr %lower, ptr %src, i8 %len) { ; CHECK-LABEL: @gep_sub_1_slt_var_idx_lower_bound( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SRC_SGE_LOWER:%.*]] = icmp sge ptr [[SRC:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[SRC_SGE_LOWER]]) ; CHECK-NEXT: [[LEN_POS:%.*]] = icmp sge i8 [[LEN:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_POS]]) ; CHECK-NEXT: [[GEP_LEN:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[LEN]] ; CHECK-NEXT: [[GEP_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[GEP_LEN]], i8 -1 ; CHECK-NEXT: [[RES:%.*]] = icmp slt ptr [[GEP_SUB_1]], [[LOWER]] ; CHECK-NEXT: ret i1 [[RES]] ; entry: %src.sge.lower = icmp sge ptr %src, %lower call void @llvm.assume(i1 %src.sge.lower) %len.pos = icmp sge i8 %len, 0 call void @llvm.assume(i1 %len.pos) %gep.len = getelementptr inbounds i8, ptr %src, i8 %len %gep.sub.1 = getelementptr inbounds i8, ptr %gep.len, i8 -1 %res = icmp slt ptr %gep.sub.1, %lower ret i1 %res } define i1 @gep_sub_1_slt_var_idx_lower_bound_len_ne_0(ptr %lower, ptr %src, i8 %len) { ; CHECK-LABEL: @gep_sub_1_slt_var_idx_lower_bound_len_ne_0( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN_NE_0:%.*]] = icmp ne i8 [[LEN:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_NE_0]]) ; CHECK-NEXT: [[SRC_SGE_LOWER:%.*]] = icmp sge ptr [[SRC:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[SRC_SGE_LOWER]]) ; CHECK-NEXT: [[LEN_POS:%.*]] = icmp sge i8 [[LEN]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_POS]]) ; CHECK-NEXT: [[GEP_LEN:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[LEN]] ; CHECK-NEXT: [[GEP_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[GEP_LEN]], i8 -1 ; CHECK-NEXT: [[RES:%.*]] = icmp slt ptr [[GEP_SUB_1]], [[LOWER]] ; CHECK-NEXT: ret i1 [[RES]] ; entry: %len.ne.0 = icmp ne i8 %len, 0 call void @llvm.assume(i1 %len.ne.0) %src.sge.lower = icmp sge ptr %src, %lower call void @llvm.assume(i1 %src.sge.lower) %len.pos = icmp sge i8 %len, 0 call void @llvm.assume(i1 %len.pos) %gep.len = getelementptr inbounds i8, ptr %src, i8 %len %gep.sub.1 = getelementptr inbounds i8, ptr %gep.len, i8 -1 %res = icmp slt ptr %gep.sub.1, %lower ret i1 %res } define i1 @gep_sub_2_slt_var_idx_lower_bound_len_ne_0(ptr %lower, ptr %src, i8 %len) { ; CHECK-LABEL: @gep_sub_2_slt_var_idx_lower_bound_len_ne_0( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN_NE_0:%.*]] = icmp ne i8 [[LEN:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_NE_0]]) ; CHECK-NEXT: [[SRC_SGE_LOWER:%.*]] = icmp sge ptr [[SRC:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[SRC_SGE_LOWER]]) ; CHECK-NEXT: [[LEN_POS:%.*]] = icmp sge i8 [[LEN]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_POS]]) ; CHECK-NEXT: [[GEP_LEN:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[LEN]] ; CHECK-NEXT: [[GEP_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[GEP_LEN]], i8 -2 ; CHECK-NEXT: [[RES:%.*]] = icmp slt ptr [[GEP_SUB_2]], [[LOWER]] ; CHECK-NEXT: ret i1 [[RES]] ; entry: %len.ne.0 = icmp ne i8 %len, 0 call void @llvm.assume(i1 %len.ne.0) %src.sge.lower = icmp sge ptr %src, %lower call void @llvm.assume(i1 %src.sge.lower) %len.pos = icmp sge i8 %len, 0 call void @llvm.assume(i1 %len.pos) %gep.len = getelementptr inbounds i8, ptr %src, i8 %len %gep.sub.2 = getelementptr inbounds i8, ptr %gep.len, i8 -2 %res = icmp slt ptr %gep.sub.2, %lower ret i1 %res } define i1 @gep_i16_sub_1_sge_inbounds(ptr %dst, ptr %lower) { ; CHECK-LABEL: @gep_i16_sub_1_sge_inbounds( ; CHECK-NEXT: [[PRE:%.*]] = icmp sge ptr [[DST:%.*]], [[LOWER:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3 ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp sle ptr [[DST_SUB_1]], [[LOWER]] ; CHECK-NEXT: [[DST_SUB_2:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -2 ; CHECK-NEXT: [[CMP_SUB_2:%.*]] = icmp sle ptr [[DST_SUB_2]], [[DST]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_2]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp sle ptr [[DST_SUB_3]], [[LOWER]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]] ; CHECK-NEXT: ret i1 [[RES_2]] ; %pre = icmp sge ptr %dst, %lower call void @llvm.assume(i1 %pre) %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3 %dst.sub.1 = getelementptr inbounds i16, ptr %dst.add.3, i64 -1 %cmp.sub.1 = icmp sle ptr %dst.sub.1, %lower %dst.sub.2 = getelementptr inbounds i16, ptr %dst.add.3, i64 -2 %cmp.sub.2 = icmp sle ptr %dst.sub.2, %dst %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2 %dst.sub.3 = getelementptr inbounds i16, ptr %dst.add.3, i64 -3 %cmp.sub.3 = icmp sle ptr %dst.sub.3, %lower %res.2 = xor i1 %res.1, %cmp.sub.3 ret i1 %res.2 } define i1 @gep_i16_sub_1_sge_inbounds_var_idx(ptr %dst, i64 %off) { ; CHECK-LABEL: @gep_i16_sub_1_sge_inbounds_var_idx( ; CHECK-NEXT: [[OFF_SGE:%.*]] = icmp sge i64 [[OFF:%.*]], 1 ; CHECK-NEXT: call void @llvm.assume(i1 [[OFF_SGE]]) ; CHECK-NEXT: [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 [[OFF]] ; CHECK-NEXT: [[DST_SUB_1:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i32 -1 ; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp sle ptr [[DST_SUB_1]], [[DST]] ; CHECK-NEXT: [[DST_SUB_2:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -2 ; CHECK-NEXT: [[CMP_SUB_2:%.*]] = icmp sle ptr [[DST_SUB_2]], [[DST]] ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_2]] ; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -3 ; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp sle ptr [[DST_SUB_3]], [[DST]] ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]] ; CHECK-NEXT: ret i1 [[RES_2]] ; %off.sge = icmp sge i64 %off, 1 call void @llvm.assume(i1 %off.sge) %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 %off %dst.sub.1 = getelementptr inbounds i16, ptr %dst.add.3, i32 -1 %cmp.sub.1 = icmp sle ptr %dst.sub.1, %dst %dst.sub.2 = getelementptr inbounds i16, ptr %dst.add.3, i64 -2 %cmp.sub.2 = icmp sle ptr %dst.sub.2, %dst %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2 %dst.sub.3 = getelementptr inbounds i16, ptr %dst.add.3, i64 -3 %cmp.sub.3 = icmp sle ptr %dst.sub.3, %dst %res.2 = xor i1 %res.1, %cmp.sub.3 ret i1 %res.2 }