
Move GEP offset collection to separate helper function and collect variable and constant offsets in OffsetResult. For now, this only supports 1 VariableOffset, but the new code structure can be more easily extended to handle more offsets in the future. The refactoring drops the check that the VariableOffset >= -1 * constant offset. This is not needed to check whether the constraint is monotonically increasing. The constant factors can be ignored, the constraint will be monotonically increasing if all variables are positive. See https://alive2.llvm.org/ce/z/ah2uSQ, https://alive2.llvm.org/ce/z/NCADNZ
639 lines
31 KiB
LLVM
639 lines
31 KiB
LLVM
; 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_uge_inbounds(ptr %dst, ptr %lower) {
|
|
; CHECK-LABEL: @gep_sub_1_uge_inbounds(
|
|
; CHECK-NEXT: [[PRE:%.*]] = icmp uge 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: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -4
|
|
; CHECK-NEXT: [[CMP_SUB_4:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
;
|
|
%pre = icmp uge 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 uge ptr %dst.sub.1, %lower
|
|
%dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3
|
|
%cmp.sub.3 = icmp uge 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 uge ptr %dst.sub.4, %lower
|
|
%res.2 = xor i1 %res.1, %cmp.sub.4
|
|
ret i1 %res.2
|
|
}
|
|
|
|
define i1 @gep_sub_1_uge_only_inner_inbounds(ptr %dst, ptr %lower) {
|
|
; CHECK-LABEL: @gep_sub_1_uge_only_inner_inbounds(
|
|
; CHECK-NEXT: [[PRE:%.*]] = icmp uge 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 uge ptr [[DST_SUB_1]], [[LOWER]]
|
|
; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -3
|
|
; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp uge 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 uge ptr [[DST_SUB_4]], [[LOWER]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
;
|
|
%pre = icmp uge 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 uge ptr %dst.sub.1, %lower
|
|
%dst.sub.3 = getelementptr i8, ptr %dst.add.3, i64 -3
|
|
%cmp.sub.3 = icmp uge 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 uge ptr %dst.sub.4, %lower
|
|
%res.2 = xor i1 %res.1, %cmp.sub.4
|
|
ret i1 %res.2
|
|
}
|
|
|
|
define i1 @gep_sub_1_uge_only_outer_inbounds(ptr %dst, ptr %lower) {
|
|
; CHECK-LABEL: @gep_sub_1_uge_only_outer_inbounds(
|
|
; CHECK-NEXT: [[PRE:%.*]] = icmp uge 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 uge 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 uge 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 uge ptr [[DST_SUB_4]], [[LOWER]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
;
|
|
%pre = icmp uge 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 uge ptr %dst.sub.1, %lower
|
|
%dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3
|
|
%cmp.sub.3 = icmp uge 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 uge ptr %dst.sub.4, %lower
|
|
%res.2 = xor i1 %res.1, %cmp.sub.4
|
|
ret i1 %res.2
|
|
}
|
|
|
|
define i1 @gep_sub_1_uge_no_inbounds(ptr %dst, ptr %lower) {
|
|
; CHECK-LABEL: @gep_sub_1_uge_no_inbounds(
|
|
; CHECK-NEXT: [[PRE:%.*]] = icmp uge 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 uge ptr [[DST_SUB_1]], [[LOWER]]
|
|
; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -3
|
|
; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp uge 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 uge ptr [[DST_SUB_4]], [[LOWER]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
;
|
|
%pre = icmp uge 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 uge ptr %dst.sub.1, %lower
|
|
%dst.sub.3 = getelementptr i8, ptr %dst.add.3, i64 -3
|
|
%cmp.sub.3 = icmp uge 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 uge ptr %dst.sub.4, %lower
|
|
%res.2 = xor i1 %res.1, %cmp.sub.4
|
|
ret i1 %res.2
|
|
}
|
|
|
|
define i1 @gep_sub_1_ult(ptr %dst, ptr %upper) {
|
|
; CHECK-LABEL: @gep_sub_1_ult(
|
|
; CHECK-NEXT: [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 4
|
|
; CHECK-NEXT: [[PRE:%.*]] = icmp ult 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: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: ret i1 [[RES_1]]
|
|
;
|
|
%dst.add.4 = getelementptr inbounds i8, ptr %dst, i64 4
|
|
%pre = icmp ult 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 ult ptr %dst.sub.1, %upper
|
|
%dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3
|
|
%cmp.sub.3 = icmp ult ptr %dst.sub.3, %upper
|
|
%res.1 = xor i1 %cmp.sub.1, %cmp.sub.3
|
|
ret i1 %res.1
|
|
}
|
|
|
|
define i1 @gep_sub_ult_var_idx(ptr %dst, ptr %upper, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_ult_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 ult 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: [[DST_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -2
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: [[DST_SUB_1_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_SUB_1]], i64 -1
|
|
; CHECK-NEXT: [[CMP_SUB_1_SUB_1:%.*]] = icmp ult 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 ult 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 ult ptr %dst.sub.1, %upper
|
|
%dst.sub.2 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -2
|
|
%cmp.sub.2 = icmp ult 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 ult 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_ult_var_idx_sgt_1(ptr %dst, ptr %upper, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_ult_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 ult 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: [[DST_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -2
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -3
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true
|
|
; 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 ult 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 ult ptr %dst.sub.1, %upper
|
|
%dst.sub.2 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -2
|
|
%cmp.sub.2 = icmp ult 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 ult ptr %dst.sub.3, %upper
|
|
%res.2 = xor i1 %res.1, %cmp.sub.3
|
|
ret i1 %res.2
|
|
}
|
|
|
|
define i1 @gep_sub_1_ult_var_idx_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_1_ult_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 ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]])
|
|
; CHECK-NEXT: [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_ULT_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: ret i1 true
|
|
;
|
|
%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 ult ptr %dst.sub.1, %upper
|
|
call void @llvm.assume(i1 %cmp.sub.1)
|
|
%cmp.idx.ult.len = icmp ult i8 %idx, %len
|
|
call void @llvm.assume(i1 %cmp.idx.ult.len)
|
|
%idx.ext = zext i8 %idx to i16
|
|
%dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
|
|
%cmp.idx = icmp ult ptr %dst.add.idx, %upper
|
|
ret i1 %cmp.idx
|
|
}
|
|
|
|
define i1 @gep_sub_1_ult_var_idx_only_inner_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_1_ult_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 ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]])
|
|
; CHECK-NEXT: [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_ULT_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 ult 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 ult ptr %dst.sub.1, %upper
|
|
call void @llvm.assume(i1 %cmp.sub.1)
|
|
%cmp.idx.ult.len = icmp ult i8 %idx, %len
|
|
call void @llvm.assume(i1 %cmp.idx.ult.len)
|
|
%idx.ext = zext i8 %idx to i16
|
|
%dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
|
|
%cmp.idx = icmp ult ptr %dst.add.idx, %upper
|
|
ret i1 %cmp.idx
|
|
}
|
|
|
|
define i1 @gep_sub_1_ult_var_idx_no_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_1_ult_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 ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]])
|
|
; CHECK-NEXT: [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_ULT_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 ult 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 ult ptr %dst.sub.1, %upper
|
|
call void @llvm.assume(i1 %cmp.sub.1)
|
|
%cmp.idx.ult.len = icmp ult i8 %idx, %len
|
|
call void @llvm.assume(i1 %cmp.idx.ult.len)
|
|
%idx.ext = zext i8 %idx to i16
|
|
%dst.add.idx = getelementptr i8, ptr %dst, i16 %idx.ext
|
|
%cmp.idx = icmp ult ptr %dst.add.idx, %upper
|
|
ret i1 %cmp.idx
|
|
}
|
|
|
|
define i1 @gep_sub_2_ult_var_idx(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_2_ult_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 ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]])
|
|
; CHECK-NEXT: [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_ULT_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 ult 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 ult ptr %dst.sub.1, %upper
|
|
call void @llvm.assume(i1 %cmp.sub.1)
|
|
%cmp.idx.ult.len = icmp ult i8 %idx, %len
|
|
call void @llvm.assume(i1 %cmp.idx.ult.len)
|
|
%idx.ext = zext i8 %idx to i16
|
|
%dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
|
|
%cmp.idx = icmp ult ptr %dst.add.idx, %upper
|
|
ret i1 %cmp.idx
|
|
}
|
|
|
|
define i1 @gep_sub_2_ult_var_idx_inbounds_len_sge_2(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_2_ult_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 ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]])
|
|
; CHECK-NEXT: [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_ULT_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: ret i1 true
|
|
;
|
|
%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 ult ptr %dst.sub.1, %upper
|
|
call void @llvm.assume(i1 %cmp.sub.1)
|
|
%cmp.idx.ult.len = icmp ult i8 %idx, %len
|
|
call void @llvm.assume(i1 %cmp.idx.ult.len)
|
|
%idx.ext = zext i8 %idx to i16
|
|
%dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
|
|
%cmp.idx = icmp ult ptr %dst.add.idx, %upper
|
|
ret i1 %cmp.idx
|
|
}
|
|
|
|
define i1 @gep_sub_2_ult_var_idx_inbounds_len_uge_2(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_2_ult_var_idx_inbounds_len_uge_2(
|
|
; CHECK-NEXT: [[UGE_2:%.*]] = icmp uge i8 [[LEN:%.*]], 2
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[UGE_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 ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]])
|
|
; CHECK-NEXT: [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_ULT_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: ret i1 true
|
|
;
|
|
%uge.2 = icmp uge i8 %len, 2
|
|
call void @llvm.assume(i1 %uge.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 ult ptr %dst.sub.1, %upper
|
|
call void @llvm.assume(i1 %cmp.sub.1)
|
|
%cmp.idx.ult.len = icmp ult i8 %idx, %len
|
|
call void @llvm.assume(i1 %cmp.idx.ult.len)
|
|
%idx.ext = zext i8 %idx to i16
|
|
%dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
|
|
%cmp.idx = icmp ult ptr %dst.add.idx, %upper
|
|
ret i1 %cmp.idx
|
|
}
|
|
|
|
define i1 @gep_sub_ult_var_idx_len_sgt_1(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
|
|
; CHECK-LABEL: @gep_sub_ult_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 ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_SUB_1]])
|
|
; CHECK-NEXT: [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_IDX_ULT_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 ult 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 ult ptr %dst.sub.1, %upper
|
|
call void @llvm.assume(i1 %cmp.sub.1)
|
|
%cmp.idx.ult.len = icmp ult i8 %idx, %len
|
|
call void @llvm.assume(i1 %cmp.idx.ult.len)
|
|
%idx.ext = zext i8 %idx to i16
|
|
%dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
|
|
%cmp.idx = icmp ult ptr %dst.add.idx, %upper
|
|
ret i1 %cmp.idx
|
|
}
|
|
|
|
define i1 @gep_sub_1_ult_var_idx_lower_bound(ptr %lower, ptr %src, i8 %len) {
|
|
; CHECK-LABEL: @gep_sub_1_ult_var_idx_lower_bound(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[SRC_UGE_LOWER:%.*]] = icmp uge ptr [[SRC:%.*]], [[LOWER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[SRC_UGE_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 ult ptr [[GEP_SUB_1]], [[LOWER]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
entry:
|
|
%src.uge.lower = icmp uge ptr %src, %lower
|
|
call void @llvm.assume(i1 %src.uge.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 ult ptr %gep.sub.1, %lower
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @gep_sub_1_ult_var_idx_lower_bound_len_ne_0(ptr %lower, ptr %src, i8 %len) {
|
|
; CHECK-LABEL: @gep_sub_1_ult_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_UGE_LOWER:%.*]] = icmp uge ptr [[SRC:%.*]], [[LOWER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[SRC_UGE_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: ret i1 false
|
|
;
|
|
entry:
|
|
%len.ne.0 = icmp ne i8 %len, 0
|
|
call void @llvm.assume(i1 %len.ne.0)
|
|
|
|
%src.uge.lower = icmp uge ptr %src, %lower
|
|
call void @llvm.assume(i1 %src.uge.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 ult ptr %gep.sub.1, %lower
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @gep_sub_2_ult_var_idx_lower_bound_len_ne_0(ptr %lower, ptr %src, i8 %len) {
|
|
; CHECK-LABEL: @gep_sub_2_ult_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_UGE_LOWER:%.*]] = icmp uge ptr [[SRC:%.*]], [[LOWER:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[SRC_UGE_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 ult 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.uge.lower = icmp uge ptr %src, %lower
|
|
call void @llvm.assume(i1 %src.uge.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 ult ptr %gep.sub.2, %lower
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @gep_i16_sub_1_uge_inbounds(ptr %dst, ptr %lower) {
|
|
; CHECK-LABEL: @gep_i16_sub_1_uge_inbounds(
|
|
; CHECK-NEXT: [[PRE:%.*]] = icmp uge 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: [[DST_SUB_2:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -2
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 false, true
|
|
; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -3
|
|
; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp ule ptr [[DST_SUB_3]], [[LOWER]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
;
|
|
%pre = icmp uge 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 ule ptr %dst.sub.1, %lower
|
|
%dst.sub.2 = getelementptr inbounds i16, ptr %dst.add.3, i64 -2
|
|
%cmp.sub.2 = icmp ule 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 ule ptr %dst.sub.3, %lower
|
|
%res.2 = xor i1 %res.1, %cmp.sub.3
|
|
ret i1 %res.2
|
|
}
|
|
|
|
define i1 @gep_i16_sub_1_uge_inbounds_var_idx(ptr %dst, i64 %off) {
|
|
; CHECK-LABEL: @gep_i16_sub_1_uge_inbounds_var_idx(
|
|
; CHECK-NEXT: [[OFF_UGE:%.*]] = icmp sge i64 [[OFF:%.*]], 1
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[OFF_UGE]])
|
|
; 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 ule 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 ule 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 ule ptr [[DST_SUB_3]], [[DST]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
;
|
|
%off.uge = icmp sge i64 %off, 1
|
|
call void @llvm.assume(i1 %off.uge)
|
|
%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 ule ptr %dst.sub.1, %dst
|
|
%dst.sub.2 = getelementptr inbounds i16, ptr %dst.add.3, i64 -2
|
|
%cmp.sub.2 = icmp ule 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 ule ptr %dst.sub.3, %dst
|
|
%res.2 = xor i1 %res.1, %cmp.sub.3
|
|
ret i1 %res.2
|
|
}
|
|
|
|
define i1 @gep_i32_two_indices_known_lt_and_positive(ptr %a, i8 %idx.1, i8 %idx.2) {
|
|
; CHECK-LABEL: @gep_i32_two_indices_known_lt_and_positive(
|
|
; CHECK-NEXT: [[LT:%.*]] = icmp ult i8 [[IDX_1:%.*]], [[IDX_2:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[LT]])
|
|
; CHECK-NEXT: [[IDX_1_POS:%.*]] = icmp sge i8 [[IDX_1]], 0
|
|
; CHECK-NEXT: [[IDX_2_POS:%.*]] = icmp sge i8 [[IDX_2]], 0
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_1_POS]])
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_2_POS]])
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i8 [[IDX_1]]
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i32, ptr [[GEP_1]], i8 -3
|
|
; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_2]]
|
|
; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr inbounds i32, ptr [[GEP_3]], i8 -3
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%lt = icmp ult i8 %idx.1, %idx.2
|
|
call void @llvm.assume(i1 %lt)
|
|
%idx.1.pos = icmp sge i8 %idx.1, 0
|
|
%idx.2.pos = icmp sge i8 %idx.2, 0
|
|
call void @llvm.assume(i1 %idx.1.pos)
|
|
call void @llvm.assume(i1 %idx.2.pos)
|
|
%gep.1 = getelementptr inbounds i32, ptr %a, i8 %idx.1
|
|
%gep.2 = getelementptr inbounds i32, ptr %gep.1, i8 -3
|
|
%gep.3 = getelementptr inbounds i32, ptr %a, i8 %idx.2
|
|
%gep.4 = getelementptr inbounds i32, ptr %gep.3, i8 -3
|
|
%c = icmp ult ptr %gep.2, %gep.4
|
|
ret i1 %c
|
|
}
|
|
|
|
define i1 @gep_i32_two_indices_known_lt_and_not_known_positive(ptr %a, i8 %idx.1, i8 %idx.2) {
|
|
; CHECK-LABEL: @gep_i32_two_indices_known_lt_and_not_known_positive(
|
|
; CHECK-NEXT: [[LT:%.*]] = icmp ult i8 [[IDX_1:%.*]], [[IDX_2:%.*]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[LT]])
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i8 [[IDX_1]]
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i32, ptr [[GEP_1]], i8 -3
|
|
; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_2]]
|
|
; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr inbounds i32, ptr [[GEP_3]], i8 -3
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[GEP_2]], [[GEP_4]]
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
;
|
|
%lt = icmp ult i8 %idx.1, %idx.2
|
|
call void @llvm.assume(i1 %lt)
|
|
%gep.1 = getelementptr inbounds i32, ptr %a, i8 %idx.1
|
|
%gep.2 = getelementptr inbounds i32, ptr %gep.1, i8 -3
|
|
%gep.3 = getelementptr inbounds i32, ptr %a, i8 %idx.2
|
|
%gep.4 = getelementptr inbounds i32, ptr %gep.3, i8 -3
|
|
%c = icmp ult ptr %gep.2, %gep.4
|
|
ret i1 %c
|
|
}
|
|
|
|
define i1 @gep_i32_two_indices_known_positive_but_not_lt(ptr %a, i8 %idx.1, i8 %idx.2) {
|
|
; CHECK-LABEL: @gep_i32_two_indices_known_positive_but_not_lt(
|
|
; CHECK-NEXT: [[IDX_1_POS:%.*]] = icmp sge i8 [[IDX_1:%.*]], 0
|
|
; CHECK-NEXT: [[IDX_2_POS:%.*]] = icmp sge i8 [[IDX_2:%.*]], 0
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_1_POS]])
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_2_POS]])
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i8 [[IDX_1]]
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i32, ptr [[GEP_1]], i8 -3
|
|
; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_2]]
|
|
; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr inbounds i32, ptr [[GEP_3]], i8 -3
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[GEP_2]], [[GEP_4]]
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
;
|
|
%idx.1.pos = icmp sge i8 %idx.1, 0
|
|
%idx.2.pos = icmp sge i8 %idx.2, 0
|
|
call void @llvm.assume(i1 %idx.1.pos)
|
|
call void @llvm.assume(i1 %idx.2.pos)
|
|
%gep.1 = getelementptr inbounds i32, ptr %a, i8 %idx.1
|
|
%gep.2 = getelementptr inbounds i32, ptr %gep.1, i8 -3
|
|
%gep.3 = getelementptr inbounds i32, ptr %a, i8 %idx.2
|
|
%gep.4 = getelementptr inbounds i32, ptr %gep.3, i8 -3
|
|
%c = icmp ult ptr %gep.2, %gep.4
|
|
ret i1 %c
|
|
}
|